Files
instagram-bot/tests/conftest.py

107 lines
3.9 KiB
Python

"""
Root Test Configuration — Global Guards Against Environmental Pollution
=======================================================================
This conftest protects ALL tests from the #1 cause of mass failure:
Config() constructor calling argparse.parse_known_args() which reads
sys.argv (pytest's arguments) and crashes with SystemExit: 2.
Every test directory inherits these fixtures automatically.
"""
import sys
import pytest
def pytest_addoption(parser):
parser.addoption("--live", action="store_true", default=False, help="Run live tests")
@pytest.fixture(autouse=True)
def _isolate_config_from_argparse(monkeypatch):
"""Prevent Config() from reading sys.argv during tests.
Root cause: Config.__init__ calls self.parse_args() which calls
self.parser.parse_known_args(). In pytest, sys.argv contains
pytest flags like '--ignore=...' which argparse interprets as
Config arguments, causing SystemExit: 2.
Fix: Temporarily set sys.argv to a minimal list so argparse
doesn't choke on pytest's arguments.
"""
monkeypatch.setattr(sys, "argv", ["test_runner"])
# ═══════════════════════════════════════════════════════
# Pytest Markers Registration
# ═══════════════════════════════════════════════════════
def pytest_configure(config):
config.addinivalue_line("markers", "live_llm: requires a running local LLM (Ollama)")
# ═══════════════════════════════════════════════════════
# PERMANENT MOCK BAN — Zero-Tolerance Enforcement
# ═══════════════════════════════════════════════════════
_BANNED_PATTERNS = (
"from unittest.mock",
"from unittest import mock",
"import unittest.mock",
"from mock import",
"import mock",
"MagicMock(",
"MagicMock)",
"@patch(",
"@patch\n",
"patch.object(",
)
def pytest_collect_file(parent, file_path):
"""Scan every collected .py test file for banned mock imports.
This runs at COLLECTION TIME — before any test executes.
If a banned pattern is found, the file is still collected but
every test inside it will be marked as an error via
pytest_collection_modifyitems below.
"""
if file_path.suffix == ".py" and file_path.name.startswith("test_"):
try:
content = file_path.read_text(encoding="utf-8")
for pattern in _BANNED_PATTERNS:
if pattern in content:
# Store the violation on the config for later reporting
if not hasattr(parent.config, "_mock_violations"):
parent.config._mock_violations = {}
parent.config._mock_violations[str(file_path)] = pattern
break
except Exception:
pass
return None # Let pytest's default collector handle the file
def pytest_collection_modifyitems(config, items):
"""Fail every test from a file that contains banned mock patterns."""
violations = getattr(config, "_mock_violations", {})
if not violations:
return
for item in items:
test_file = str(item.fspath)
if test_file in violations:
pattern = violations[test_file]
item.add_marker(
pytest.mark.xfail(
reason=(
f"🚨 MOCK BAN VIOLATION: File contains '{pattern}'. "
f"unittest.mock is permanently banned. "
f"Use monkeypatch + real fixtures instead."
),
strict=True,
raises=Exception,
)
)