04.07 — Coverage policy: what’s tested, what isn’t, why#

Line coverage is explicitly scoped to the pure DSL and agnostic infra. The rest gets tested by other means (cram, types, snapshots, e2e) or stays out of scope (inert shapes).

pyproject.toml#tool.coverage.run#

[tool.coverage.run]
omit = [
    "*/__init__.py",
    "*/tests/*",
    "*/test_*.py",
    "src/ocarina/custom_errors/*",
    "src/ocarina/custom_types/*",
    "src/ocarina/ports/*",
    "src/ocarina/opinionated/loggers/custom_types/*",
    "src/**/*singleton.py",
    "src/**/consts/**",
    # Selenium adapter layer — exercised only against a real browser.
    "src/ocarina/infra/selenium/*",
    "src/ocarina/dsl/testing/selenium/*",
    "src/ocarina/opinionated/cli/selenium/*",
    "src/ocarina/pom/selenium/muted.py",
    # Playwright adapter layer — exercised only against a real browser.
    "src/ocarina/infra/playwright/*",
    "src/ocarina/dsl/testing/playwright/*",
    "src/ocarina/opinionated/cli/playwright/*",
    "src/ocarina/pom/playwright/*",
    "src/ocarina/opinionated/cli/phantoms.py",
    # Opinionated loggers — only file_logger.py stays in scope.
    "src/ocarina/opinionated/loggers/create_matching_logger.py",
    "src/ocarina/opinionated/loggers/muted_logger.py",
    "src/ocarina/opinionated/loggers/print_logger.py",
    "src/ocarina/opinionated/loggers/print_and_file_logger.py",
    "src/ocarina/opinionated/loggers/utils/*",
    # Traversed by cram tests
    "src/ocarina/opinionated/cli/store.py",
    "src/ocarina/opinionated/cli/builder.py",
]

Categories#

1. Obvious exclusions#

PatternJustification
*/__init__.pyEmpty modules (Python 3 often doesn’t need them)
*/tests/*, */test_*.pyTests don’t test themselves

2. Types / errors / ports / shapes#

PathJustification
src/ocarina/custom_types/*Just type X = ... and frozen dataclasses. No runtime logic.
src/ocarina/custom_errors/*Just Exception subclasses. No logic.
src/ocarina/ports/*ABCs and Protocols. No behavior.
src/ocarina/opinionated/loggers/custom_types/*id.
src/**/consts/**Constants (LOGGERS_CHOICES = (...)).
src/**/*singleton.pyTrivial Singleton wrappers.

3. Selenium and Playwright layers (e2e only)#

PathJustification
src/ocarina/infra/selenium/*Real Selenium code (Chrome(), Firefox()). Only runs with a real browser.
src/ocarina/dsl/testing/selenium/*create_selenium_test, create_selenium_watcher (trivial factories on Test / Watcher).
src/ocarina/opinionated/cli/selenium/*create_selenium_*_cli_store (reads platform.system, instantiates).
src/ocarina/pom/selenium/muted.pyUtility MutedPOM (nearly empty).
src/ocarina/infra/playwright/*Real Playwright code + the PlaywrightDriver actor. The end-to-end only proves out against a real browser.
src/ocarina/dsl/testing/playwright/*create_playwright_test, create_playwright_watcher (same trivial factories).
src/ocarina/opinionated/cli/playwright/*create_playwright_cli_store (Playwright CLI).
src/ocarina/pom/playwright/*MutedPlaywrightPOM + mixins (Null Object, nearly empty).

These files are covered by:

  • ocarina-example/e2e.yml (manual CI, Firefox + Redis).
  • ocarina-with-ai-example/ai_proof_e2e.yml (manual CI, Chrome + Firefox).

External e2e suites prove the adapters work — not the framework’s pytest coverage.

Nuance for the Playwright actor: infra/playwright/* is off the coverage metric, yet its marshalling logic is exercised by test_playwright_driver_actor.py, which patches sync_playwright with a mock and runs in CI without a browser. Omitted from the score ≠ untested.

4. Opinionated loggers (except FileLogger)#

PathJustification
print_logger.py, muted_logger.py, print_and_file_logger.py, create_matching_logger.py, utils/*Trivial variants (terminal only, muted, factory dispatch).
file_logger.pyStays in scope — it’s the only one with real logic (taxonomy → file tree, cleanup, recycle).

FileLogger is tested by test_loggers_and_reports.py. The others are trivial variations on PrintLogger that snapshots cover.

5. CLI traversed by cram#

PathJustification
src/ocarina/opinionated/cli/store.pyTested by cram (the .ts exercise set / get / _Unset)
src/ocarina/opinionated/cli/builder.pyTested by cram (the .ts exercise parse + validation + effects)
src/ocarina/opinionated/cli/phantoms.pyIndirectly tested (the fields using it go through cram)

Retained perimeter#

ModuleWhy
src/ocarina/railway/*ROP core
src/ocarina/dsl/invariants/*Invariants DSL — tested by pytest + mypy plugins + hypothesis
src/ocarina/dsl/testing/* (except selenium/)Orchestration — tested in the “scenarios” folder of unit tests
src/ocarina/dsl/testing_with_railway/*ROP DSL — tested by scenarios + mypy plugins
src/ocarina/infra/drivers_pool.py, driver_builder.py, screenshotter.py, act_counter.pyAgnostic infra — tested with FakeDriver
src/ocarina/aggregates/*TypeGuard helpers
src/ocarina/custom_invariants/*Pre-built invariants — tested by “scenarios” and traversed by the classes that use them
src/ocarina/opinionated/dsl/drive_page.pyTrivial alias
src/ocarina/opinionated/infra/act_counter.pyThread-local counter
src/ocarina/opinionated/launcher/bootstrap.pyBootstrap — tested by test_test_cycle_and_bootstrap.py
src/ocarina/opinionated/plugins/reports/*Plugins — tested by test_loggers_and_reports.py, test_docx_tests_proofs.py, snapshots

Metrics#

--cov-report=html (HTML) + --cov-report=xml:coverage.xml (XML) show:

Coverage typeMetric
Line coverage% of lines executed at least once
Branch coverage% of branches (if/else) covered both ways

The --cov-branch flag is on — Ocarina measures branch coverage, not just line (instruction) coverage.

HTML#

make serve-htmlcov opens htmlcov/index.html in the browser.

  • Green: covered.
  • Red: not covered.
  • Yellow: partially covered (missing branch).

Why not test “everything”#

Naïve approachOcarina policy
Test everything, aim for 100% everywhereTest what matters, aim for a healthy score on what matters
Cover inert shapes (type Result = ...) → trivial 100%Exclude → 100% truly reflects covered behavior
Test Selenium adapters in unit CI → browser setup on every PRTest the adapters in manual e2e CI → fast CI, heavy CI on demand
Test trivial loggers → boilerplateTest only loggers with real logic

On top of what pytest gives us, we account for the other mechanisms verifying Ocarina’s quality (cram, e2e, snapshots, types, manual tests).