mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-09-12 22:25:49 -04:00
docs(tests): add guidelines for stubbing modules in standalone-capable tests
This commit is contained in:
1 parent
8000d9b453
commit
7cbdeb9855
2 files changed
+55
No files matched your search
@@ -98,6 +98,15 @@ from db_test_helpers import make_db, DummyDB, insert_device, minutes_ago
|
||||
|
||||
If a helper you need doesn't exist yet, add it to `db_test_helpers.py` — not locally in the test file.
|
||||
|
||||
## Stubbing Modules in Standalone-Capable Tests
|
||||
|
||||
If a test stubs NetAlertX modules into `sys.modules` so a script can be imported
|
||||
outside the container (see `test/plugins/test_ntfy_custom_headers.py`), pop each
|
||||
stubbed name back out of `sys.modules` right after the one-time import that needed
|
||||
it. Otherwise the fake module leaks into every other test file collected in the
|
||||
same pytest session and shadows the real module (see `testing-workflow` skill for
|
||||
the full pattern and reproduction steps).
|
||||
|
||||
## MAC Literals in Tests — ALWAYS Lowercase
|
||||
|
||||
**MANDATORY:** Every MAC address literal used in test fixtures, parametrize decorators, assertions, or comments must be lowercase hex:
|
||||
|
||||
@@ -59,3 +59,49 @@ docker buildx build -t netalertx-test .
|
||||
```
|
||||
|
||||
This takes ~30 seconds unless venv stage changes (~90s).
|
||||
|
||||
## Pitfall: `sys.modules` Stubbing Leaks Across Test Files
|
||||
|
||||
Some plugin tests (e.g. `test/plugins/test_ntfy_custom_headers.py`) stub NetAlertX
|
||||
modules (`conf`, `helper`, `models.notification_instance`, etc.) via
|
||||
`sys.modules[name] = fake_module` so the plugin script can be imported standalone,
|
||||
outside the container. Because `sys.modules` is a single process-wide cache shared
|
||||
by the whole pytest session, a fake module inserted by one test file silently
|
||||
shadows the real module for every other test file collected afterwards — pytest
|
||||
imports all test files during collection, before any test runs, so this can happen
|
||||
regardless of alphabetical/directory order.
|
||||
|
||||
Symptom: `AttributeError: <module 'models.notification_instance'> does not have
|
||||
the attribute 'get_setting_value'` (or similar) in an unrelated test file, where
|
||||
the module repr has no `from '<path>'` suffix — a giveaway that a stub, not the
|
||||
real module, was resolved.
|
||||
|
||||
Fix pattern: track which module names your stub actually inserted, and pop them
|
||||
back out of `sys.modules` immediately after the one-time import that needed them
|
||||
(the already-imported script keeps its bound names regardless):
|
||||
|
||||
```python
|
||||
_stubbed_module_names = []
|
||||
|
||||
def _stub(name, **attrs):
|
||||
if name not in sys.modules:
|
||||
mod = types.ModuleType(name)
|
||||
for k, v in attrs.items():
|
||||
setattr(mod, k, v)
|
||||
sys.modules[name] = mod
|
||||
_stubbed_module_names.append(name)
|
||||
|
||||
# ... _stub(...) calls, then the one-time import ...
|
||||
import ntfy
|
||||
|
||||
for _name in _stubbed_module_names:
|
||||
sys.modules.pop(_name, None)
|
||||
```
|
||||
|
||||
Reproduce cross-file pollution locally by running the suspect file together with
|
||||
the affected one in a single pytest invocation (order matters less than you'd
|
||||
think — collection happens for all files first):
|
||||
|
||||
```bash
|
||||
pytest test/plugins/test_ntfy_custom_headers.py test/backend/test_notification_templates.py -v
|
||||
```
|
||||
Reference in new issue
Block a user