feat: add working tests
This commit is contained in:
parent
cd7a5431e9
commit
3d7217ec69
10 changed files with 80 additions and 21 deletions
|
@ -6,7 +6,7 @@ from sqlalchemy import pool
|
||||||
from alembic import context
|
from alembic import context
|
||||||
|
|
||||||
from foxnouns.db import Base
|
from foxnouns.db import Base
|
||||||
from foxnouns.settings import SYNC_DATABASE_URL
|
from foxnouns.db.sync import SYNC_DATABASE_URL
|
||||||
|
|
||||||
# this is the Alembic Config object, which provides
|
# this is the Alembic Config object, which provides
|
||||||
# access to the values within the .ini file in use.
|
# access to the values within the .ini file in use.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from quart import Quart, make_response, jsonify, request, g
|
from quart import Quart, request, g
|
||||||
from quart_schema import QuartSchema, RequestSchemaValidationError
|
from quart_schema import QuartSchema, RequestSchemaValidationError
|
||||||
|
|
||||||
from .blueprints import users_blueprint
|
from .blueprints import users_blueprint
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from pydantic import BaseModel, Field, field_validator
|
from pydantic import BaseModel, Field, field_validator
|
||||||
from quart import Blueprint, request
|
from quart import Blueprint
|
||||||
from quart_schema import validate_response, validate_request
|
from quart_schema import validate_response, validate_request
|
||||||
|
|
||||||
from foxnouns.db.aio import async_session
|
from foxnouns.db.aio import async_session
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from sqlalchemy import URL
|
from sqlalchemy import URL
|
||||||
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
|
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
|
||||||
|
|
||||||
from foxnouns.settings import DATABASE
|
from foxnouns.settings import DATABASE, ECHO_SQL
|
||||||
|
|
||||||
ASYNC_DATABASE_URL = URL.create(
|
ASYNC_DATABASE_URL = URL.create(
|
||||||
"postgresql+asyncpg",
|
"postgresql+asyncpg",
|
||||||
|
@ -11,5 +11,5 @@ ASYNC_DATABASE_URL = URL.create(
|
||||||
database=DATABASE["NAME"],
|
database=DATABASE["NAME"],
|
||||||
)
|
)
|
||||||
|
|
||||||
engine = create_async_engine(ASYNC_DATABASE_URL)
|
engine = create_async_engine(ASYNC_DATABASE_URL, echo=ECHO_SQL)
|
||||||
async_session = async_sessionmaker(engine, expire_on_commit=False)
|
async_session = async_sessionmaker(engine, expire_on_commit=False)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from sqlalchemy import URL, create_engine
|
from sqlalchemy import URL, create_engine
|
||||||
|
|
||||||
from foxnouns.settings import DATABASE
|
from foxnouns.settings import DATABASE, ECHO_SQL
|
||||||
|
|
||||||
SYNC_DATABASE_URL = URL.create(
|
SYNC_DATABASE_URL = URL.create(
|
||||||
"postgresql+psycopg",
|
"postgresql+psycopg",
|
||||||
|
@ -10,4 +10,4 @@ SYNC_DATABASE_URL = URL.create(
|
||||||
database=DATABASE["NAME"],
|
database=DATABASE["NAME"],
|
||||||
)
|
)
|
||||||
|
|
||||||
engine = create_engine(SYNC_DATABASE_URL)
|
engine = create_engine(SYNC_DATABASE_URL, echo=ECHO_SQL)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import re
|
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
from . import BaseSnowflakeModel
|
from . import BaseSnowflakeModel
|
||||||
|
|
|
@ -20,3 +20,6 @@ SHORT_DOMAIN = env("SHORT_DOMAIN", "prns.localhost")
|
||||||
|
|
||||||
# Secret key for signing tokens, generate with (for example) `openssl rand -base64 32`
|
# Secret key for signing tokens, generate with (for example) `openssl rand -base64 32`
|
||||||
SECRET_KEY = env("SECRET_KEY")
|
SECRET_KEY = env("SECRET_KEY")
|
||||||
|
|
||||||
|
# Whether to echo SQL statements to the logs.
|
||||||
|
ECHO_SQL = env.bool("ECHO_SQL", False)
|
||||||
|
|
|
@ -1,8 +1,61 @@
|
||||||
|
import pytest
|
||||||
import pytest_asyncio
|
import pytest_asyncio
|
||||||
|
from sqlalchemy import text, delete
|
||||||
|
|
||||||
|
from foxnouns.db import Base
|
||||||
|
from foxnouns.settings import DATABASE
|
||||||
|
|
||||||
|
|
||||||
|
# Override the database name to the testing database
|
||||||
|
DATABASE["NAME"] = f"{DATABASE['NAME']}_test"
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_collection_modifyitems(items):
|
||||||
|
"""Ensure that all async tests use the same event loop."""
|
||||||
|
|
||||||
|
pytest_asyncio_tests = (
|
||||||
|
item for item in items if pytest_asyncio.is_async_test(item)
|
||||||
|
)
|
||||||
|
session_scope_marker = pytest.mark.asyncio(scope="session")
|
||||||
|
for async_test in pytest_asyncio_tests:
|
||||||
|
async_test.add_marker(session_scope_marker, append=False)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def setup():
|
||||||
|
"""Migrate the testing database to the latest migration, and once the tests complete, clear the database again."""
|
||||||
|
|
||||||
|
from foxnouns.db.sync import engine
|
||||||
|
from alembic import command, config
|
||||||
|
|
||||||
|
cfg = config.Config("alembic.ini")
|
||||||
|
cfg.attributes["connection"] = engine.connect()
|
||||||
|
command.upgrade(cfg, "head")
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
with engine.begin() as session:
|
||||||
|
Base.metadata.drop_all(session)
|
||||||
|
session.execute(text("DROP TABLE alembic_version"))
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
|
def clean_tables_after_tests():
|
||||||
|
"""Clean tables after every test."""
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
from foxnouns.db.sync import engine
|
||||||
|
|
||||||
|
with engine.begin() as session:
|
||||||
|
for table in reversed(Base.metadata.sorted_tables):
|
||||||
|
session.execute(delete(table))
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session", autouse=True)
|
@pytest_asyncio.fixture(scope="session", autouse=True)
|
||||||
async def setup():
|
async def app():
|
||||||
print("hello from setup!")
|
from foxnouns.app import app
|
||||||
yield
|
|
||||||
print("bye from setup!")
|
return app
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import pytest
|
|
||||||
|
|
||||||
from foxnouns import hello
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_hello():
|
|
||||||
assert (await hello()) == "Hello world!"
|
|
13
tests/test_users.py
Normal file
13
tests/test_users.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import pytest
|
||||||
|
from quart import Quart
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
class TestUsers:
|
||||||
|
async def test_get_me_returns_403_if_unauthenticated(self, app: Quart):
|
||||||
|
resp = await app.test_client().get("/api/v2/users/@me")
|
||||||
|
assert resp.status_code == 403
|
||||||
|
|
||||||
|
async def test_get_users_returns_404_if_user_not_found(self, app: Quart):
|
||||||
|
resp = await app.test_client().get("/api/v2/users/unknown_user")
|
||||||
|
assert resp.status_code == 404
|
Loading…
Reference in a new issue