Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#10 add fixtures #13

Merged
merged 58 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
cebd3a3
#10: Added pytest fixtures for usage in integration tests of externa…
ckunki May 17, 2024
ef423fe
Merge branch 'main' into feature/#10-add_fixtures
ckunki May 17, 2024
8121b53
Apply suggestions from code review
ckunki May 17, 2024
6190da3
Use pyyaml for reading project short tag from error_code_config.yml
ckunki May 22, 2024
6c76a2c
Use pyyaml for reading project short tag from error_code_config.yml
ckunki May 22, 2024
6f48ebd
Fixed review findings
ckunki May 22, 2024
bc72a63
Abort shellscript in just file on errors
ckunki May 22, 2024
37198fe
Added secrets for integration tests
ckunki May 22, 2024
1e76646
Replaced bash script in justfile by python
ckunki May 22, 2024
b68d9f2
Separated long running test cases
ckunki May 22, 2024
cc9ecbb
Separated long running test cases
ckunki May 22, 2024
549f201
Separated long running test cases
ckunki May 22, 2024
24a82d9
Fixed if statement in github worflow
ckunki May 22, 2024
e83d749
Fixed if statement in github worflow
ckunki May 22, 2024
5f89ffe
Experiment event
ckunki May 22, 2024
bdd3eb5
Update ci.yml
ckunki May 22, 2024
f20e225
Update ci.yml
ckunki May 22, 2024
70eb743
Update ci.yml
ckunki May 22, 2024
7d81626
move commit message to input
ckunki May 22, 2024
184ea40
move commit message to input
ckunki May 22, 2024
64db909
experiment 1
ckunki May 22, 2024
9c88ed6
experiment 2
ckunki May 22, 2024
ada2d32
experiment 3
ckunki May 22, 2024
5a847d5
experiment 4
ckunki May 22, 2024
e1bf00e
experiment 5
ckunki May 22, 2024
e3519aa
experiment 6
ckunki May 22, 2024
18cdc24
experiment 7
ckunki May 22, 2024
f38ee40
experiment 8
ckunki May 22, 2024
71e8b4c
experiment 9
ckunki May 22, 2024
615b4a4
experiment 10
ckunki May 22, 2024
08c0a65
experiment 11
ckunki May 22, 2024
e9d1e7d
experiment 12
ckunki May 22, 2024
68b4c98
experiment 13
ckunki May 22, 2024
7edd50e
experiment 14
ckunki May 22, 2024
9c5964d
experiment 15
ckunki May 22, 2024
292b7f6
experiment 16
ckunki May 22, 2024
4df961a
experiment 17
ckunki May 22, 2024
00dcb79
experiment 18
ckunki May 22, 2024
e1b57b4
experiment 19
ckunki May 22, 2024
ec5240f
experiment 20
ckunki May 22, 2024
e676eef
experiment 21
ckunki May 22, 2024
191d7ee
experiment 22
ckunki May 22, 2024
164ba41
experiment 23
ckunki May 22, 2024
997f4d5
Apply suggestions from code review
ckunki May 22, 2024
9df4d15
clean up
ckunki May 22, 2024
6125dcd
Added developer instructions
ckunki May 22, 2024
ff1d2b1
Added pytest marker "slow" to pytest-itde, too
ckunki May 22, 2024
58e8c6b
May 23rd workflow experiment 1
ckunki May 23, 2024
533fc15
May 23rd workflow experiment 2
ckunki May 23, 2024
4490332
May 23rd workflow experiment 3
ckunki May 23, 2024
013645b
May 23rd workflow experiment 4
ckunki May 23, 2024
f677941
May 23rd workflow experiment 5
ckunki May 23, 2024
a846e91
May 23rd workflow experiment 6
ckunki May 23, 2024
3a77020
May 23rd workflow experiment 7
ckunki May 23, 2024
28efea4
Changed workflows to use input instead of commit messages
ckunki May 23, 2024
b8d654b
Updated README file
ckunki May 23, 2024
6456608
Reverted separation of slow tests
ckunki May 27, 2024
99bca15
Updated README
ckunki May 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Continues Integration (Master)
name: Continuous Integration (Main)

on:
workflow_dispatch:
Expand All @@ -13,3 +13,6 @@ jobs:

CI:
uses: ./.github/workflows/ci.yml
secrets: inherit
with:
slow-tests: true
5 changes: 4 additions & 1 deletion .github/workflows/ci-pr.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Continues Integration (PR)
name: Continuous Integration (PR)

on:
pull_request:
Expand All @@ -7,3 +7,6 @@ jobs:

CI:
uses: ./.github/workflows/ci.yml
secrets: inherit
with:
slow-tests: true
22 changes: 19 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ name: CI

on:
workflow_call:
inputs:
slow-tests:
type: boolean
required: false
default: false
secrets:
ALTERNATIVE_GITHUB_TOKEN:
required: false
Expand All @@ -13,6 +18,11 @@ jobs:
runs-on: ubuntu-20.04

