-
Notifications
You must be signed in to change notification settings - Fork 399
Description
π§ Chore Summary β Add mutation testing with mutmut for test quality validation
Implement mutation testing using mutmut to measure and improve test suite quality beyond traditional code coverage. Add Makefile targets and GitHub Actions integration to automatically detect weak assertions, missing edge cases, and untested logic paths through systematic code mutations.
π§± Areas Affected
- Makefile β new mutation testing targets
- GitHub Actions β test quality validation workflow
- Test suite quality β improved assertion coverage
- CI/CD pipeline β mutation score quality gates
- Documentation β mutation testing guide
- pyproject.toml β mutmut configuration
βοΈ Context / Rationale
What is Mutation Testing?
Traditional code coverage tells you which lines executed, but not whether your tests would catch bugs on those lines. Mutation testing solves this by automatically creating tiny, systematic code changes ("mutants") and re-running your test suite:
# Original code
def calculate_discount(price, percentage):
if percentage > 0: # Mutant: change > to >=
return price * (1 - percentage) # Mutant: change - to +
return price # Mutant: return 0
# Example mutations mutmut creates:
# 1. `percentage > 0` β `percentage >= 0`
# 2. `1 - percentage` β `1 + percentage`
# 3. `return price` β `return 0`Mutation Results:
- Killed mutant = Tests failed β (your tests caught the bug)
- Survived mutant = Tests passed β (potential gap in test coverage)
Why mutmut?
mutmut is a fast, Python-native mutation testing tool that:
- Integrates seamlessly with
pytest(our existing test runner) - Provides incremental testing (only re-runs tests for changed files)
- Supports coverage-guided mutations (only mutate covered lines)
- Offers rich CLI with detailed reporting (
mutmut results,mutmut html) - Easily configurable via
pyproject.tomlfor CI integration
Example workflow:
# Run mutation testing
mutmut run --paths-to-mutate=mcpgateway
# View results
mutmut results # Show summary: 47/50 killed (94% mutation score)
# Examine survivors
mutmut show 3 # Inspect specific surviving mutant
# Generate HTML report
mutmut html # Browse detailed results in browserA high mutation score (>80%) indicates robust tests that catch real bugs, while survivors reveal weak assertions and missing edge cases.
π¦ New & Updated Make Targets
| Target | Purpose |
|---|---|
make mutmut-install |
Install mutmut in development virtualenv |
make mutmut-run |
Run mutation testing on mcpgateway package with coverage guidance |
make mutmut-results |
Display mutation testing summary and surviving mutants |
make mutmut-html |
Generate browsable HTML report of mutation results |
make mutmut-ci |
CI-friendly mutation testing with score threshold enforcement |
Existing test targets remain: test, coverage, pytest-examples.
π Acceptance Criteria
-
make mutmut-runexecutes mutation testing onmcpgateway/package - Mutation score baseline established (aim for >75% initially, >85% target)
-
make mutmut-htmlgenerates browsable HTML report showing survivors - GitHub Actions runs mutation testing and fails if score drops below threshold
- Configuration in
pyproject.tomlexcludes test files and migrations - All existing tests (
make test,make coverage) stay green - Documentation explains mutation testing workflow and interpreting results
π οΈ Task List
-
Add mutmut configuration
# pyproject.toml [tool.mutmut] paths_to_mutate = "mcpgateway/" backup = false runner = "python -m pytest" tests_dir = "tests/" cache_only = true coverage = true mutation_score_threshold = 75 # Exclude patterns exclude = [ "mcpgateway/migrations/*", "mcpgateway/__init__.py", "mcpgateway/version.py" ]
-
Add Makefile targets
.PHONY: mutmut-install mutmut-run mutmut-results mutmut-html mutmut-ci mutmut-install: @echo "π₯ Installing mutmut..." @$(VENV_DIR)/bin/pip install mutmut mutmut-run: mutmut-install @echo "𧬠Running mutation testing..." @$(VENV_DIR)/bin/mutmut run --paths-to-mutate mcpgateway mutmut-results: @echo "π Mutation testing results:" @$(VENV_DIR)/bin/mutmut results mutmut-html: @echo "π Generating HTML mutation report..." @$(VENV_DIR)/bin/mutmut html @echo "Report available at: file://$(PWD)/html/index.html" mutmut-ci: @echo "π CI mutation testing with threshold check..." @$(VENV_DIR)/bin/mutmut run --ci --paths-to-mutate mcpgateway
-
GitHub Actions integration
- Add mutation testing job to existing test workflow
- Cache mutmut results between runs for faster CI
- Configure failure threshold (75% minimum mutation score)
- Generate mutation report artifact for download
-
Baseline establishment
- Run initial
make mutmut-runto establish current mutation score - Identify and fix obvious surviving mutants (weak assertions)
- Set realistic initial threshold based on current score
- Run initial
-
Test suite improvements
- Add missing edge case tests for surviving mutants
- Strengthen assertions (e.g.,
assert resultβassert result == expected) - Add boundary condition tests revealed by mutations
-
Documentation
- Add mutation testing section to testing documentation
- Explain how to interpret mutation results and fix survivors
- Document workflow for investigating failing mutants
-
Performance optimization
- Configure coverage-guided mutations to reduce runtime
- Set up incremental mutation testing for faster development
- Cache mutmut database for CI performance
-
Final validation
-
make mutmut-run && make mutmut-results - Verify HTML report generation and browsability
- Test GitHub Actions workflow with mutation score threshold
-
π References
- mutmut GitHub β https://github.com/boxed/mutmut
- mutmut Documentation β https://mutmut.readthedocs.io/
- Mutation Testing Guide β https://en.wikipedia.org/wiki/Mutation_testing
- pytest Integration β https://mutmut.readthedocs.io/en/latest/index.html#running-mutmut
π§© Additional Notes
- Start conservative: Begin with 75% threshold and gradually increase to 85%+
- Incremental adoption: Focus on core business logic first (tools, resources, prompts)
- Pragmatic exemptions: Use
# pragma: no mutatefor intentionally untested code - Performance consideration: Mutation testing is slower than unit tests - optimize with coverage guidance
- CI integration: Run on PRs but consider making it a non-blocking check initially
- Common mutations:
>to>=,andtoor,+to-, method calls removed, return values changed - Interpreting survivors: Each surviving mutant represents a potential bug your tests wouldn't catch