TestIQ - Intelligent test analysis for finding duplicate and redundant tests using coverage analysis
Project description
TestIQ - Intelligent Test Analysis
TestIQ v0.2.2 - Catch duplicate and redundant tests before they pollute your codebase. Perfect for AI-generated test suites.
๐ค Why TestIQ? The AI Testing Problem
AI coding assistants (GitHub Copilot, Cursor, ChatGPT) generate tests fast - but they create duplicate and redundant tests that bloat your test suite.
The Problem
# AI generates these 5 tests - all testing the same thing!
def test_addition(): # AI suggestion 1
assert calc.add(2, 3) == 5
def test_add_numbers(): # AI suggestion 2
assert calc.add(2, 3) == 5
def test_sum_calculation(): # AI suggestion 3
assert calc.add(2, 3) == 5
def test_calculate_sum(): # AI suggestion 4
assert calc.add(2, 3) == 5
def test_basic_addition(): # AI suggestion 5
assert calc.add(2, 3) == 5
The Solution
$ pytest --testiq-output=coverage.json
$ testiq analyze coverage.json
๐ TestIQ Analysis Results
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Total tests: 47
โ Exact duplicates: 39 (83% redundant!)
โ Subset duplicates: 168
โ Similar pairs: 45
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
TestIQ catches AI-generated duplicates automatically - before they waste your CI time! โก
๐ฏ Key Features
- ๐ฏ Duplicate Detection - Find exact duplicates, subsets, and similar tests
- ๐ค AI Test Quality Gate - Catch AI-generated redundancy in CI
- ๐ Visual Reports - Interactive HTML reports with side-by-side comparison
- ๐ฆ CI/CD Integration - Quality gates, baselines, and trend tracking
- โก Fast Analysis - Parallel processing for large test suites
- ๐งช pytest Plugin - Built-in plugin for seamless integration
๐ธ Screenshots
Exact Duplicates Detection
Side-by-Side Coverage Comparison
Subset Duplicates (Tests Completely Covered by Others)
Similar Test Detection
๐ฆ Installation
pip install testiq
๐ Quick Start
Option 1: pytest Plugin (Easiest - Recommended)
The pytest plugin automatically collects per-test coverage:
# Run tests with TestIQ coverage collection
pytest --testiq-output=coverage.json
# Analyze the results
testiq analyze coverage.json --format html --output report.html
Pro Tip: Add to your pytest config for automatic collection:
# pytest.ini
[pytest]
addopts = --testiq-output=coverage.json -v
Option 2: Try the AI Demo
See real AI-generated test redundancy in action:
cd examples/ai-generated-tests
pytest --testiq-output=coverage.json
testiq analyze coverage.json --format html --output ai-test-report.html
Demo Results:
- 54 tests โ 39 exact duplicates (72% redundant!)
- 168 subset relationships
- 45 similar test pairs
- Only 15 tests actually needed โ
Analysis Options
Similarity Threshold (--threshold):
| Value | Meaning | Use Case |
|---|---|---|
| 0.3 (default) | 30% overlap | Development - catch most duplicates |
| 0.5 | 50% overlap | CI/CD - balanced detection |
| 0.7 | 70% overlap | Production - strict quality gate |
| 0.9 | 90% overlap | Very strict - only near-identical tests |
# Strict analysis (only flag tests with 70%+ overlap)
testiq analyze coverage.json --threshold 0.7
# Lenient analysis (flag tests with 20%+ overlap)
testiq analyze coverage.json --threshold 0.2
See Configuration Guide for all options.
๐ CLI Reference
Quick Start
See it in action immediately:
# Run demo with sample data
testiq demo
Generate per-test coverage data:
TestIQ needs per-test coverage (which lines each test executes). Use our pytest plugin:
# Run tests with TestIQ plugin (easiest method - recommended)
pytest --testiq-output=testiq_coverage.json
# Or specify your test directory
pytest tests/ --testiq-output=testiq_coverage.json
# Then analyze with TestIQ
testiq analyze testiq_coverage.json --format html --output report.html
Alternative methods:
# Method 2: Use pytest coverage contexts (requires pytest-cov)
pytest --cov=src --cov-context=test --cov-report=json
python -m testiq.coverage_converter coverage.json --with-contexts -o testiq_coverage.json
# Method 3: Convert standard pytest coverage (limited - aggregated only)
pytest --cov=src --cov-report=json
python -m testiq.coverage_converter coverage.json -o testiq_coverage.json
Manual sample data:
# Create sample coverage data (for testing)
cat > testiq_coverage.json << 'EOF'
{
"test_login_success": {
"auth.py": [10, 11, 12, 15, 20, 25],
"user.py": [5, 6, 7, 8]
},
"test_login_failure": {
"auth.py": [10, 11, 12, 15, 16],
"user.py": [5, 6]
}
}
EOF
# Analyze the sample data
testiq analyze testiq_coverage.json
๐ See Pytest Integration Guide for complete setup instructions
CLI Usage
Global Options
# Check version
testiq --version
# Use custom config file
testiq --config my-config.yaml analyze testiq_coverage.json
# Set log level
testiq --log-level DEBUG analyze testiq_coverage.json
# Save logs to file
testiq --log-file testiq.log analyze testiq_coverage.json
# Run demo with sample data
testiq demo
1. Analyze Your Tests
# Basic analysis with terminal output (text format)
testiq analyze testiq_coverage.json
# With custom similarity threshold (default: 0.3)
testiq analyze testiq_coverage.json --threshold 0.8
# Generate beautiful HTML report
testiq analyze testiq_coverage.json --format html --output reports/report.html
# CSV export for spreadsheet analysis
testiq analyze testiq_coverage.json --format csv --output reports/results.csv
# JSON output for automation
testiq analyze testiq_coverage.json --format json --output reports/results.json
# Markdown format
testiq analyze testiq_coverage.json --format markdown --output reports/results.md
# Get quality score and recommendations
testiq quality-score testiq_coverage.json --output reports/quality.txt
2. CI/CD Integration
# Quality gates (exit code 2 if failed, 1 if duplicates found, 0 if success)
testiq analyze testiq_coverage.json --quality-gate --max-duplicates 5
# Save baseline for future comparisons
testiq analyze testiq_coverage.json --save-baseline my-baseline
# Compare against baseline (fail if quality worsens)
testiq analyze testiq_coverage.json --quality-gate --baseline my-baseline
# Combined: quality gate with threshold and baseline
testiq analyze testiq_coverage.json \
--quality-gate \
--max-duplicates 5 \
--threshold 0.8 \
--baseline production \
--format html \
--output reports/ci-report.html
# Manage baselines
testiq baseline list # List all saved baselines
testiq baseline show my-baseline # Show baseline details
testiq baseline delete old-baseline # Delete a baseline
GitHub Actions Example:
name: Test Quality Gate
on: [pull_request]
jobs:
test-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install testiq pytest
- name: Run tests with TestIQ
run: pytest --testiq-output=coverage.json
- name: Check for AI-generated duplicates
run: |
testiq analyze coverage.json \
--quality-gate \
--max-duplicates 0 \
--format html \
--output testiq-report.html
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: testiq-report
path: testiq-report.html
3. Python API
from testiq.analyzer import CoverageDuplicateFinder
import json
# Create analyzer with performance options
finder = CoverageDuplicateFinder(
enable_parallel=True,
max_workers=4,
enable_caching=True
)
# Load coverage data
with open('coverage.json') as f:
coverage_data = json.load(f)
# Add test coverage
for test_name, test_coverage in coverage_data.items():
finder.add_test_coverage(test_name, test_coverage)
# Find issues
exact_duplicates = finder.find_exact_duplicates()
subset_duplicates = finder.find_subset_duplicates()
similar_tests = finder.find_similar_coverage(threshold=0.8)
# Generate reports
from testiq.reporting import HTMLReportGenerator
html_gen = HTMLReportGenerator(finder)
html_gen.generate(Path("reports/report.html"), threshold=0.8)
# Quality analysis
from testiq.analysis import QualityAnalyzer
analyzer = QualityAnalyzer(finder)
score = analyzer.calculate_score(threshold=0.8)
print(f"Quality Score: {score.overall_score}/100 (Grade: {score.grade})")
4. Examples & Testing
See complete working examples:
- ๐ Python API Examples - Complete demonstration of all features
- ๐ Bash Examples - Quick CLI testing scripts
- ๐ CI/CD Examples - Jenkins & GitHub Actions integration
- ๐ Manual Testing Guide - Comprehensive testing guide
CI/CD Integration:
- Jenkinsfile Example - Complete Jenkins pipeline with quality gates
- GitHub Actions Example - Full workflow with error handling
Next Steps
- Try the demo:
testiq demo - Analyze your tests:
testiq analyze coverage.json - Run examples:
python examples/python/manual_test.py - Integrate with CI/CD: See examples/cicd/
๏ฟฝ Understanding TestIQ Results
Quality Score Components
TestIQ calculates a comprehensive quality score (0-100) with letter grade (A+ to F):
- Duplication Score (40%) - Based on exact duplicates found
- Coverage Efficiency (30%) - Tests with broad vs. narrow coverage
- Uniqueness Score (30%) - Based on similar/subset tests
Important Notes:
- Coverage Efficiency requires source metadata - Use
pytest --covwith--cov-report=jsonto generate.coveragefile with source line info - Without source metadata, efficiency score is 0 - This lowers overall grade but doesn't indicate actual problems
- Run
make test-completeor sequential coverage+TestIQ analysis for full scoring
Interpreting Duplicate Detection
TestIQ uses coverage-based duplicate detection - it identifies tests that execute the same code paths. This can include:
True Duplicates (Should Review):
- โ Multiple tests with identical coverage and same purpose
- โ Copy-pasted tests with minor naming differences
- โ Tests that add no unique code coverage value
False Positives (Expected Behavior):
- โ ๏ธ Tests with same coverage but different assertions/logic
- โ ๏ธ Tests that exercise different input values (same code path)
- โ ๏ธ Tests focused on behavior verification vs. code coverage
Example: Two tests that both create a dataclass instance will show identical coverage (import paths), but one might test validation while another tests defaults - both are valuable!
Recommendations:
- Review high-priority duplicates first - These have highest impact
- Check test intent, not just coverage - Different assertions mean different value
- Focus on exact duplicates - Subset/similar tests may be intentional
- Use quality score as a guide - Not an absolute metric
- Combine with test execution time - Slow duplicate tests are higher priority
Running Complete Analysis
For best results, run coverage and duplicate detection separately:
# Option 1: Use make target (recommended)
make test-complete
# Option 2: Run manually
pytest --cov=testiq --cov-report=term --cov-report=html # Coverage first
pytest --testiq-output=testiq_coverage.json -q # TestIQ second
testiq analyze testiq_coverage.json --format html --output reports/duplicates.html
# Option 3: Use provided script
./run_complete_analysis.sh
Why separate runs? Python's sys.settrace() allows only ONE active tracer. Running both together causes conflicts (19% coverage vs 81% separate).
๐ก Why TestIQ?
The Numbers Speak
- ๐ 72% test reduction in AI-generated test suites
- โก Faster CI/CD - Remove slow duplicate tests
- ๐ฐ Lower costs - Less CI compute time
- ๐ฏ Better quality - Focus on unique, valuable tests
- ๐ค AI-proof - Catch redundant tests before merge
Perfect For Teams Using
- โ GitHub Copilot
- โ Cursor AI
- โ ChatGPT for testing
- โ Any AI code assistant
- โ TDD workflows
- โ Large test suites
๐ What's Next?
- Try the demo:
cd examples/ai-generated-tests && pytest --testiq-output=coverage.json - Add to your CI: See GitHub Actions example above
- Share your results: Open an issue to share your test reduction story!
- Star the repo: Help others discover TestIQ โญ
๐ Documentation
Essential Reading
| Document | Description |
|---|---|
| Interpreting Results | Understanding TestIQ scores and recommendations |
| Pytest Integration | Generate per-test coverage data |
| Configuration | Config file options (.testiq.toml/.testiq.yaml) |
| CLI Reference | Command-line interface docs |
| API Reference | Python API documentation |
| CHANGELOG | v0.2.0 release notes |
Additional Resources
- Contributing Guide - How to contribute
- Security Policy - Vulnerability reporting
- Examples - Python, CI/CD, and sample data
๐ค Contributing
We welcome contributions! TestIQ is built by developers for developers. See CONTRIBUTING.md for guidelines.
๐ License
MIT License - see LICENSE for details.
๐ Security
For security vulnerabilities, see SECURITY.md for responsible disclosure.
โญ Star us on GitHub โ it helps!
Made with โค๏ธ for developers drowning in AI-generated tests
Report Bug โข Request Feature โข Documentation
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file testiq-0.2.2.tar.gz.
File metadata
- Download URL: testiq-0.2.2.tar.gz
- Upload date:
- Size: 79.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c09a22dc1dbd212a8513256f3c0d067ec2a09917db05d8c07d218c4edae8ca7e
|
|
| MD5 |
6886280d67945e1867380af6c3cf09c1
|
|
| BLAKE2b-256 |
21e564cb85bdee05fb6a091e8e1b964b41e864aa2a7378fe9c518c21d971949b
|
Provenance
The following attestation bundles were made for testiq-0.2.2.tar.gz:
Publisher:
release.yml on pydevtools/TestIQ
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
testiq-0.2.2.tar.gz -
Subject digest:
c09a22dc1dbd212a8513256f3c0d067ec2a09917db05d8c07d218c4edae8ca7e - Sigstore transparency entry: 833558708
- Sigstore integration time:
-
Permalink:
pydevtools/TestIQ@26ec8e395bb6f679e8e8f1bf249648b33361200a -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/pydevtools
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@26ec8e395bb6f679e8e8f1bf249648b33361200a -
Trigger Event:
release
-
Statement type:
File details
Details for the file testiq-0.2.2-py3-none-any.whl.
File metadata
- Download URL: testiq-0.2.2-py3-none-any.whl
- Upload date:
- Size: 91.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af72341105711332ee7838d2d8414777fbdc10480daa884bd1cc01a87b3b1cfb
|
|
| MD5 |
8db034f261d6852d196a6dcff5f72721
|
|
| BLAKE2b-256 |
5e68d6a03502330a97fe83c14e6ab54ebb7676d579be93c51e8c0773d3882345
|
Provenance
The following attestation bundles were made for testiq-0.2.2-py3-none-any.whl:
Publisher:
release.yml on pydevtools/TestIQ
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
testiq-0.2.2-py3-none-any.whl -
Subject digest:
af72341105711332ee7838d2d8414777fbdc10480daa884bd1cc01a87b3b1cfb - Sigstore transparency entry: 833558710
- Sigstore integration time:
-
Permalink:
pydevtools/TestIQ@26ec8e395bb6f679e8e8f1bf249648b33361200a -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/pydevtools
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@26ec8e395bb6f679e8e8f1bf249648b33361200a -
Trigger Event:
release
-
Statement type: