Skip to content

Commit

Permalink
set up pytest fixtures and simple cli test
Browse files Browse the repository at this point in the history
  • Loading branch information
azliu0 committed Apr 15, 2024
1 parent 479faeb commit 7f0e0ca
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ select = [
[tool.ruff.lint.per-file-ignores]
# D415: API endpoint docstrings shouldn't end with a period
"server/controllers/*" = ["D415"]
"server_tests/*" = ["D"]

[tool.ruff.lint.pydocstyle]
convention = "google"
1 change: 1 addition & 0 deletions server_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Tests for the `server/` folder.
Empty file added server_tests/__init__.py
Empty file.
91 changes: 91 additions & 0 deletions server_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import os
from typing import cast

import psycopg2
import pytest
from apiflask import APIFlask
from flask.testing import FlaskClient, FlaskCliRunner
from psycopg2 import sql
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
from sqlalchemy.engine import Engine
from sqlalchemy.engine.base import Connection

from server import create_app, db


@pytest.fixture(scope="session")
def db_url(db_name="pigeondb_test"):
"""Creates a test database in postgres, yielding the database URL.
Drops and recreates the database if it already exists.
"""
conn = psycopg2.connect(
dbname="postgres",
user="postgres",
password="password",
host="localhost",
port="5432",
)
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

with conn.cursor() as cur:
cur.execute(f"SELECT 1 FROM pg_database WHERE datname = '{db_name}'")
exists = cur.fetchone()
if exists:
cur.execute(sql.SQL(f"DROP DATABASE {db_name}"))
cur.execute(sql.SQL(f"CREATE DATABASE {db_name}"))

conn.close()

yield "postgresql://postgres:password@localhost/ballotdb_test"


@pytest.fixture(scope="session")
def app(db_url: str):
os.environ["DATABASE_URL"] = db_url

app = create_app()
app.config.update(
{
"TESTING": True,
}
)

yield app


@pytest.fixture(autouse=True)
def enable_transactional_tests(app: APIFlask):
"""Enables fast independent tests by rolling back changes made during every test.
Taken from https://github.com/pallets-eco/flask-sqlalchemy/issues/1171,
with modifications for static type checking.
"""

with app.app_context():
engines = cast(dict[str | None, Engine | Connection], db._app_engines[app])

engine_cleanup = []

for key, engine in engines.items():
connection = (cast(Engine, engine)).connect()
transaction = connection.begin()
engines[key] = connection
engine_cleanup.append((key, engine, connection, transaction))

yield

for key, engine, connection, transaction in engine_cleanup:
transaction.rollback()
connection.close()
engines[key] = engine


@pytest.fixture()
def client(app: APIFlask) -> FlaskClient:
return app.test_client()


@pytest.fixture()
def runner(app: APIFlask) -> FlaskCliRunner:
return app.test_cli_runner()
7 changes: 7 additions & 0 deletions server_tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from click.testing import Result


def test_seed_email(runner):
result: Result = runner.invoke(args=["seed", "email"])
print(result.stdout)
assert result.exit_code == 0

0 comments on commit 7f0e0ca

Please sign in to comment.