libra/tests/README.md
Padreug 7a4b3022c2 Add integration test suite
113 passing tests + 3 skipped + 8 xfailed across 10 files, covering user
expense and income flow, admin receivable/revenue, settings + auth gates,
void/reject, manual payment requests, balance display, Lightning auth
paths, reconciliation API, and pure-function units. Runs against a real
Fava subprocess and full LNbits app via asgi_lifespan; the harness
captures the auth-flow / settings / env-var disciplines surfaced during
build-out (see tests/README.md and tests/conftest.py docstring).

Eight xfailed/skipped tests carry full implementations gated behind issues
#38, #39, #40 — they flip back on automatically when those land.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 15:39:45 +02:00

2.5 KiB

Libra extension tests

Integration tests covering the user- and admin-facing flows of the libra extension. Tests run against a real fava subprocess and a full LNbits app so they catch behaviour that mocks would miss (BQL semantics, Beancount arithmetic, multi-currency aggregation, HTTP boundary).

Layout

  • conftest.py — session-scoped Fava subprocess + LNbits app + user/wallet fixtures.
  • helpers.py — high-level wrappers for the common API flows (post_expense, settle_receivable, approve_manual_payment_request, …). One per intention, so test bodies read as sequences of actions rather than HTTP calls.
  • test_smoke.py — single end-to-end test; run first to validate the harness.
  • test_<area>_api.py — per-flow coverage (entries, balances, settlement, manual payment requests, lightning, reconciliation, settings/auth, void/reject).
  • test_unit.py — pure functions (beancount_format, account_utils, core/validation); no harness.

Prerequisites

The harness requires fava on PATH. On NixOS:

nix-shell -p python3Packages.fava

Inside the regtest container fava is already provisioned.

Running

From the LNbits source root (with the libra extension reachable via LNBITS_EXTENSIONS_PATH or symlinked into lnbits/extensions/):

# Whole suite
pytest path/to/libra/tests

# Smoke test only (validate the harness before running everything)
pytest path/to/libra/tests/test_smoke.py

# One area
pytest path/to/libra/tests/test_balances_api.py

# Single test, verbose
pytest path/to/libra/tests/test_balances_api.py::test_mixed_income_expense_nets_correctly -v

The Fava subprocess starts once per session (~1-2s) and is shared across tests; each test creates its own LNbits user so the shared ledger doesn't cause inter-test interference.

Conventions

  • Tests assert intent, not shape. Use the helpers in helpers.py for the request and assert on the meaning of the response (balance values, account names, settlement state), not on incidental keys in the JSON. This keeps tests resilient to non-behavioural API tweaks.
  • Currency-handling assertions use pytest.approx for Decimal/float tolerance.
  • One canonical happy path per flow, plus boundary cases that matter (voided entries excluded, pending entries excluded, cross-user isolation, auth gate rejection). Don't over-matrix.
  • Each test creates its own users via the function-scoped libra_user / libra_user_b fixtures. The ledger is session-shared and accumulates entries; test isolation comes from unique user IDs, not ledger resets.