Skip to content

Commit

Permalink
#21: Created integration test for operation "create DB" (#22)
Browse files Browse the repository at this point in the history
* Addded changes file
* #21: Added integration tests
* Updated version to 0.3.0
* Described environment variables for integration tests in developer guide
* re-activated coverage
* Use org secrets
* Fixed additional review findings
* Set scope of fixtures to "session"
* Fixed import
  • Loading branch information
ckunki authored Apr 29, 2024
1 parent 95454ad commit 9c3db81
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 9 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
runs-on: ubuntu-latest

steps:

- name: SCM Checkout
uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -103,9 +104,12 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Calculate Test Coverage
if: ${{ hashFiles('.coverage') != '' }}
run: poetry run nox -s coverage -- -- --db-version ${{ matrix.exasol-version }}
- name: Run Tests and Calculate Coverage
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 }}
run: poetry run nox -s coverage -- --

- name: Upload Artifacts
uses: actions/upload-artifact@v3
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
ci-job:
name: Checks
uses: ./.github/workflows/checks.yml
secrets: inherit

metrics:
needs: [ ci-job ]
Expand Down
2 changes: 2 additions & 0 deletions doc/changes/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changes

* [0.3.0](changes_0.3.0.md)
* [0.2.0](changes_0.2.0.md)
* [0.1.0](changes_0.1.0.md)

Expand All @@ -8,6 +9,7 @@
---
hidden:
---
changes_0.3.0
changes_0.2.0
changes_0.1.0
Expand Down
9 changes: 9 additions & 0 deletions doc/changes/changes_0.3.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Saas API Python 0.3.0, released tbd

## Summary

This release adds integration tests for the most important calls to SaaS API.

## Refactorings

* #21: Added integration test for operation "create database"
11 changes: 11 additions & 0 deletions doc/developer_guide/developer_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,14 @@ Use CLI option `--path` to read the JSON definition from a local file instead of
```python
"--path", "/path/to/openapi.json",
```

## Run Tests

Executing the integration tests requires the following environment variables to be set:

| Variable | Description |
|-------------------|-------------------------------------------------------|
| `SAAS_HOST` | Host to use for requests to REST API |
| `SAAS_ACCOUNT_ID` | ID of the Exasol SAAS account to be used by the tests |
| `SAAS_PAT` | Personal access token to access the SAAS API |

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "saas-api"
version = "0.2.0"
version = "0.3.0"
description = "API enabling Python applications connecting to Exasol database SaaS instances and using their SaaS services"
packages = [ {include = "exasol"}, ]
authors = [ "Christoph Kuhnke <[email protected]>" ]
Expand Down Expand Up @@ -77,6 +77,7 @@ ignore = [
]
ignore-paths = [
".*/exasol/saas/client/openapi/.*",
".*/test/.*",
]


Expand Down
89 changes: 89 additions & 0 deletions test/integration/api_access.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from typing import Iterable
from contextlib import contextmanager
from datetime import datetime

from exasol.saas.client import openapi
from exasol.saas.client.openapi.api.databases import (
create_database,
delete_database,
list_databases,
)
from exasol.saas.client.openapi.api.security import (
list_allowed_i_ps,
add_allowed_ip,
delete_allowed_ip,
)


def timestamp() -> str:
return f'{datetime.now().timestamp():.0f}'


def create_saas_client(
host: str,
pat: str,
raise_on_unexpected_status: bool = True,
) -> openapi.AuthenticatedClient:
return openapi.AuthenticatedClient(
base_url=host,
token=pat,
raise_on_unexpected_status = raise_on_unexpected_status,
)


class _OpenApiAccess:
"""
This class is meant to be used only in the context of the API
generator repository while integration tests in other repositories are
planned to only use fixture ``saas_database_id()``.
"""

def __init__(self, client: openapi.Client, account_id: str):
self._client = client
self._account_id = account_id

def create_database(self, cluster_size: str = "XS") -> openapi.models.database.Database:
cluster_spec = openapi.models.CreateCluster(
name="my-cluster",
size=cluster_size,
)
return create_database.sync(
self._account_id,
client=self._client,
body=openapi.models.CreateDatabase(
name=f"pytest-{timestamp()}",
initial_cluster=cluster_spec,
provider="aws",
region='us-east-1',
)
)

@contextmanager
def _ignore_failures(self, ignore: bool = False):
before = self._client.raise_on_unexpected_status
self._client.raise_on_unexpected_status = not ignore
yield self._client
self._client.raise_on_unexpected_status = before

def delete_database(self, database_id: str, ignore_failures=False):
with self._ignore_failures(ignore_failures) as client:
return delete_database.sync_detailed(
self._account_id, database_id, client=client)

def list_database_ids(self) -> Iterable[str]:
dbs = list_databases.sync(self._account_id, client=self._client)
return (db.id for db in dbs)

@contextmanager
def database(
self,
keep: bool = False,
ignore_delete_failure: bool = False,
):
db = None
try:
db = self.create_database()
yield db
finally:
if not keep and db:
self.delete_database(db.id, ignore_delete_failure)
35 changes: 35 additions & 0 deletions test/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest
import os

from exasol.saas.client import openapi
from api_access import create_saas_client, _OpenApiAccess

@pytest.fixture(scope="session")
def saas_host() -> str:
return os.environ["SAAS_HOST"]


@pytest.fixture(scope="session")
def saas_pat() -> str:
return os.environ["SAAS_PAT"]


@pytest.fixture(scope="session")
def saas_account_id() -> str:
return os.environ["SAAS_ACCOUNT_ID"]


@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(api_access) -> openapi.models.database.Database:
"""
Note: The SaaS instance database returned by this fixture initially
will not be operational. The startup takes about 20 minutes.
"""
with api_access.database() as db:
yield db
26 changes: 26 additions & 0 deletions test/integration/databases_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from exasol.saas.client import openapi


def test_lifecycle(api_access):
"""
This integration test uses the database created and provided by pytest
context ``_OpenApiAccess.database()`` to verify
- initial status and number of clusters of the created database
- list_databases includes the new database
- delete_database deletes the database
- list_databases does not include the deleted database anymore
"""

testee = api_access
with testee.database(ignore_delete_failure=True) as db:
# verify state and clusters of created database
assert db.status == openapi.models.Status.TOCREATE and \
db.clusters.total == 1

# verify database is listed
assert db.id in testee.list_database_ids()

# delete database and verify database is not listed anymore
testee.delete_database(db.id)
assert db.id not in testee.list_database_ids()
4 changes: 0 additions & 4 deletions test/integration/test_placeholder.py

This file was deleted.

2 changes: 1 addition & 1 deletion version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
# Do not edit this file manually!
# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`.
MAJOR = 0
MINOR = 2
MINOR = 3
PATCH = 0
VERSION = f"{MAJOR}.{MINOR}.{PATCH}"

0 comments on commit 9c3db81

Please sign in to comment.