Skip to content

Commit 79d310f

Browse files
authored
feat(pytest): add session fixture to run db migrations (#18)
1 parent 3ce6a4c commit 79d310f

8 files changed

Lines changed: 203 additions & 6 deletions

File tree

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,23 @@ def patient(session):
203203
session.commit()
204204
return patient
205205
```
206+
207+
### `db_migration`
208+
209+
A session scope fixture that runs `alembic upgrade` at test session setup and
210+
`alembic downgrade` at tear down.
211+
212+
It depends on `alembic_ini_path` fixture to get the path of `alembic.ini` file.
213+
214+
To use:
215+
216+
```python
217+
from pytest import mark
218+
219+
pytestmark = mark.usefixtures("db_migration")
220+
```
221+
222+
### `alembic_ini_path`
223+
224+
It returns the path of `alembic.ini` configuration file. By default, it returns
225+
`./alembic.ini`.

fastapi_sqla/_pytest_plugin.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
22
from unittest.mock import patch
33

4+
from alembic import command
5+
from alembic.config import Config
46
from pytest import fixture
57
from sqlalchemy import create_engine
68

@@ -26,8 +28,30 @@ def sqla_connection(db_url):
2628
connection.close()
2729

2830

31+
@fixture(scope="session")
32+
def alembic_ini_path(): # pragma: no cover
33+
"""Path for alembic.ini file, defaults to `./alembic.ini`."""
34+
return "./alembic.ini"
35+
36+
37+
@fixture(scope="session")
38+
def db_migration(db_url, sqla_connection, alembic_ini_path):
39+
"""Run alembic upgrade at test session setup and downgrade at tear down.
40+
41+
Override fixture `alembic_ini_path` to change path of `alembic.ini` file.
42+
"""
43+
alembic_config = Config(file_=alembic_ini_path)
44+
alembic_config.set_main_option("sqlalchemy.url", db_url)
45+
46+
sqla_connection.execute("DROP SCHEMA public CASCADE; CREATE SCHEMA public;")
47+
48+
command.upgrade(alembic_config, "head")
49+
yield
50+
command.downgrade(alembic_config, "base")
51+
52+
2953
@fixture
30-
def sqla_modules(): # pragma: no cover
54+
def sqla_modules():
3155
raise Exception(
3256
"sqla_modules fixture is not defined. Define a sqla_modules fixture which "
3357
"imports all modules with sqla entities deriving from fastapi_sqla.Base ."

poetry.lock

Lines changed: 100 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ asgi_lifespan = "^1.0.1"
2424
httpx = "^0.15.4"
2525
pytest-asyncio = "^0.14.0"
2626
Faker = "^4.5.0"
27+
alembic = "^1.4.3"
2728

2829
[build-system]
2930
requires = ["poetry>=0.12"]

tests/alembic.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[alembic]
2+
script_location = %(here)s/db

tests/db/env.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from alembic import context
2+
from sqlalchemy import engine_from_config, pool
3+
4+
config = context.config
5+
6+
connectable = engine_from_config(
7+
config.get_section(config.config_ini_section),
8+
prefix="sqlalchemy.",
9+
poolclass=pool.NullPool,
10+
)
11+
12+
with connectable.connect() as connection:
13+
context.configure(connection=connection, target_metadata=None)
14+
15+
with context.begin_transaction():
16+
context.run_migrations()
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""create user table to test
2+
3+
Revision ID: 01
4+
Revises:
5+
Create Date: 2020-12-23 12:08:57.382420
6+
7+
"""
8+
from alembic import op
9+
from sqlalchemy import Column, Integer, String
10+
11+
# revision identifiers, used by Alembic.
12+
revision = "01"
13+
down_revision = None
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade():
19+
op.create_table(
20+
"testuser",
21+
Column("id", Integer, primary_key=True, autoincrement=True),
22+
Column("name", String, nullable=False),
23+
)
24+
25+
26+
def downgrade():
27+
op.drop_table("testuser")

tests/test_db_migration.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from pytest import fixture, mark
2+
3+
pytestmark = mark.usefixtures("db_migration")
4+
5+
6+
@fixture(scope="session")
7+
def alembic_ini_path():
8+
return "./tests/alembic.ini"
9+
10+
11+
def test_it(session):
12+
session.execute("select * from testuser")

0 commit comments

Comments
 (0)