Tests
The first automated tests for JQC. Kept deliberately small and targeted at the places where a bug is catastrophic and non-obvious — the money path (Stripe webhooks), the SLA state machine, and the multi-tenant routing invariant.
Running
pip install -r requirements-dev.txt
pytest
No MySQL, Redis, or Stripe account is required. tests/conftest.py sets
throwaway SECRET_KEY / DATABASE_URL (in-memory SQLite) at import time so the
app package imports cleanly, and every test either exercises pure functions or
uses the in-memory engine.
What's covered
| File | Scope | Infra needed |
|---|---|---|
test_sla.py |
SLA thresholds + ok/at_risk/breached/None boundaries |
none |
test_billing_webhooks.py |
_ts_to_dt, status normalization, handle_event dispatch + error-swallowing |
none |
test_tenant_routing.py |
Routing is inert with no tenant; resolved g.tenant_engine wins |
in-memory SQLite |
Not yet covered (needs a live control DB + ≥2 tenant DBs)
These are the highest-value integration tests to add next. They require a throwaway MySQL control DB plus two provisioned tenant DBs, so they live outside this fast unit suite for now:
- Cross-tenant isolation — resolve tenant A, write a row, resolve tenant B,
assert the row is invisible. Proves
RoutingSessionnever leaks across tenants. This is the single most important test the project can have. - Webhook handlers end-to-end —
_on_payment_failedsetspast_due_sinceandsubscription_status='past_due';_on_payment_succeededclears the dunning columns. Assert against a realTenantrow. bootstrap_tenantvsupgrade_tenant— a freshly bootstrapped tenant DB ends stamped at chain head with the full schema (the logicscripts/scratch_bootstrap_test.pyproves manually today).- Billing gate state machine — trial-expired redirects to
/billing/subscribe;cancelledredirects to/billing/suspended.