Flaky test: startup log-redaction test fails intermittently depending on worker test order #110
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
tests/test_startup.py—LogStartupInfo::does_not_log_db_password("DB password must be redacted in debug startup log output") fails intermittently in full-suite runs. The failure shows the captured log output as empty:expected contains '***' — received '', while the first assertion ("not contain secret") passes trivially because there is no output at all.Reproduction / frequency
Impact
Random red CI runs and noisy local verification. The production behaviour under test (credential redaction) is fine; the test's capture setup is order-dependent.
Findings from chasing this during PR #109 (where the same root cause also produced a real CI failure for new tests):
StreamHandlertologging.getLogger("fenliu.__main__")and callslog_startup_info, saving/restoring the logger level around the call. Whether records are emitted, however, depends on the logger's effective level, which inherits process-global logging state mutated by whichever tests ran earlier on the same tryke worker. When a previous test leaves the effective level above DEBUG/INFO, the handler receives zero records and the assertion on captured output fails.tests/test_ai_classification.py(added for #106) failed in CI on the 3.13 and 3.14 workers only, with zero records collected — and passed deterministically once the tests pinned the logger's own level (setLevel(WARNING)+ restore infinally) for the capture window.fenliu.logging.setup_loggingor otherwise reconfigure root/package loggers (startup / main / entrypoint test areas).Plan of attack (sketch)
finally.test_startup.pyand audit the other log-capture sites (test_main._capture_logusers,test_entrypoint) for the same hole.Root cause found and fixed on PR #107 (commit
ea42a15).Mechanism:
alembic/env.pycalledfileConfig(config.config_file_name)with the stdlib defaultdisable_existing_loggers=True.test_database.pyruns real migrations viaalembic.command.upgrade, so on any worker where a migration ran before a log-capture test, every logger created up to that point — includingfenliu.__main__— haddisabled=True.Logger.handle()checksdisabledbefore levels, so the capture helpers' level pinning was irrelevant: the handler simply never received records (confirmed empirically by dumping logger state on empty captures —logger.disabled=Truewith empty handlers, exactly matching the failure signature).Fix:
fileConfig(..., disable_existing_loggers=False)in env.py (the Alembic-documented setting for apps that own their logging), plus both capture helpers (test_main._capture_log, the inline capture intest_startup.py) now save/restorelogger.disabledfor hermeticity. This also fixes a latent production symptom: the "Database migrations applied" log line after alembic was being silently dropped.Validation:
fenliu-tryke-3.14(the nox session that reproduced the flake at ~1-in-3) ran 8× consecutively clean after the fix.