steps:
- name: Set pytest markers
id: pytest-markers
if: ${{ ! inputs.slow-tests }}
run: echo slow-tests='-m "not slow"' >> "$GITHUB_OUTPUT"

- name: SCM Checkout
uses: actions/checkout@v4
with:
Expand All @@ -21,6 +31,12 @@ jobs:
- name: Setup Development Environment
uses: ./.github/actions/pytest-plugins-environment

- name: Run Tests of all plugins
run: just test

- name: Run Tests of All Plugins
run: |
echo "PYTEST_ADDOPTS = $PYTEST_ADDOPTS"
just test
env:
SAAS_HOST: ${{ secrets.INTEGRATION_TEAM_SAAS_STAGING_HOST }}
SAAS_ACCOUNT_ID: ${{ secrets.INTEGRATION_TEAM_SAAS_STAGING_ACCOUNT_ID }}
SAAS_PAT: ${{ secrets.INTEGRATION_TEAM_SAAS_STAGING_PAT }}
PYTEST_ADDOPTS: '-o log_cli=true -o log_cli_level=INFO ${{ steps.pytest-markers.outputs.slow-tests }}'
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Pytest-Plugins for Exasol

Welcome to the official repository for Exasol pytest-plugins!

This collection of plugins is designed to enhance and simplify the testing experience for projects related to Exasol.

By providing a centralized location for pytest plugins, we aim to foster collaboration, ensure consistency, and improve the quality of testing practices within the organization.

## Introduction

