Skip to content

Commit 723620a

Browse files
committed
tests: Simplify database pytest fixture
Stop using the DatabaseJanitor from pytest-postgresql to start a separate PostgreSQL server for the tests, but instead connect to existing database server via the configured database settings and appending "_test" to the database name. If there is no configuration (nor DATABASE_URL env var), fallback to connecting to passari_test database on local unix socket. Use functions from sqlalchemy-utils to drop the test database if it already exists and to (re-)create it to ensure that a fresh test database is available for each test case. This makes the database fixture much simpler and allows running the tests on host that doesn't have PostgreSQL installed (by connecting to remote PostgreSQL instance).
1 parent e9190e5 commit 723620a

File tree

2 files changed

+14
-62
lines changed

2 files changed

+14
-62
lines changed

requirements_dev.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ fakeredis~=2.26.1
44
freezegun~=1.5.1
55
pytest-asyncio~=0.24.0
66
pytest-cov~=6.0.0
7-
pytest-postgresql~=6.1.1
87
lupa~=2.2
8+
sqlalchemy-utils~=0.41

tests/conftest.py

+13-61
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import datetime
2-
import os
2+
import re
33
import subprocess
44
import time
55
from pathlib import Path
66

77
from sqlalchemy import create_engine
8+
from sqlalchemy_utils import create_database, database_exists, drop_database
89

910
import fakeredis
1011
import freezegun
1112
import pytest
1213
from passari.config import CONFIG as PAS_CONFIG
1314
from passari_workflow.config import CONFIG
1415
from passari_workflow.db import DBSession
15-
from passari_workflow.db.connection import connect_db
16+
from passari_workflow.db.connection import connect_db, get_connection_uri
1617
from passari_workflow.db.models import (Base, MuseumAttachment,
1718
MuseumObject, MuseumPackage,
1819
SyncStatus)
19-
from pytest_postgresql.janitor import DatabaseJanitor
2020

2121

2222
@pytest.fixture(scope="function", autouse=True)
@@ -42,68 +42,20 @@ def redis(monkeypatch):
4242

4343
@pytest.fixture(scope="session")
4444
def database(request):
45-
def get_psql_version():
46-
result = subprocess.check_output(["psql", "--version"]).decode("utf-8")
47-
version = result.split(" ")[-1].strip()
48-
major, minor, *_ = version.split(".")
49-
50-
# Get the major and minor version, which are what pytest-postgresql
51-
# wants
52-
return f"{major}.{minor}"
53-
54-
if os.environ.get("POSTGRES_USER"):
55-
# Use separately launched process if environments variables are defined
56-
# This is used in Gitlab CI tests which run in a Docker container
57-
user = os.environ["POSTGRES_USER"]
58-
host = os.environ["POSTGRES_HOST"]
59-
password = os.environ["POSTGRES_PASSWORD"]
60-
61-
# POSTGRES_PORT can also be a value such as "tcp://1.1.1.1:5432"
62-
# This handles that format as well
63-
port = int(os.environ.get("POSTGRES_PORT", "5432").split(":")[-1])
64-
db_name = "passari_test"
65-
version = os.environ["POSTGRES_VERSION"]
66-
create_engine(
67-
f"postgresql://{user}:{password}@{host}:{port}/{db_name}"
68-
)
69-
70-
yield request.getfixturevalue("postgresql_nooproc")
71-
else:
72-
# Launch PostgreSQL ourselves
73-
postgresql = request.getfixturevalue("postgresql_proc")
74-
75-
user = postgresql.user
76-
host = postgresql.host
77-
port = postgresql.port
78-
db_name = "passari_test"
79-
80-
version = get_psql_version()
81-
82-
with DatabaseJanitor(
83-
user=user,
84-
host=host,
85-
port=port,
86-
dbname=db_name,
87-
version=version
88-
):
89-
create_engine(
90-
f"postgresql://{user}@{host}:{port}/{db_name}"
91-
)
92-
yield postgresql
45+
db_url = get_connection_uri(default="postgresql:///passari")
46+
test_db_url = re.sub(r"^([^?]*[^/?])(/?[?]?.*)$", r"\1_test\2", db_url)
47+
assert "_test" in test_db_url
48+
if database_exists(test_db_url):
49+
drop_database(test_db_url)
50+
create_database(test_db_url)
51+
yield create_engine(test_db_url)
9352

9453

9554
@pytest.fixture(scope="function")
9655
def engine(database, monkeypatch):
97-
monkeypatch.setitem(CONFIG["db"], "url", "")
98-
monkeypatch.setitem(CONFIG["db"], "user", database.user)
99-
monkeypatch.setitem(
100-
CONFIG["db"], "password",
101-
# Password authentication is used when running tests under Docker
102-
os.environ.get("POSTGRES_PASSWORD", "")
103-
)
104-
monkeypatch.setitem(CONFIG["db"], "host", database.host)
105-
monkeypatch.setitem(CONFIG["db"], "port", database.port)
106-
monkeypatch.setitem(CONFIG["db"], "name", "passari_test")
56+
monkeypatch.setitem(CONFIG["db"], "url", str(database.url))
57+
for item in ("user", "password", "host", "port", "name"):
58+
monkeypatch.setitem(CONFIG["db"], item, "")
10759

10860
engine = connect_db()
10961
engine.echo = True

0 commit comments

Comments
 (0)