Branch coverage records which possible control-flow destinations were executed, while tests separately decide whether their results were correct.
Coverage.py branch coverage: execution paths are not correctness assertions
Operation contract
The owned module has one negative-input branch and one accepted return. Tests execute both paths with explicit expected behavior, then coverage.py writes a JSON report. The program checks that no branch destination is missing. Module, report and measurement files all live in one temporary directory, and exact coverage totals are not printed as a portability promise.
Failure and ownership boundary
Full measured branch coverage can still accompany wrong assertions or an incomplete input contract. The fixture is a two-path local function, not coverage of the site or an entire service. Excluded lines and subprocesses also require deliberate configuration. Hypothesis property tests: compare generated cases with an independent contract and Python unittest.mock: inject a collaborator failure before publication extend testing beyond one percentage.
Tested environment
Dependency check: this program was executed on CPython 3.14.6 with coverage==7.16.2. Install these versions in a separate virtual environment. The download includes the recorded environment snapshot; no third-party package is part of the website runtime.
Working program
from pathlib import Path
import importlib.util
import json
import tempfile
import coverage
with tempfile.TemporaryDirectory() as directory:
target = Path(directory) / "quantity_rules.py"
target.write_text('def accept_quantity(quantity):\n if quantity < 0:\n raise ValueError("negative")\n return quantity\n', encoding="utf-8")
measured = coverage.Coverage(branch=True, data_file=str(Path(directory) / ".coverage"))
measured.start()
try:
spec = importlib.util.spec_from_file_location("owned_quantity_rules", target)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
assert module.accept_quantity(3) == 3
try:
module.accept_quantity(-1)
except ValueError:
pass
else:
raise AssertionError("negative branch did not reject")
finally:
measured.stop()
report = Path(directory) / "coverage.json"
measured.json_report(outfile=str(report), include=[str(target)])
details = json.loads(report.read_text(encoding="utf-8"))
print("missing branches:", details["totals"]["missing_branches"])
print("measurement files owned by temporary directory")Output
missing branches: 0
measurement files owned by temporary directoryCosts and limits
Instrumentation adds execution and recording overhead; this fixture does not benchmark it. Source and control-flow analysis scale with measured code, while retained coverage data scales with recorded locations. A percentage must be interpreted against the actual measured files.
Common Mistakes
- Coverage measures execution, not the strength of an assertion.
- Do not report a tiny fixture’s percentage as whole-service coverage.
Connected lessons
Hypothesis property tests: compare generated cases with an independent contract, Python unittest.mock: inject a collaborator failure before publication, Pytest fixtures: isolated files and parameterized rejection tests.
Check the next state boundary
Python mutation testing: prove a suite rejects selected wrong implementations.
