Skip to content

Commit 0c67391

Browse files
authored
Change tests to dump the first migration and use for all other tests (#236)
* add default env vars for pg client * add postgresql-client to the docker image * Change tests to dump the first migration and use for all other tests * remove the defn of slow_db
1 parent 11d5882 commit 0c67391

File tree

4 files changed

+46
-68
lines changed

4 files changed

+46
-68
lines changed

.env.example

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
POSTGRES_USER=navigator
33
POSTGRES_PASSWORD=password
44
ADMIN_POSTGRES_HOST=admin_backend_db
5+
PGUSER=navigator
6+
PGPASSWORD=password
7+
PGHOST=admin_backend_db
58

69
# API
710
SECRET_KEY=secret_test_key

Dockerfile

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ FROM python:3.10-slim
33
WORKDIR /usr/src
44
ENV PYTHONPATH=/usr/src
55

6+
# Install PostgreSQL client tools
7+
RUN apt-get update && \
8+
apt-get install -y --no-install-recommends \
9+
postgresql-client && \
10+
rm -rf /var/lib/apt/lists/*
11+
612
# Requirements
713
RUN pip install --no-cache-dir poetry==1.7.1
814
COPY poetry.lock pyproject.toml ./

poetry.lock

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration_tests/conftest.py

+34-65
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import os
2-
import uuid
3-
from typing import Dict, Generator
1+
import subprocess
2+
import tempfile
3+
from typing import Dict
44

55
import boto3
66
import pytest
@@ -9,7 +9,6 @@
99
from fastapi.testclient import TestClient
1010
from moto import mock_s3
1111
from sqlalchemy import create_engine
12-
from sqlalchemy.engine import Connection
1312
from sqlalchemy.orm import sessionmaker
1413
from sqlalchemy_utils import create_database, database_exists, drop_database
1514

@@ -40,29 +39,51 @@
4039
UNFCCC_ORG_ID = 2
4140
SUPER_ORG_ID = 50
4241

42+
migration_file = None
4343

44-
def get_test_db_url() -> str:
45-
return SQLALCHEMY_DATABASE_URI + f"_test_{uuid.uuid4()}"
4644

45+
def _create_engine_run_migrations(test_db_url: str):
46+
test_engine = create_engine(test_db_url)
47+
run_migrations(test_engine)
48+
return test_engine
4749

48-
@pytest.fixture(scope="function")
49-
def slow_db(monkeypatch):
50-
"""Create a fresh test database for each test."""
5150

52-
test_db_url = get_test_db_url()
51+
def do_cached_migrations(test_db_url: str):
52+
53+
global migration_file # Note this is scoped to the module, so it will not get recreated.
5354

5455
# Create the test database
5556
if database_exists(test_db_url):
5657
drop_database(test_db_url)
5758
create_database(test_db_url)
5859

60+
test_engine = None
61+
62+
if not migration_file:
63+
test_engine = _create_engine_run_migrations(test_db_url)
64+
migration_file = tempfile.NamedTemporaryFile().name
65+
result = subprocess.run(["pg_dump", "-f", migration_file])
66+
assert result.returncode == 0
67+
else:
68+
result = subprocess.run(["psql", "-f", migration_file])
69+
assert result.returncode == 0
70+
test_engine = create_engine(test_db_url)
71+
72+
return test_engine
73+
74+
75+
@pytest.fixture(scope="function")
76+
def data_db(monkeypatch):
77+
"""Create a fresh test database for each test."""
78+
79+
test_db_url = SQLALCHEMY_DATABASE_URI # Use the same db - cannot parrallelize tests
80+
81+
test_engine = do_cached_migrations(test_db_url)
5982
test_session = None
6083
connection = None
6184
try:
62-
test_engine = create_engine(test_db_url)
63-
connection = test_engine.connect()
6485

65-
run_migrations(test_engine)
86+
connection = test_engine.connect()
6687
test_session_maker = sessionmaker(
6788
autocommit=False,
6889
autoflush=False,
@@ -86,58 +107,6 @@ def get_test_db():
86107
drop_database(test_db_url)
87108

88109

89-
@pytest.fixture(scope="session")
90-
def data_db_connection() -> Generator[Connection, None, None]:
91-
test_db_url = get_test_db_url()
92-
93-
if database_exists(test_db_url):
94-
drop_database(test_db_url)
95-
create_database(test_db_url)
96-
97-
saved_db_url = os.environ["DATABASE_URL"]
98-
os.environ["DATABASE_URL"] = test_db_url
99-
100-
test_engine = create_engine(test_db_url)
101-
102-
run_migrations(test_engine)
103-
connection = test_engine.connect()
104-
105-
yield connection
106-
connection.close()
107-
108-
os.environ["DATABASE_URL"] = saved_db_url
109-
drop_database(test_db_url)
110-
111-
112-
@pytest.fixture(scope="function")
113-
def data_db(slow_db):
114-
yield slow_db
115-
116-
117-
# @pytest.fixture(scope="function")
118-
# def data_db(data_db_connection, monkeypatch):
119-
120-
# outer = data_db_connection.begin_nested()
121-
# SessionLocal = sessionmaker(
122-
# autocommit=False, autoflush=False, bind=data_db_connection
123-
# )
124-
# session = SessionLocal()
125-
126-
# def get_test_db():
127-
# return session
128-
129-
# monkeypatch.setattr(db_session, "get_db", get_test_db)
130-
# yield session
131-
# if not outer.is_active:
132-
# print("Outer transaction already completed.")
133-
# #raise RuntimeError("Outer transaction already completed.")
134-
# else:
135-
# outer.rollback()
136-
# n_cols = data_db_connection.execute("select count(*) from collection")
137-
# if n_cols.scalar() != 0:
138-
# raise RuntimeError("Database not cleaned up properly")
139-
140-
141110
@pytest.fixture
142111
def client():
143112
"""Get a TestClient instance that reads/write to the test database."""

0 commit comments

Comments
 (0)