[pytest](https://pytest.org) is a powerful testing framework for [python](https://www.python.org), and with the help of these plugins, developers can extend its functionality to better suit the testing requirements of Exasol-related projects.

Whether you're looking to use database interactions, enhance test reporting, or streamline your testing pipeline, our plugins are here to help.

## Plugins

| Plugin | Description | PYPI |
|----------------------|----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
| `pytest-exasol-itde` | Fixture to enable simple usage with Exasol's project [ITDE](https://github.com/exasol/integration-test-docker-environment) | [pytest-exasol-itde](https://pypi.org/project/pytest-exasol-itde/) |
| `pytest-exasol-saas` | Fixture to enable simple usage with Exasol's project [saas-api-python](https://github.com/exasol/saas-api-python/) | [pytest-exasol-saas](https://pypi.org/project/pytest-exasol-saas/) |


## Installation

To ensure you're using the latest features and bug fixes, we recommend installing the plugins directly from PyPI using your preferred package manager. This approach simplifies the process of keeping your testing environment up-to-date.

For example, to install the `pytest-exasol-itde` plugin, you could use the following command:


```shell
pip install pytest-exasol-itde
```

To install a specific version of a plugin, simply specify the version number:

```shell
pip install "pytest-exasol-itde==x.y.z"
```

tkilias marked this conversation as resolved.
Show resolved Hide resolved
Replace x.y.z with the desired version number.

## Development
ckunki marked this conversation as resolved.
Show resolved Hide resolved

See [Developer Guide](doc/developer-guide.md).
55 changes: 0 additions & 55 deletions README.rst

This file was deleted.

23 changes: 23 additions & 0 deletions doc/developer-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Developer Guide Exasol pytest-plugins

## Dependencies

Before you can start developing in this workspace, please ensure you have the following tools installed either globally or at a workspace level.

* [Python](https://www.python.org)
* [Just](https://github.com/casey/just)

## Run Tests

### Slow Tests

Some of the test cases verify connecting to a SaaS database instance and
execution will take about 20 minutes.

These test cases are only executed by the following GitHub workflows
* `ci-main.yml`
* `ci-slow.yml`

Both of these workflows can be run manually, workflow `ci-main.yml` is executed automatically at the 7th day of each month.

For merging a pull request to branch `main` workflow `ci-slow.yml` needs to be run and terminate successfully.
17 changes: 12 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ default:

# Run tests for one or multiple projects within this respository
test +projects=PROJECTS:
#!/usr/bin/env bash
for p in {{projects}}; do
poetry -C ${p}/ install
poetry -C ${p}/ run nox -f ${p}/noxfile.py -s coverage
done
#!/usr/bin/env python3
import subprocess, sys
rc = 0
def run(command):
global rc
ckunki marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +11 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?
Please do not use globals, they are rarely a good idea. Only use them if you can justify it with a solid argument why there is no equivalent easy non-global alternative for the problem.

result = subprocess.run(command.split())
rc = result.returncode or rc

for p in "{{projects}}".split():
run(f"poetry -C {p}/ install")
run(f"poetry -C {p}/ run nox -f {p}/noxfile.py -s coverage")
sys.exit(rc)

# Create a release
release project version:
Expand Down
4 changes: 4 additions & 0 deletions pytest-itde/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pyexasol = "^0.25"
[tool.poetry.plugins.pytest11]
itde = "exasol.pytest_itde"

[tool.pytest.ini_options]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
]

[tool.poetry.group.dev.dependencies]
exasol-toolbox = "0.8.0"
Expand Down
40 changes: 40 additions & 0 deletions pytest-saas/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,43 @@ To install the pytest-exasol-saas plugin, you can use pip:
```shell
pip install pytest-exasol-saas
```

## Database Instances

### Using an Existing Database Instance

By default the fixtures in pytest-exasol-saas Plugin will create instances of Exasol SaaS database with scope `session`.

If you want to use an existing instance instead, then you can provide the instance's ID with the command line option `--saas-database-id <ID>` to pytest.

### Keeping Database Instances After the Test Session

By default the fixtures in pytest-exasol-saas Plugin will remove the created database instances after the session or in case of errors.

However, if you provide the command line option `--keep-saas-database` then the pytest-exasol-saas plugin will _keep_ these instances for subsequent inspection or reuse.

Please note hat long-running instances will cause significant costs.

### Naming Database Instances

pytest-exasol-saas Plugin will name the database instances using 3 components

* **Project Short Tag**: Abbreviation of the current project, see below for different [options for providing the project short tag](#options-for-providing-the-project-short-tag).
* **Timestamp**: Number of seconds since epoc, see [Unix Time](https://en.wikipedia.org/wiki/Unix_time).
* A dash character `-`
* **User Name**: Login name of the current user.

A database instances might for example have the name `1715155224SAPIPY-run` indicating it was
* created on Wednesday, May 8, 2024
* in the context of a project with short tag `SAPIPY`
* by a user with login name starting with `run`

Please note that Exasol SaaS limits the length of database names to 10 characters only. So pytest-exasol-saas plugin will shorten the constructed name to 10 characters max.

If running your tests on a server for Continuous Integration (CI) then the name of the user might be not very expressive.

### Options for providing the Project Short Tag

* In yaml file `error_code_config.yml` in the project's root directory
* CLI option `--project-short-tag <short tag>` to pytest
* Environment variable `PROJECT_SHORT_TAG`
1 change: 1 addition & 0 deletions pytest-saas/doc/changes/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ This version introduces the `pytest-exasol-saas` plugin providing pytest functio
## Features

* #9: Added sub-project for exasol-saas-api
* #10: Added pytest fixtures for usage in integration tests of external projects
101 changes: 101 additions & 0 deletions pytest-saas/exasol/pytest_saas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import os
from pathlib import Path

import pytest
from exasol.saas.client import openapi
from exasol.saas.client.api_access import (
OpenApiAccess,
create_saas_client,
timestamp_name,
)

import exasol.pytest_saas.project_short_tag as pst


def pytest_addoption(parser):
parser.addoption(
f"--saas-database-id",
help="""ID of the instance of an existing SaaS database to be
used during the current pytest session instead of creating a
dedicated instance temporarily.""",
)
parser.addoption(
f"--keep-saas-database",
action="store_true",
default=False,
help="""Keep the SaaS database instance created for the current
pytest session for subsequent inspection or reuse.""",
)
parser.addoption(
f"--project-short-tag",
help="""Short tag aka. "abbreviation" for your current project.
See docstring in project_short_tag.py for more details.
pytest plugin for exasol-saas-api will include this short tag into
the names of created database instances.""",
)


def _env(var: str) -> str:
result = os.environ.get(var)
if result:
return result
raise RuntimeError(f"Environment variable {var} is empty.")


@pytest.fixture(scope="session")
def saas_host() -> str:
return _env("SAAS_HOST")


@pytest.fixture(scope="session")
def saas_pat() -> str:
return _env("SAAS_PAT")


@pytest.fixture(scope="session")
def saas_account_id() -> str:
return _env("SAAS_ACCOUNT_ID")


@pytest.fixture(scope="session")
def project_short_tag(request):
return (
request.config.getoption("--project-short-tag")
or os.environ.get("PROJECT_SHORT_TAG")
or pst.read_from_yaml(request.config.rootpath)
)


@pytest.fixture(scope="session")
def database_name(project_short_tag):
return timestamp_name(project_short_tag)


@pytest.fixture(scope="session")
def api_access(saas_host, saas_pat, saas_account_id) -> OpenApiAccess:
with create_saas_client(saas_host, saas_pat) as client:
yield OpenApiAccess(client, saas_account_id)


@pytest.fixture(scope="session")
def saas_database(
request, api_access, database_name
) -> openapi.models.database.Database:
"""
Note: The SaaS instance database returned by this fixture initially
will not be operational. The startup takes about 20 minutes.
"""
db_id = request.config.getoption("--saas-database-id")
if db_id:
yield api_access.get_database(db_id)
return
with api_access.database(database_name) as db:
yield db


@pytest.fixture(scope="session")
def operational_saas_database_id(api_access, saas_database) -> str:
db = saas_database
api_access.add_allowed_ip()
api_access.wait_until_running(db.id)
return db.id
Loading
Loading