test-suite-prioritizer
Test Suite Prioritizer
Intelligently prioritize test execution based on code changes and project impact.
Core Capabilities
This skill helps optimize test execution by:
- Analyzing code changes - Identifying which files were modified
- Mapping test coverage - Determining which tests cover changed code
- Calculating priority scores - Ranking tests by impact and relevance
- Generating execution order - Creating an optimized test run sequence
- Providing reasoning - Explaining why each test is prioritized
Test Prioritization Workflow
Step 1: Identify Code Changes
Determine what code has been modified to focus testing efforts.
Sources of Change Information:
- Git diff (most recent commit or uncommitted changes)
- Pull request file list
- Specific files mentioned by user
- Modified files in working directory
Collect Changed Files:
# Recent commit changes
git diff --name-only HEAD~1 HEAD
# Uncommitted changes
git diff --name-only
# Changes in current branch vs main
git diff --name-only main...HEAD
# Files in last N commits
git diff --name-only HEAD~N HEAD
Example Output:
src/auth/login.py
src/payment/processor.py
src/models/user.py
tests/test_auth.py
Step 2: Analyze Test Coverage
Map which tests cover the changed code.
Strategies:
1. Direct Test-to-Code Mapping
- Tests in same directory as changed code
- Tests with similar names (e.g.,
user.py→test_user.py) - Integration tests that import changed modules
2. Static Analysis
- Parse test files for imports
- Identify which modules each test uses
- Map dependencies transitively
3. Coverage Data (if available)
- Use pytest-cov, coverage.py, JaCoCo output
- Identify tests that execute changed lines
- Most accurate but requires prior test run
Example Mapping:
Changed: src/auth/login.py
Covered by:
- tests/test_auth.py::test_login_success
- tests/test_auth.py::test_login_failure
- tests/integration/test_user_flow.py::test_complete_registration
- tests/e2e/test_authentication_flow.py::test_full_auth_cycle
Changed: src/payment/processor.py
Covered by:
- tests/test_payment.py::test_process_payment
- tests/test_payment.py::test_refund
- tests/integration/test_checkout.py::test_complete_purchase
Step 3: Calculate Priority Scores
Assign priority scores based on change impact.
Scoring Formula:
Priority Score = Base Score × Change Impact Factor
Base Score factors:
- Direct coverage of changed file: +10 points
- Indirect coverage (imports changed file): +5 points
- Integration test covering changed area: +3 points
- Test in same module: +2 points
Change Impact Factor (multiply):
- Critical path code (auth, payments): ×1.5
- Recently failed test: ×1.3
- High historical failure rate: ×1.2
- Core business logic: ×1.2
- UI/cosmetic changes: ×0.8
Example Scoring:
# Example: test_login_success
base_score = 10 # Directly tests login.py (changed)
impact_factor = 1.5 # Auth is critical path
priority_score = 10 × 1.5 = 15
# Example: test_user_flow
base_score = 5 + 3 # Imports login.py + integration test
impact_factor = 1.2 # Core business logic
priority_score = 8 × 1.2 = 9.6
# Example: test_ui_styling
base_score = 2 # Same module as changed file
impact_factor = 0.8 # UI/cosmetic
priority_score = 2 × 0.8 = 1.6
Step 4: Generate Prioritized Test List
Create ordered execution sequence with scores and reasoning.
Output Format:
# Test Execution Priority List
## Summary
- Total tests analyzed: 45
- High priority (score ≥ 10): 8 tests
- Medium priority (score 5-9): 15 tests
- Low priority (score < 5): 22 tests
- Estimated time for high priority tests: ~2 minutes
## Recommended Execution Order
### Priority 1: Critical Tests (Run First)
1. **tests/test_auth.py::test_login_success** (Score: 15.0)
- Directly tests modified file: src/auth/login.py
- Critical path: Authentication
- Reason: Core security functionality changed
2. **tests/test_auth.py::test_login_failure** (Score: 15.0)
- Directly tests modified file: src/auth/login.py
- Critical path: Authentication
- Reason: Error handling for authentication changed
3. **tests/test_payment.py::test_process_payment** (Score: 15.0)
- Directly tests modified file: src/payment/processor.py
- Critical path: Payment processing
- Reason: Payment logic modified, high business impact
### Priority 2: High Impact Tests
4. **tests/integration/test_user_flow.py::test_complete_registration** (Score: 9.6)
- Indirect coverage: Imports src/auth/login.py
- Integration test: End-to-end user flow
- Reason: Validates auth changes in realistic scenario
5. **tests/integration/test_checkout.py::test_complete_purchase** (Score: 9.6)
- Indirect coverage: Imports src/payment/processor.py
- Integration test: Full checkout flow
- Reason: Validates payment changes with real workflow
6. **tests/test_models.py::test_user_model** (Score: 7.0)
- Related file: src/models/user.py modified
- Dependency: Auth and payment depend on user model
- Reason: Foundation for changed functionality
### Priority 3: Supporting Tests
7. **tests/test_validators.py::test_email_validation** (Score: 4.0)
- Indirect dependency: Used by auth module
- Reason: Input validation for authentication
8. **tests/e2e/test_authentication_flow.py::test_full_auth_cycle** (Score: 3.9)
- E2E coverage: Complete authentication flow
- Reason: Comprehensive validation but slow to execute
[... remaining tests with lower scores ...]
## Quick Commands
Run high priority tests only (8 tests, ~2 min):
```bash
pytest tests/test_auth.py::test_login_success \
tests/test_auth.py::test_login_failure \
tests/test_payment.py::test_process_payment \
tests/integration/test_user_flow.py::test_complete_registration \
tests/integration/test_checkout.py::test_complete_purchase \
tests/test_models.py::test_user_model \
tests/test_validators.py::test_email_validation \
tests/e2e/test_authentication_flow.py::test_full_auth_cycle
Run critical tests only (3 tests, ~30 sec):
pytest tests/test_auth.py tests/test_payment.py::test_process_payment
Time Estimates
- Critical tests (3): ~30 seconds
- High priority tests (8): ~2 minutes
- All prioritized tests (23): ~5 minutes
- Full test suite (45): ~15 minutes
Recommendations
- Pre-commit: Run critical tests (score ≥ 15) before committing
- CI fast lane: Run high priority tests (score ≥ 9) in first stage
- Full validation: Run all tests in parallel after merge
### Step 5: Handle Special Cases
Adjust prioritization for specific scenarios.
**Time-Constrained Testing:**
```markdown
## 1-Minute Quick Check (Top 3 Critical Tests)
pytest tests/test_auth.py::test_login_success \
tests/test_auth.py::test_login_failure \
tests/test_payment.py::test_process_payment
These cover the most critical changed functionality.
Post-Refactoring:
## Post-Refactor Validation
Changed file: src/utils/helpers.py (used by 25 modules)
Priority:
1. All tests directly importing helpers.py (18 tests)
2. Integration tests using helper functions (8 tests)
3. Tests in dependent modules (25 tests)
Reason: Wide-reaching refactor requires comprehensive validation.
Flaky Test Handling:
## Note: Flaky Tests Detected
The following tests have high failure rates but low priority scores:
- tests/test_cache.py::test_concurrent_access (30% failure rate)
- tests/test_api.py::test_rate_limiting (25% failure rate)
Recommendation:
- Fix flaky tests before relying on prioritization
- Consider quarantining or mocking timing-dependent code
Step 6: Provide Execution Guidance
Offer practical commands and strategies.
For CI/CD Pipelines:
# .github/workflows/ci.yml example
jobs:
quick-tests:
name: Critical Tests (Fast Feedback)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run critical tests
run: |
# Run tests with score ≥ 15 first
pytest -v tests/test_auth.py tests/test_payment.py
full-tests:
name: Complete Test Suite
runs-on: ubuntu-latest
needs: quick-tests # Only run if critical tests pass
steps:
- uses: actions/checkout@v2
- name: Run all tests
run: pytest
For Local Development:
# Pre-commit hook (.git/hooks/pre-commit)
#!/bin/bash
# Get changed files
changed_files=$(git diff --cached --name-only)
# Run prioritized tests for changed files
if echo "$changed_files" | grep -q "src/auth/"; then
pytest tests/test_auth.py || exit 1
fi
if echo "$changed_files" | grep -q "src/payment/"; then
pytest tests/test_payment.py || exit 1
fi
For Selective Test Execution:
# pytest conftest.py - custom marker
import pytest
def pytest_collection_modifyitems(config, items):
# Mark tests based on priority
for item in items:
if "test_auth" in item.nodeid or "test_payment" in item.nodeid:
item.add_marker(pytest.mark.critical)
# Run only critical tests
# pytest -m critical
Prioritization Strategies
Strategy 1: Code Change Impact (Primary)
Focus on tests covering modified code:
- Direct coverage - Tests that explicitly test changed files
- Indirect coverage - Tests that import/use changed modules
- Dependency coverage - Tests for code that depends on changes
When to use:
- After code modifications
- Pre-commit validation
- Pull request testing
Strategy 2: Risk-Based Prioritization
Prioritize based on business and technical risk:
High Risk Areas:
- Authentication and authorization
- Payment processing
- Data integrity (database operations)
- Security-critical functions
- APIs and public interfaces
Medium Risk Areas:
- Business logic
- User workflows
- Data validation
- Email/notification systems
Low Risk Areas:
- UI cosmetics
- Logging
- Internal utilities
- Development tools
Strategy 3: Failure History
Prioritize tests that fail often:
# Example: Analyze test failure history from CI
# tests with >10% historical failure rate get boosted priority
Historical Failures:
- test_concurrent_access: 12 failures / 100 runs = 12% → Priority boost ×1.2
- test_database_connection: 5 failures / 100 runs = 5% → No boost
Strategy 4: Execution Time Optimization
Balance coverage with speed:
Fast-First Strategy:
- Run quick unit tests first (< 1 second each)
- Get rapid feedback on basic functionality
- Then run slower integration/E2E tests
Critical-First Strategy:
- Run most important tests first regardless of speed
- Better for catching major issues early
- May take longer for initial feedback
Hybrid Approach (Recommended):
- Run quick critical tests first (best of both worlds)
- Then slow critical tests
- Then fast non-critical tests
- Finally slow non-critical tests
Analyzing Different Project Types
Python (pytest)
Analyze test structure:
# Find all test files
find . -name "test_*.py" -o -name "*_test.py"
# Get test functions
pytest --collect-only -q
# Analyze imports in tests
grep -r "^import\|^from" tests/
JavaScript/TypeScript (Jest)
Analyze test structure:
# Find test files
find . -name "*.test.js" -o -name "*.spec.js"
# Get test list
npm test -- --listTests
# Analyze coverage
npm test -- --coverage --coverageReporters=json
Java (JUnit)
Analyze test structure:
# Find test classes
find . -name "*Test.java"
# Run with verbose output
mvn test -X
# Get test reports
cat target/surefire-reports/*.xml
Best Practices
- Update prioritization regularly - Re-analyze when code structure changes significantly
- Combine with coverage tools - Use actual coverage data when available
- Consider test stability - Deprioritize flaky tests or fix them first
- Balance speed and coverage - Don't sacrifice important slow tests
- Communicate reasoning - Explain why tests are prioritized to team
- Adjust for context - Pre-commit vs. CI vs. nightly runs need different priorities
- Monitor effectiveness - Track if prioritized tests catch bugs earlier
- Keep it simple - Start with basic change-impact prioritization
- Document critical paths - Maintain list of high-priority areas
- Automate where possible - Integrate into CI/CD workflows
Example Scenarios
Scenario 1: Pre-Commit Validation
Context: Developer modified src/auth/login.py
Prioritization:
Top 3 tests to run (30 seconds):
1. tests/test_auth.py::test_login_success
2. tests/test_auth.py::test_login_failure
3. tests/test_auth.py::test_session_creation
Reasoning: Direct tests of changed functionality, fast execution.
Scenario 2: CI/CD Fast Lane
Context: Pull request with 15 files changed across 3 modules
Prioritization:
Stage 1 - Critical Tests (2 min):
- All auth tests (5 tests)
- All payment tests (4 tests)
- Core user model tests (3 tests)
Stage 2 - Integration Tests (5 min):
- User flow integration (8 tests)
- API integration (6 tests)
Stage 3 - Full Suite (parallel, 10 min):
- Remaining tests (120 tests)
Reasoning: Fast feedback on critical paths, comprehensive validation in parallel.
Scenario 3: Time-Constrained Testing
Context: 5 minutes before deadline, need to validate changes
Prioritization:
Must-run tests (2 min):
1. Tests directly covering changed files (8 tests)
2. Integration tests for critical paths (4 tests)
Nice-to-run tests (3 min):
3. Related unit tests (15 tests)
Skip for now:
- E2E tests (too slow)
- Unrelated tests (no impact)
Reasoning: Maximum validation coverage in minimum time.
Resources
references/prioritization_algorithms.md- Detailed algorithms and formulas for calculating priority scoresreferences/framework_guides.md- Framework-specific commands for test analysis (pytest, jest, junit, etc.)
Quick Reference
| Scenario | Priority Strategy | Recommended Tests |
|---|---|---|
| Pre-commit | Code change impact | Direct tests of modified files |
| CI fast lane | Critical path + changes | High-priority + change-impacted |
| Time-limited | Highest scores only | Top 10-20 by priority score |
| Post-refactor | Wide coverage | All tests touching refactored code |
| Nightly build | Full comprehensive | All tests (no prioritization) |