Skip to content

Commit

Permalink
Add schemathesis tests to respect the OpenAPI contract
Browse files Browse the repository at this point in the history
  • Loading branch information
francbartoli committed Mar 3, 2024
1 parent d1342e8 commit b39983d
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 6 deletions.
70 changes: 70 additions & 0 deletions .github/workflows/contract-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Contract Tests

on:
- push
- pull_request

jobs:
contract-tests:
name: Validate and test the contract of fastgeoapi against the generated pygeoapi OpenAPI document
runs-on: ubuntu-latest
# strategy:
# fail-fast: false
# matrix:
# include:
# - { python: "3.10", os: "ubuntu-20.04", session: "contractests" }
# - { python: "3.9", os: "ubuntu-20.04", session: "contractests" }

# env:
# NOXSESSION: ${{ matrix.session }}
# FORCE_COLOR: "1"

steps:
- name: Check out the repository
uses: actions/[email protected]

- name: Set up Python 3.10
uses: actions/[email protected]
with:
python-version: "3.10"

- name: Upgrade pip
run: |
pip install --constraint=.github/workflows/constraints.txt pip
pip --version
- name: Upgrade pip in virtual environments
shell: python
run: |
import os
import pip
with open(os.environ["GITHUB_ENV"], mode="a") as io:
print(f"VIRTUALENV_PIP={pip.__version__}", file=io)
- name: Install Poetry
run: |
pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry
poetry --version
# - name: Install Nox
# run: |
# pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox
# pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry
# nox --version

- name: Install GDAL
run: |
sudo apt-add-repository ppa:ubuntugis/ubuntugis-unstable
sudo apt-get update
sudo apt-get install python-numpy gdal-bin libgdal-dev
# - name: Run Nox
# run: |
# nox --force-color --python=${{ matrix.python }}

- name: Install fastgeoapi and run schemathesis tests
run: |
poetry install
poetry run uvicorn app.main:app --host 0.0.0.0 --port 6000 --reload --loop asyncio
poetry run st run --checks all "http://localhost:6000/openapi?f=json"
51 changes: 51 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os
import pytest
import schemathesis
import sys
from typer.testing import CliRunner
from unittest import mock


@pytest.fixture
def runner() -> CliRunner:
"""Fixture for invoking command-line interfaces."""
return CliRunner()

def reload_app():
if "app.main" in sys.modules:
del sys.modules["app.main"]
if "app.config.app" in sys.modules:
del sys.modules["app.config.app"]
from app.main import app

return app

@pytest.fixture
def create_app():
"""Return a new app that is being reloaded with
any environment variable has being set"""

yield reload_app

@pytest.fixture
def create_protected_with_apikey_app(create_app):
def _protected_app():
with mock.patch.dict(
os.environ,
{
"API_KEY_ENABLED": "true",
"PYGEOAPI_KEY_GLOBAL": "pygeoapi",
"JWKS_ENABLED": "false",
"OPA_ENABLED": "false"
}
):
app = create_app()
return app

yield _protected_app

@pytest.fixture
def protected_apikey_schema(create_protected_with_apikey_app):
app = create_protected_with_apikey_app()

return schemathesis.from_asgi("/geoapi/openapi?f=json", app=app)
6 changes: 0 additions & 6 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
from typer.testing import CliRunner


@pytest.fixture
def runner() -> CliRunner:
"""Fixture for invoking command-line interfaces."""
return CliRunner()


def test_openapi_succeeds(runner: CliRunner) -> None:
"""It exits with a status code of zero."""
result = runner.invoke(app, ["openapi"])
Expand Down
11 changes: 11 additions & 0 deletions tests/test_openapi_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import pytest
import schemathesis


schema = schemathesis.from_pytest_fixture("protected_apikey_schema")

@schema.parametrize()
def test_api(case):
case.headers = {"X-API-KEY": "pygeoapi"}
response = case.call_asgi()
case.validate_response(response)

0 comments on commit b39983d

Please sign in to comment.