Download tests/mutation_tests/scripts/generate_mutation_report.py from techprotrade/annator-command-center: direct link, hf CLI and curl.
- Browser
- Download file 6.95 kB
-
https://huggingface.co/spaces/techprotrade/annator-command-center/resolve/main/tests/mutation_tests/scripts/generate_mutation_report.py
- Command line
-
hf download hf://spaces/techprotrade/annator-command-center/tests/mutation_tests/scripts/generate_mutation_report.py
-
curl -L -o generate_mutation_report.py https://huggingface.co/spaces/techprotrade/annator-command-center/resolve/main/tests/mutation_tests/scripts/generate_mutation_report.py
6.95 kB
| #!/usr/bin/env python3 | |
| """ | |
| Mutation Test Report Generator | |
| Generates comprehensive mutation testing reports including: | |
| - Mutation scores by module | |
| - Surviving mutants analysis | |
| - Test coverage gaps | |
| - Recommendations for improvement | |
| Usage: | |
| python generate_mutation_report.py --target priority_p0_financial | |
| python generate_mutation_report.py --all | |
| """ | |
| import argparse | |
| import json | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| from datetime import datetime | |
| import configparser | |
| def load_targets_config(): | |
| """Load mutation testing targets configuration.""" | |
| config_path = Path(__file__).parent.parent / "targets" / "TARGETS.ini" | |
| config = configparser.ConfigParser() | |
| config.read(config_path) | |
| return config | |
| def get_mutmut_results(): | |
| """Get mutation testing results from mutmut.""" | |
| try: | |
| result = subprocess.run( | |
| ["mutmut", "results"], | |
| capture_output=True, | |
| text=True, | |
| timeout=30 | |
| ) | |
| return result.stdout | |
| except Exception as e: | |
| print(f"Error getting mutmut results: {e}") | |
| return None | |
| def parse_mutmut_results(output): | |
| """Parse mutmut results into structured data.""" | |
| if not output: | |
| return None | |
| results = { | |
| 'score': 0.0, | |
| 'killed': 0, | |
| 'survived': 0, | |
| 'total': 0, | |
| 'modules': {} | |
| } | |
| lines = output.split('\n') | |
| for line in lines: | |
| if 'Mutation score:' in line: | |
| import re | |
| match = re.search(r'(\d+\.\d+)%', line) | |
| if match: | |
| results['score'] = float(match.group(1)) | |
| return results | |
| def generate_html_report(results, output_path): | |
| """Generate HTML mutation testing report.""" | |
| html = f""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Mutation Testing Report - Atom Platform</title> | |
| <style> | |
| body {{ | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
| margin: 40px; | |
| background: #f5f5f5; | |
| }} | |
| .container {{ | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| background: white; | |
| padding: 30px; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |
| }} | |
| h1 {{ | |
| color: #333; | |
| border-bottom: 2px solid #007bff; | |
| padding-bottom: 10px; | |
| }} | |
| h2 {{ | |
| color: #555; | |
| margin-top: 30px; | |
| }} | |
| .score {{ | |
| font-size: 48px; | |
| font-weight: bold; | |
| text-align: center; | |
| margin: 30px 0; | |
| }} | |
| .score.good {{ | |
| color: #28a745; | |
| }} | |
| .score.warning {{ | |
| color: #ffc107; | |
| }} | |
| .score.danger {{ | |
| color: #dc3545; | |
| }} | |
| table {{ | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin: 20px 0; | |
| }} | |
| th, td {{ | |
| padding: 12px; | |
| text-align: left; | |
| border-bottom: 1px solid #ddd; | |
| }} | |
| th {{ | |
| background: #f8f9fa; | |
| font-weight: 600; | |
| }} | |
| .status-pass {{ | |
| color: #28a745; | |
| font-weight: bold; | |
| }} | |
| .status-fail {{ | |
| color: #dc3545; | |
| font-weight: bold; | |
| }} | |
| .recommendation {{ | |
| background: #f8f9fa; | |
| padding: 15px; | |
| border-left: 4px solid #007bff; | |
| margin: 20px 0; | |
| }} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>🧬 Mutation Testing Report</h1> | |
| <p>Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p> | |
| <div class="score {'good' if results.get('score', 0) >= 90 else 'warning' if results.get('score', 0) >= 80 else 'danger'}"> | |
| {results.get('score', 0):.2f}% | |
| </div> | |
| <h2>Results Summary</h2> | |
| <table> | |
| <tr> | |
| <th>Metric</th> | |
| <th>Value</th> | |
| </tr> | |
| <tr> | |
| <td>Mutation Score</td> | |
| <td>{results.get('score', 0):.2f}%</td> | |
| </tr> | |
| <tr> | |
| <td>Killed Mutants</td> | |
| <td>{results.get('killed', 0)}</td> | |
| </tr> | |
| <tr> | |
| <td>Surviving Mutants</td> | |
| <td>{results.get('survived', 0)}</td> | |
| </tr> | |
| <tr> | |
| <td>Total Mutants</td> | |
| <td>{results.get('total', 0)}</td> | |
| </tr> | |
| </table> | |
| <h2>Quality Gates</h2> | |
| <table> | |
| <tr> | |
| <th>Priority</th> | |
| <th>Target</th> | |
| <th>Status</th> | |
| </tr> | |
| <tr> | |
| <td>P0: Financial & Security</td> | |
| <td>>95%</td> | |
| <td class="{'status-pass' if results.get('score', 0) >= 95 else 'status-fail'}"> | |
| {'✅ PASS' if results.get('score', 0) >= 95 else '❌ FAIL'} | |
| </td> | |
| </tr> | |
| <tr> | |
| <td>P1: Core Business Logic</td> | |
| <td>>90%</td> | |
| <td class="{'status-pass' if results.get('score', 0) >= 90 else 'status-fail'}"> | |
| {'✅ PASS' if results.get('score', 0) >= 90 else '❌ FAIL'} | |
| </td> | |
| </tr> | |
| <tr> | |
| <td>P2: API & Tools</td> | |
| <td>>85%</td> | |
| <td class="{'status-pass' if results.get('score', 0) >= 85 else 'status-fail'}"> | |
| {'✅ PASS' if results.get('score', 0) >= 85 else '❌ FAIL'} | |
| </td> | |
| </tr> | |
| </table> | |
| <div class="recommendation"> | |
| <h3>Recommendations</h3> | |
| <ul> | |
| <li>Add property-based tests to kill surviving mutants</li> | |
| <li>Focus on testing edge cases and boundary conditions</li> | |
| <li>Increase Hypothesis max_examples for better coverage</li> | |
| <li>Review test assertions for completeness</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </body> | |
| </html> | |
| """ | |
| with open(output_path, 'w') as f: | |
| f.write(html) | |
| print(f"HTML report generated: {output_path}") | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description="Generate mutation testing report" | |
| ) | |
| parser.add_argument( | |
| "--output", | |
| default="tests/mutation_tests/reports/mutation_report.html", | |
| help="Output path for HTML report" | |
| ) | |
| args = parser.parse_args() | |
| # Get results | |
| output = get_mutmut_results() | |
| results = parse_mutmut_results(output) or {'score': 0.0} | |
| # Generate report | |
| output_path = Path(args.output) | |
| output_path.parent.mkdir(parents=True, exist_ok=True) | |
| generate_html_report(results, output_path) | |
| print(f"\nMutation Score: {results['score']:.2f}%") | |
| if __name__ == "__main__": | |
| main() | |