test-optimization
Analyze test suites for speed bottlenecks, redundancy, and DRY violations. Use when tests are slow, duplicated, or need refactoring.
When & Why to Use This Skill
This Claude skill is designed to optimize software test suites by identifying performance bottlenecks, eliminating redundant test cases, and applying DRY (Don't Repeat Yourself) principles. It helps engineering teams reduce CI/CD wait times and improve code maintainability by transforming slow, repetitive tests into a streamlined, efficient validation process.
Use Cases
- Performance Bottleneck Analysis: Identifying slow tests caused by database I/O, external API calls, or complex computations and providing specific mocking or caching strategies to accelerate execution.
- Test Suite Refactoring: Detecting 'Copy-Paste' patterns and repeated setup code to recommend the implementation of fixtures, parameterized tests, and helper functions.
- Redundancy Reduction: Analyzing semantic overlap and logical subsumption to remove duplicate test coverage, ensuring the suite remains lean without sacrificing quality.
- CI/CD Optimization: Helping teams meet strict feedback loop targets (e.g., keeping total suite duration under 30 seconds) by prioritizing high-impact speed fixes.
| name | test-optimization |
|---|---|
| description | Analyze test suites for speed bottlenecks, redundancy, and DRY violations. Use when tests are slow, duplicated, or need refactoring. |
Test Optimization
You analyze and optimize test suites for speed, maintainability, and clarity.
Speed Analysis
Slow Test Causes
| Cause | Symptom | Solution |
|---|---|---|
| Database calls | >50ms, I/O wait | Mock with fixtures |
| External API calls | >100ms, network | Mock responses |
| File I/O | >20ms per operation | In-memory or fixtures |
| Complex computation | CPU-bound | Cache or simplify |
| Sleep/wait | Explicit delays | Mock time |
Speed Targets
- Unit tests: <50ms each
- Integration tests: <500ms each
- Total suite: <30s for fast feedback
Analysis Commands
# Python
pytest -v --durations=0 -m "not integration"
# JavaScript
vitest run --reporter=verbose
# Just command (if available)
just slowtests 50
Redundancy Detection
Semantic Overlap
Tests with >70% similar assertions:
# Redundant: Test B is subset of Test A
# Test A: validates email with 5 formats
# Test B: validates email with 3 formats (subset of A)
# -> Test B is subsumed by Test A
Logical Subsumption
Integration test covers unit test cases:
# Integration test: POST /users validates email
# Unit test: validate_email() checks formats
# -> If integration covers all formats, unit may be redundant
Copy-Paste Detection
70% code similarity between tests
- Repeated setup code across tests
- Duplicate assertions
DRY Analysis
Fixture Candidates
Repeated object creation:
# Before: Repeated in each test
def test_user_valid():
user = User(name="Test", email="test@test.com")
...
def test_user_invalid():
user = User(name="Test", email="invalid")
...
# After: Fixture
@pytest.fixture
def base_user():
return User(name="Test", email="test@test.com")
Parameterization Opportunities
Similar tests with different inputs:
# Before: Multiple tests
def test_email_valid():
assert validate("test@test.com")
def test_email_invalid():
assert not validate("invalid")
# After: Parameterized
@pytest.mark.parametrize("email,expected", [
("test@test.com", True),
("invalid", False),
])
def test_email_validation(email, expected):
assert validate(email) == expected
Helper Function Candidates
Repeated assertion patterns:
# Before: Repeated assertions
def test_a():
assert result.status == "success"
assert result.data is not None
assert result.errors == []
# After: Helper
def assert_success(result):
assert result.status == "success"
assert result.data is not None
assert result.errors == []
Categorization
Speed Issues
mock_opportunities- External calls to mockin_memory_db- Use SQLite in-memoryfixture_optimization- Reduce setup timecomputation_simplification- Algorithm improvements
Redundancy Issues
semantic_overlap- Similar test coveragelogical_subsumption- Integration covers unitcopy_paste- Duplicated test code
DRY Issues
fixture_candidates- Repeated setupparameterize_candidates- Similar tests, different inputshelper_candidates- Repeated assertions
Prioritization
Impact Score (0-10):
- Speed:
(current_ms - target_ms) / current_ms * 10 - Maintainability:
lines_saved / 10 - Test reduction:
tests_removed * 2
Complexity Score (0-10):
- Speed fixes: Low (2-3) if mocking, High (7-8) if redesign
- Redundancy removal: Low (2-3) - just delete
- DRY improvements: Medium (4-6) - refactoring
Priority: impact / (complexity + 1)
Output Format
Test Optimization Analysis
==========================
Module: {path}
Tests: {count} | Duration: {total}ms | Avg: {avg}ms
Speed Issues ({count}):
- test_foo: 245ms (database calls) -> mock fixtures
- test_bar: 180ms (external API) -> mock responses
Redundancy Issues ({count}):
- test_email_valid subsumed by test_user_create
- test_a and test_b: 85% similar assertions
DRY Opportunities ({count}):
- Parameterize: test_format_* (5 tests -> 1)
- Fixture: user setup in 8 tests
- Helper: success assertion in 12 tests
Priority Order:
1. [High] Mock database in test_validation.py
2. [Medium] Parameterize format tests
3. [Low] Extract user fixture
Safeguards
When optimizing:
- Never remove tests without verifying coverage maintained
- Ensure all original assertions still pass
- Run
just check-allafter changes - Maintain 96% coverage threshold