Skip to content

Commit 2d559ce

Browse files
authored
✅ Add an end-to-end integration test (#102)
* ✅ Add an end-to-end integration test - Reworks top level of the app to avoid creating the app/routes on import. This allows us to inject settings and get an appropriate app instance. - Moves postman tests to a dedicated directory - Adds the necessary scaffolding to integration test the API - Adds a single test to simulate an election with all guardians - Updates README, workflows, makefile to run the new test * Minor README and pyproject file cleanup
1 parent 371c358 commit 2d559ce

23 files changed

+2681
-61
lines changed

.github/workflows/pull_request.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,15 @@ jobs:
4040
steps:
4141
- name: Checkout Code
4242
uses: actions/checkout@v2
43-
- name: Run Tests
44-
run: make docker-test
43+
- name: Set up Python ${{ env.PYTHON_VERSION }}
44+
uses: actions/setup-python@v1
45+
with:
46+
python-version: ${{ env.PYTHON_VERSION }}
47+
- name: Change Directory
48+
run: cd ${{ github.workspace }}
49+
- name: Setup Environment
50+
run: make environment
51+
- name: Run Integration Tests
52+
run: make test-integration
53+
- name: Run Postman Tests
54+
run: make docker-postman-test

.github/workflows/release.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,18 @@ jobs:
4141
steps:
4242
- name: Checkout Code
4343
uses: actions/checkout@v2
44-
- name: Run Tests
45-
run: make docker-test
44+
- name: Set up Python ${{ env.PYTHON_VERSION }}
45+
uses: actions/setup-python@v1
46+
with:
47+
python-version: ${{ env.PYTHON_VERSION }}
48+
- name: Change Directory
49+
run: cd ${{ github.workspace }}
50+
- name: Setup Environment
51+
run: make environment
52+
- name: Run Integration Tests
53+
run: make test-integration
54+
- name: Run Postman Tests
55+
run: make docker-postman-test
4656

4757
release:
4858
name: Release

Makefile

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ docker-run:
6363
docker-dev:
6464
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.dev.yml up --build
6565

66-
docker-test:
67-
@echo 🧪 RUNNING TESTS IN DOCKER
66+
docker-postman-test:
67+
@echo 🧪 RUNNING POSTMAN TESTS IN DOCKER
6868
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose \
69-
-f tests/docker-compose.yml up \
69+
-f tests/postman/docker-compose.yml up \
7070
--build \
7171
--abort-on-container-exit \
7272
--exit-code-from test-runner
@@ -75,17 +75,21 @@ docker-test:
7575
lint:
7676
@echo 💚 LINT
7777
@echo 1.Pylint
78-
poetry run pylint --extension-pkg-whitelist=pydantic app
78+
poetry run pylint --extension-pkg-whitelist=pydantic app tests
7979
@echo 2.Black Formatting
80-
poetry run black --diff --check app
80+
poetry run black --diff --check app tests
8181
@echo 3.Mypy Static Typing
82-
poetry run mypy --config-file=pyproject.toml app
82+
poetry run mypy --config-file=pyproject.toml app tests
8383
@echo 4.Documentation
8484
poetry run mkdocs build --strict
8585

8686
auto-lint:
87-
poetry run black app
88-
make lint
87+
poetry run black app tests
88+
make lint
89+
90+
test-integration:
91+
@echo ✅ INTEGRATION TESTS
92+
poetry run pytest . -x
8993

9094
# Documentation
9195
docs-serve:

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,19 @@ If the code fails to run, [make sure your Python interpreter is set](https://cod
7575

7676
## 🧪 Testing
7777

78-
A Postman collection is available to test the API located in the `/tests` folder. You can do a few things with this:
78+
End-to-end integration tests can be found in the `/tests/integration` folder. To see them in action, run:
79+
80+
```bash
81+
make test-integration
82+
```
83+
84+
A Postman collection is also available to test the API located in the `/tests/postman` folder. You can do a few things with this:
7985

8086
- [Import into Postman](https://learning.postman.com/docs/getting-started/importing-and-exporting-data/#importing-data-into-postman) for easy manual testing.
8187
- Run locally with the [Newman CLI](https://github.com/postmanlabs/newman).
8288
- Run the APIs and tests entirely in Docker by running:
8389
```bash
84-
make docker-test
90+
make docker-postman-test
8591
```
8692

8793
## 📝 Documentation

app/api/v1/api.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

app/api/v1/routes.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from fastapi import APIRouter
2+
from app.core.config import ApiMode, Settings
3+
from . import common
4+
from . import guardian
5+
from . import mediator
6+
7+
8+
def get_routes(settings: Settings) -> APIRouter:
9+
api_router = APIRouter()
10+
11+
if settings.API_MODE == ApiMode.guardian:
12+
api_router.include_router(guardian.router)
13+
elif settings.API_MODE == ApiMode.mediator:
14+
api_router.include_router(mediator.router)
15+
else:
16+
raise ValueError(f"Unknown API mode: {settings.API_MODE}")
17+
18+
api_router.include_router(common.router)
19+
20+
return api_router

app/core/config.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,3 @@ class Settings(BaseSettings):
2020

2121
class Config:
2222
case_sensitive = True
23-
24-
25-
settings = Settings()

app/main.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
from logging import getLogger
2+
from typing import Optional
23
from fastapi import FastAPI
34
from starlette.middleware.cors import CORSMiddleware
45

5-
from app.api.v1.api import api_router
6-
from app.core.config import settings
6+
from app.api.v1.routes import get_routes
7+
from app.core.config import Settings
78

8-
logger = getLogger("app")
9+
logger = getLogger(__name__)
910

10-
app = FastAPI(
11-
title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json"
12-
)
1311

14-
logger.error(f"Starting API in {settings.API_MODE} mode")
12+
def get_app(settings: Optional[Settings] = None) -> FastAPI:
13+
if not settings:
14+
settings = Settings()
1515

16-
# Set all CORS enabled origins
17-
if settings.BACKEND_CORS_ORIGINS:
18-
app.add_middleware(
19-
CORSMiddleware,
20-
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
21-
allow_credentials=True,
22-
allow_methods=["*"],
23-
allow_headers=["*"],
16+
web_app = FastAPI(
17+
title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json"
2418
)
2519

26-
app.include_router(api_router, prefix=settings.API_V1_STR)
20+
logger.error(f"Starting API in {settings.API_MODE} mode")
21+
22+
# Set all CORS enabled origins
23+
if settings.BACKEND_CORS_ORIGINS:
24+
web_app.add_middleware(
25+
CORSMiddleware,
26+
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
27+
allow_credentials=True,
28+
allow_methods=["*"],
29+
allow_headers=["*"],
30+
)
31+
32+
routes = get_routes(settings)
33+
web_app.include_router(routes, prefix=settings.API_V1_STR)
34+
35+
return web_app
36+
37+
38+
app = get_app()
2739

2840
if __name__ == "__main__":
2941
# IMPORTANT: This should only be used to debug the application.

poetry.lock

Lines changed: 76 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,19 @@ mkdocs = "^1"
2121
mypy = "^0.782"
2222
pylint = "^2"
2323
pytest = "^6"
24-
25-
[build-system]
26-
requires = ["poetry>=0.12"]
27-
build-backend = "poetry.masonry.api"
24+
requests = "^2.24.0"
2825

2926
[tool.black]
3027
target-version = ['py38']
3128
include = '\.pyi?$'
3229

30+
[tool.pylint.'MESSAGES CONTROL']
31+
disable = "duplicate-code, missing-module-docstring, missing-class-docstring, missing-function-docstring, logging-fstring-interpolation"
32+
33+
[build-system]
34+
requires = ["poetry>=0.12"]
35+
build-backend = "poetry.masonry.api"
36+
3337
[mypy]
3438
python_version = 3.8
3539
warn_return_any = true
@@ -39,5 +43,3 @@ ignore_missing_imports = true
3943
follow_imports = "silent"
4044
show_column_numbers = true
4145

42-
[tool.pylint.'MESSAGES CONTROL']
43-
disable = "duplicate-code, missing-module-docstring, missing-class-docstring, missing-function-docstring, logging-fstring-interpolation"

0 commit comments

Comments
 (0)