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:
Marc 2023-08-12 11:45:51 -04:00 committed by GitHub
parent d3cc915039
commit a341b462c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 19 deletions

View file

@ -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

View file

@ -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
View file

@ -0,0 +1,5 @@
[tool.pytest.ini_options]
pythonpath=[
".",
"./rotini",
]

View file

@ -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,
)

View file

@ -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
)

View 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
View 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

View 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)