build(backend): add db-aware testing tooling (#9)
* fix(backend): centralized settings, fix refs * build(backend): pytest configuration points at the right path * build(backend): test tooling script * ci(backend): use taskfile to trigger tests in ci * test(backend): stub db-test * ci(backend): use Task for backend steps, remove redundant bootstrap
This commit is contained in:
parent
d3cc915039
commit
a341b462c7
8 changed files with 75 additions and 19 deletions
20
.github/workflows/backend-pipeline.yml
vendored
20
.github/workflows/backend-pipeline.yml
vendored
|
@ -3,6 +3,10 @@ name: Backend Pipeline
|
|||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
TASK_VERSION: 3.28.0
|
||||
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -42,6 +46,10 @@ jobs:
|
|||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ steps.get-python-version.outputs.python_version }}
|
||||
- name: Setup Task
|
||||
uses: arduino/setup-task@v1
|
||||
with:
|
||||
version: ${{ env.TASK_VERSION }}
|
||||
- uses: actions/cache@v3
|
||||
id: cache-restore
|
||||
with:
|
||||
|
@ -50,8 +58,7 @@ jobs:
|
|||
key: ${{ runner.os }}-${{ hashFiles('**/requirements*.txt') }}-${{ steps.get-python-version.outputs.python_version }}
|
||||
- name: Lint
|
||||
run: |
|
||||
. script/bootstrap
|
||||
black . --check
|
||||
task be:lint
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test
|
||||
|
@ -67,13 +74,16 @@ jobs:
|
|||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ steps.get-python-version.outputs.python_version }}
|
||||
- name: Setup Task
|
||||
uses: arduino/setup-task@v1
|
||||
with:
|
||||
version: ${{ env.TASK_VERSION }}
|
||||
- uses: actions/cache@v3
|
||||
id: cache-restore
|
||||
with:
|
||||
path: |
|
||||
.venv
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/requirements*.txt') }}-${{ steps.get-python-version.outputs.python_version }}
|
||||
- name: Lint
|
||||
- name: Test
|
||||
run: |
|
||||
. script/bootstrap
|
||||
pytest
|
||||
task be:test
|
||||
|
|
|
@ -22,7 +22,7 @@ tasks:
|
|||
test:
|
||||
desc: "Run the test suites."
|
||||
deps: [bootstrap]
|
||||
cmd: source {{ .VENV_ACTIVATE }} && pytest .
|
||||
cmd: . script/test
|
||||
dir: backend
|
||||
start:
|
||||
desc: "Starts the backend application."
|
||||
|
|
5
backend/pyproject.toml
Normal file
5
backend/pyproject.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
[tool.pytest.ini_options]
|
||||
pythonpath=[
|
||||
".",
|
||||
"./rotini",
|
||||
]
|
|
@ -1,16 +1,16 @@
|
|||
import os
|
||||
|
||||
import psycopg2
|
||||
|
||||
import settings
|
||||
|
||||
|
||||
def get_connection():
|
||||
"""
|
||||
Create a database connection.
|
||||
"""
|
||||
return psycopg2.connect(
|
||||
user=os.environ["DATABASE_USERNAME"],
|
||||
password=os.environ["DATABASE_PASSWORD"],
|
||||
host=os.environ["DATABASE_HOST"],
|
||||
port=os.environ["DATABASE_PORT"],
|
||||
database=os.environ["DATABASE_NAME"],
|
||||
user=settings.DATABASE_USERNAME,
|
||||
password=settings.DATABASE_PASSWORD,
|
||||
host=settings.DATABASE_HOST,
|
||||
port=settings.DATABASE_PORT,
|
||||
database=settings.DATABASE_NAME,
|
||||
)
|
||||
|
|
|
@ -38,6 +38,8 @@ import sys
|
|||
|
||||
import psycopg2
|
||||
|
||||
import settings
|
||||
|
||||
VALID_COMMANDS = ["up", "down", "new"]
|
||||
|
||||
DIRECTION_UP = 1
|
||||
|
@ -57,11 +59,11 @@ def _get_connection():
|
|||
Create a database connection.
|
||||
"""
|
||||
return psycopg2.connect(
|
||||
user=os.environ["DATABASE_USERNAME"],
|
||||
password=os.environ["DATABASE_PASSWORD"],
|
||||
host=os.environ["DATABASE_HOST"],
|
||||
port=os.environ["DATABASE_PORT"],
|
||||
database=os.environ["DATABASE_NAME"],
|
||||
user=settings.DATABASE_USERNAME,
|
||||
password=settings.DATABASE_PASSWORD,
|
||||
host=settings.DATABASE_HOST,
|
||||
port=settings.DATABASE_PORT,
|
||||
database=settings.DATABASE_NAME,
|
||||
)
|
||||
|
||||
|
||||
|
@ -90,7 +92,7 @@ def _get_migration_sequence() -> typing.List[MigrationItem]:
|
|||
This will detect duplicates and breaks in the sequence
|
||||
and raise if the history is not linear and complete.
|
||||
"""
|
||||
migrations_dir = pathlib.Path(".")
|
||||
migrations_dir = pathlib.Path(__file__).parent
|
||||
migrations: typing.Dict[MigrationID, MigrationModuleName] = {}
|
||||
dependency_map: typing.Dict[MigrationID, MigrationID] = {}
|
||||
|
||||
|
@ -177,6 +179,7 @@ def migrate(direction: typing.Union[typing.Literal[1], typing.Literal[-1]]):
|
|||
print(f"Applying {migrations_to_apply[pos][1]}")
|
||||
cursor.execute(sql)
|
||||
|
||||
print(migrations_to_apply)
|
||||
next_last_applied = (
|
||||
None if direction == DIRECTION_DOWN else migrations_to_apply[-1].id
|
||||
)
|
||||
|
|
5
backend/rotini/settings.py
Normal file
5
backend/rotini/settings.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
DATABASE_USERNAME = "postgres"
|
||||
DATABASE_PASSWORD = "test"
|
||||
DATABASE_HOST = "localhost"
|
||||
DATABASE_PORT = 5431
|
||||
DATABASE_NAME = "postgres"
|
18
backend/script/test
Normal file
18
backend/script/test
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
|
||||
TEST_DB_CONTAINER=rotini-test-ephemeral
|
||||
|
||||
docker run \
|
||||
--name $TEST_DB_CONTAINER \
|
||||
-e POSTGRES_PASSWORD=test \
|
||||
-p 5431:5432 \
|
||||
-d \
|
||||
postgres:15.4
|
||||
|
||||
sleep 2
|
||||
|
||||
PYTHONPATH=rotini .venv/bin/python rotini/migrations/migrate.py up
|
||||
.venv/bin/pytest .
|
||||
|
||||
docker stop $TEST_DB_CONTAINER
|
||||
docker remove $TEST_DB_CONTAINER
|
15
backend/tests/test_api_files.py
Normal file
15
backend/tests/test_api_files.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from fastapi.testclient import TestClient
|
||||
import pytest
|
||||
|
||||
from rotini.main import app
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client():
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def test_list_files(client):
|
||||
response = client.get("/files/")
|
||||
|
||||
print(response)
|
Reference in a new issue