Test Coverage and CI
Navgold is a money system — it pushes live prices and stock to Amazon. The test suite is built to catch the one class of bug that matters most: a plausible-but-wrong price or quantity shipping while every test stays green. This page describes how CI is set up and what the suite guarantees.
Continuous Integration
Every push and PR runs the full server suite on a freshly built, bare site (bench new-site + ERPNext + navgold_custom) via GitHub Actions.
Bare-site seeding
A bare CI site has none of the master data a restored production site has (no Company, no default Warehouse, no UOM "Nos", no Item Group tree, no Price List). ERPNext's setup wizard creates all of that, but Frappe only auto-runs it when a single app is installed — with ERPNext + navgold_custom present it bails, leaving the site empty.
Navgold fixes this with a before_tests hook that completes the setup wizard itself:
flowchart TD
A[bench run-tests] --> B[before_tests hook]
B --> C{is_setup_complete?}
C -->|no| D[setup_complete with explicit<br/>fiscal-year dates]
D --> E[Company + Warehouses + UOM Nos<br/>+ Item Group tree + Price Lists]
C -->|yes| F[set defaults + seed buying price list]
E --> F --> G[run suite]
Two gotchas baked into the fix:
- You must pass explicit fiscal-year dates — ERPNext's Fiscal Year validation requires the end date to be exactly one year after the start, and a missing/off-by-one span silently aborts Company creation.
frappe.flags.skip_test_records = Trueavoids the per-doctype auto test-record walk, and background jobs are run inline so tests can assert their results synchronously.
The result: the suite runs green on a clean install — the same condition as a fresh Frappe Cloud site restore — not just on the seeded dev site.
What the suite guarantees
Coverage is concentrated on the money path. Highlights:
| Area | Guarantee |
|---|---|
| Price formula | The price = numerator / (denominator − margin) math (Absolute / Relative / VAT / high-price commission swap / zero-guards / min-max swap) is asserted against hand-derived values. |
| Doctype controllers | Amazon Product Strategy.validate_margin, Amazon Product Pricing.validate_strategies_belong_to_this, fixed-price / active-strategy price selection, and submit_to_amazon gating. |
| Outbound payload | The actual price / SKU / currency written into the Amazon feed and the Repricer CSV is asserted — a wrong price cannot ship green. |
| Guardrails | Freeze, loss circuit-breaker (the freeze actually trips), Dry-Run/Live approval gate (blocked before HTTP), deviation band, oversell / stock reserve, below-cost floor. |
| Stock safety | A failed AFN inventory pull must not zero existing stock; bundle buildable qty; zero-stock publishing modes. |
How the tests are written
- Real database, minimal mocks. Tests insert real documents (rolled back per class) and mock only the true external boundary (Amazon HTTP,
frappe.enqueue). The subject under test always executes. - Assert the side-effect, not the return. After a mocked push, tests query the persisted rows (submission log, snapshot, ledger,
freeze_amazon_outbound), and for a guard they assert the unsafe path is blocked (no enqueue / no HTTP / raises). - Money compared at precision, never raw float equality; expected values are hand-derived from the spec, independent of the code under test.
- Self-seeding. Tests create their own Customer / Item / Sales Order rather than reusing restored-site data, so they run identically on the bare CI site.
- Settings via
@change_settings, notunittest.mock— the real configuration read path is exercised.
Merge policy
The Server check gates every merge. A red CI is treated as a blocker; branches are updated onto the latest develop so they inherit the seed fix before merge.