project-root/ ├── src/ │ └── calculator.py ├── tests/ │ ├── test_calculator.py │ ├── __init__.py │ └── conftest.py ├── pytest.ini ├── requirements.txt └── README.md
Branch coverage in PyTest - Framework Patterns
Start learning this pattern below
Jump into concepts and practice - no test required
- Source Code Layer (src/): Contains the application code to be tested, e.g.,
calculator.pywith functions having branches (if/else). - Test Layer (tests/): Contains test files like
test_calculator.pywhere pytest test functions verify different branches of the code. - Fixtures and Setup (conftest.py): Shared test setup or reusable fixtures for tests.
- Configuration (pytest.ini): Configures pytest options including coverage settings.
- Utilities (optional): Helper functions or test data if needed.
Use pytest.ini to configure coverage options for branch coverage:
[pytest] addopts = --cov=src --cov-branch --cov-report=term-missing
This enables branch coverage measurement and shows missing branches in the terminal report.
For environment-specific settings (like test vs. dev), use environment variables or separate config files loaded in conftest.py.
- Use
pytest-covplugin to generate coverage reports including branch coverage. - Reports can be output as terminal summary, HTML, XML (for CI tools).
- Integrate with CI/CD pipelines (GitHub Actions, Jenkins, GitLab CI) to run tests and fail builds if branch coverage drops below threshold.
- Example GitHub Actions step to run tests with coverage:
- name: Run tests with coverage run: | pytest --cov=src --cov-branch --cov-report=xml
- Write tests for all decision points: Ensure tests cover both true and false branches of if/else statements.
- Use pytest-cov plugin: It integrates smoothly with pytest and supports branch coverage.
- Keep tests small and focused: Each test should verify one branch or behavior to isolate failures.
- Fail build on coverage drop: Enforce minimum branch coverage thresholds in CI to maintain quality.
- Use clear naming: Name tests to reflect which branch or condition they cover for easy maintenance.
Where in this folder structure would you add a new test to verify the false branch of a conditional in the calculator.py file?
Practice
What does branch coverage measure in pytest testing?
Solution
Step 1: Understand branch coverage concept
Branch coverage ensures every possible path in decision points (like if-else) is tested.Step 2: Compare with other coverage types
Line coverage counts executed lines, but branch coverage focuses on decision paths.Final Answer:
It checks if all decision paths in the code are tested. -> Option AQuick Check:
Branch coverage = all decision paths tested [OK]
- Confusing branch coverage with line coverage
- Thinking it counts test cases
- Assuming it checks syntax errors
Which pytest command option enables branch coverage measurement?
Solution
Step 1: Recall pytest coverage options
The option--covenables coverage measurement, and--cov-branchadds branch coverage.Step 2: Identify correct combined command
Both options must be used together aspytest --cov --cov-branchto measure branch coverage.Final Answer:
pytest --cov --cov-branch -> Option AQuick Check:
Use --cov with --cov-branch for branch coverage [OK]
- Using only --cov-branch without --cov
- Typing incorrect option names
- Assuming branch coverage is default
Given this code snippet tested with pytest and branch coverage enabled, what is the branch coverage result?
def check_num(x):
if x > 0:
return "Positive"
else:
return "Non-positive"
# Test cases:
assert check_num(5) == "Positive"
Solution
Step 1: Identify branches in the code
The function has two branches: one for x > 0 and one for else (x ≤ 0).Step 2: Check which branches are tested
The test calls check_num(5), which covers only the x > 0 branch, missing the else branch.Final Answer:
50% branch coverage -> Option DQuick Check:
One branch tested out of two = 50% [OK]
- Assuming one test covers all branches
- Confusing line coverage with branch coverage
- Ignoring else branch testing
Identify the error in this pytest test that aims for full branch coverage:
def classify(n):
if n > 10:
return "High"
elif n > 5:
return "Medium"
else:
return "Low"
def test_classify():
assert classify(12) == "High"
assert classify(7) == "Medium"
Solution
Step 1: Analyze branches in classify()
There are three branches: n > 10, n > 5, and else (n ≤ 5).Step 2: Check test coverage of branches
Tests cover n=12 (High) and n=7 (Medium), but no test covers n ≤ 5 (Low) branch.Final Answer:
Missing test for the else branch (n ≤ 5). -> Option CQuick Check:
All branches need tests for full coverage [OK]
- Assuming two tests cover all branches
- Looking for syntax errors where none exist
- Ignoring else branch testing
You have this function. Which set of test inputs achieves 100% branch coverage?
def analyze_score(score):
if score >= 90:
return "A"
elif score >= 75:
return "B"
else:
return "C"
Solution
Step 1: Identify all branches
Branches: score ≥ 90 ("A"), score ≥ 75 ("B"), else "C".Step 2: Check which inputs cover all branches
Input 95 covers "A" branch; 80 covers score ≥ 75 ("B"); 70 covers else "C" branch. This covers all branches.Final Answer:
[95, 80, 70] -> Option BQuick Check:
Test inputs cover all if-elif-else paths [OK]
- Missing coverage for one of the branches
- Choosing inputs that skip else branch
- Assuming close values cover all branches
