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>
This commit is contained in:
+18
-1
@@ -49,6 +49,23 @@ def run_alembic(url: str, *args: str) -> subprocess.CompletedProcess:
|
||||
return result
|
||||
|
||||
|
||||
class MaskedURL(str):
|
||||
"""A database URL, fully usable as a plain string (passed to `.replace()`,
|
||||
`urlsplit()`, a subprocess environment, ...) but never through `repr()`
|
||||
(core-api T-12): pytest prints a failing test's fixture arguments using
|
||||
`repr()`, with no `-v`/`--showlocals` needed to trigger it — that is how
|
||||
a failing database test used to print this fixture's password straight
|
||||
into the terminal. `__str__` is deliberately left alone, so the real
|
||||
value is still what every caller actually connects with."""
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parts = urlsplit(self)
|
||||
netloc = parts.netloc
|
||||
if parts.password:
|
||||
netloc = netloc.replace(f":{parts.password}@", ":***@")
|
||||
return repr(parts._replace(netloc=netloc).geturl())
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def test_database_url() -> str:
|
||||
"""The core_api_test database URL, or skip/refuse per the rules above."""
|
||||
@@ -62,7 +79,7 @@ def test_database_url() -> str:
|
||||
"TEST_DATABASE_URL resolves to 'core_api' (production) — refusing to use it for tests"
|
||||
)
|
||||
|
||||
return url
|
||||
return MaskedURL(url)
|
||||
|
||||
|
||||
def _grant_test_office_gemini(url: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user