Files
core-api/tests/test_conftest.py
T
jpmschweitzerandClaude Sonnet 5 2f53722078 fix(tests): a failing database test no longer prints the password (T-12)
pytest prints a failing test's fixture arguments via repr() as part of the
default traceback header — no -v or --showlocals needed — so any test
taking the test_database_url fixture and failing printed the real
TEST_DATABASE_URL straight into the terminal, password included.

test_database_url now returns a MaskedURL: a str subclass identical to a
plain string for every functional use (passed to .replace(), urlsplit(),
a subprocess environment) but whose repr() masks the password while still
showing host and database name. __str__ is untouched, so every caller
still connects with the real value.

tests/test_conftest.py proves it, both for the fixture itself and for
MaskedURL's string behaviour in isolation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-20 00:28:34 +02:00

44 lines
1.9 KiB
Python

"""Tests for conftest.py's own test-infrastructure fixtures.
core-api T-12: a failing database test used to print the test database
password, because pytest renders a failing test's fixture arguments with
`repr()` — no `-v` or `--showlocals` needed to trigger it, just a test that
takes `test_database_url` and fails. `MaskedURL` (conftest.py) is the fix:
same string, same connection, but a `repr()` that never shows the password.
"""
from urllib.parse import urlsplit
from tests.conftest import MaskedURL
def test_database_url_fixture_renders_without_its_password(test_database_url):
"""Mutation check: revert `MaskedURL.__repr__` to the inherited `str`
one (or hand back a plain `str` from the fixture) and this fails — the
real password would appear in `repr(test_database_url)`, exactly as it
did in a failing test's traceback before T-12."""
password = urlsplit(test_database_url).password
assert password, "fixture must carry a real password for this test to mean anything"
rendered = repr(test_database_url)
assert password not in rendered
# Host and database name are still visible — only the password is masked.
assert "***" in rendered
assert urlsplit(test_database_url).path in rendered
def test_masked_url_is_still_a_fully_usable_string():
"""The wrapper changes only `repr()`; every other string operation the
rest of the suite relies on (`.replace()`, `urlsplit()`, use as a
subprocess environment value) must see the real value unchanged."""
raw = "postgresql://core_api_test:s3cr3t@localhost:5432/core_api_test"
masked = MaskedURL(raw)
assert masked == raw
assert str(masked) == raw
assert masked.replace("postgresql://", "postgresql+asyncpg://", 1) == raw.replace(
"postgresql://", "postgresql+asyncpg://", 1
)
assert urlsplit(masked).password == "s3cr3t"
assert "s3cr3t" not in repr(masked)