Testing
pyzm has three tiers of tests:
Unit / integration — mock-based, no special hardware
ML end-to-end — real ML models against real images
ZoneMinder end-to-end — live ZM server API calls
Running all tests
pip install pytest
python -m pytest tests/ -v
Both e2e tiers auto-skip when their prerequisites are missing, so this is always safe to run.
Unit / integration tests
These tests mock backends and use no real models. They run anywhere:
python -m pytest tests/ -m "not e2e and not zm_e2e" -v
ML end-to-end tests
The tests/test_ml_e2e/ directory contains 89 tests that exercise every
objectconfig feature using real YOLO models and a real test image
(tests/test_ml_e2e/bird.jpg, included in the repository).
Prerequisites:
ML models installed at
/var/lib/zmeventnotification/models/(at least one YOLO model, e.g.yolov4/)Python packages:
opencv-python,numpy,shapelyFor remote-serve tests:
fastapi,uvicorn,requests,PyJWT
Run all ML e2e tests:
python -m pytest tests/test_ml_e2e/ -v
Skip the slower remote-serve tests (which start real server subprocesses):
python -m pytest tests/test_ml_e2e/ -v -m "not serve"
Run only remote-serve tests:
python -m pytest tests/test_ml_e2e/ -v -m serve
Run a single test file:
python -m pytest tests/test_ml_e2e/test_zone_filtering.py -v
ZoneMinder end-to-end tests
The tests/test_zm_e2e/ directory tests the ZM API layer (auth, monitors,
events, zones, frames, state management) against a live ZoneMinder server.
One-time setup:
sudo /opt/zoneminder/venv/bin/pip install pytest
cp tests/.env.zm_e2e.sample .env.zm_e2e
# edit .env.zm_e2e with your ZM_API_URL, ZM_USER, ZM_PASSWORD
The .env.zm_e2e file is gitignored. Tests auto-skip when it is missing.
Tests run as www-data so they can read /etc/zm/zm.conf for DB access.
The -p no:cacheprovider flag avoids permission warnings on .pytest_cache/.
Readonly tests (auth, monitors, events, zones, frames, detection):
sudo -u www-data python -m pytest tests/test_zm_e2e/ -v -p no:cacheprovider
Include write tests (event notes, stop/start/restart, DB tagging):
sudo -u www-data ZM_E2E_WRITE=1 python -m pytest tests/test_zm_e2e/ -v -p no:cacheprovider
If your ZM config is in a non-standard location, set PYZM_CONFPATH in
.env.zm_e2e or as an environment variable.
Test file reference
File |
Tests |
What it covers |
|---|---|---|
|
5 |
File path input, numpy input, multi-frame, result properties, to_dict roundtrip |
|
5 |
Auto-discover all, directory name resolution, file stem resolution, unknown fallback, framework assignment |
|
4 |
Per-model pattern, global pattern, restrictive regex, specific label match |
|
5 |
|
|
6 |
Full-image zone, tiny zone, zone-specific pattern, non-matching pattern, multiple zones, no zones |
|
2 |
High threshold filters low-confidence, low vs high comparison |
|
2 |
|
|
4 |
|
|
4 |
|
|
2 |
Gate not satisfied (skips), gate satisfied (runs) |
|
6 |
First run, duplicate filtering, aliases, |
|
8 |
|
|
8 |
|
|
2 |
Custom |
|
2 |
Two-model UNION, multiple model names by string |
|
3 |
Eager load ( |
|
8 |
|
|
3 |
|
|
4 |
Pattern + size, zone + pattern, global pattern + zone, past detection + zone |
|
6 |
Bad file path, empty frames list, no models, |
Pytest markers
Marker |
Description |
|---|---|
|
Tests requiring optional dependencies (cv2, shapely, numpy) |
|
ML end-to-end tests requiring real models and images on disk |
|
Tests that start a |
|
Tests requiring a live ZoneMinder instance (configured via |
|
ZM E2E tests that mutate state (event notes, stop/start/restart, DB
tagging). Excluded from CI; opt-in via |