|
| 1 | +import json |
| 2 | +import sys |
| 3 | +import argparse |
| 4 | + |
| 5 | +# Mapping tags to readable Status names |
| 6 | +TAG_MAPPING = { |
| 7 | + '@new_issue': 'New and reported', |
| 8 | + '@under_debugging': 'Debugging', |
| 9 | + '@bug_reported': 'Bug reported', |
| 10 | + '@test_issue': 'Test Framework issue', |
| 11 | + '@flaky': 'Flaky Test' |
| 12 | +} |
| 13 | + |
| 14 | +def get_status(tags): |
| 15 | + """Determines status based on tags. Returns 'New' if no matching tag found.""" |
| 16 | + found_status = 'Not reported' |
| 17 | + # Priority order can be adjusted here if needed |
| 18 | + for tag in tags: |
| 19 | + tag_name = tag.get('name') |
| 20 | + if tag_name in TAG_MAPPING: |
| 21 | + found_status = TAG_MAPPING[tag_name] |
| 22 | + # Stop at the first relevant tag found (or remove break to prioritise last) |
| 23 | + break |
| 24 | + return found_status |
| 25 | + |
| 26 | +def generate_summary(json_file_path): |
| 27 | + try: |
| 28 | + with open(json_file_path, 'r', encoding='utf-8') as f: |
| 29 | + features = json.load(f) |
| 30 | + except Exception as e: |
| 31 | + print(f"Error reading JSON file: {e}") |
| 32 | + sys.exit(1) |
| 33 | + |
| 34 | + failed_features_count = 0 |
| 35 | + total_failed_scenarios = 0 |
| 36 | + status_counts = {val: 0 for val in TAG_MAPPING.values()} |
| 37 | + status_counts['Not reported'] = 0 |
| 38 | + output_lines = [] |
| 39 | + |
| 40 | + for feature in features: |
| 41 | + feature_name = feature.get('name', 'Unknown Feature') |
| 42 | + elements = feature.get('elements', []) |
| 43 | + feature_tags = feature.get('tags', []) |
| 44 | + |
| 45 | + feature_has_failure = False |
| 46 | + first_failure_recorded = False |
| 47 | + |
| 48 | + for scenario in elements: |
| 49 | + # Check if this element is a scenario (not background) and if it failed |
| 50 | + if scenario.get('type') != 'scenario': |
| 51 | + continue |
| 52 | + |
| 53 | + # Check steps for any failure |
| 54 | + steps = scenario.get('steps', []) |
| 55 | + is_failed = any(step.get('result', {}).get('status') == 'failed' for step in steps) |
| 56 | + |
| 57 | + if is_failed: |
| 58 | + total_failed_scenarios += 1 |
| 59 | + feature_has_failure = True |
| 60 | + |
| 61 | + # Merge Scenario tags with Feature tags |
| 62 | + scenario_tags = scenario.get('tags', []) |
| 63 | + all_tags = feature_tags + scenario_tags |
| 64 | + |
| 65 | + # Determine Status |
| 66 | + status = get_status(all_tags) |
| 67 | + status_counts[status] += 1 |
| 68 | + |
| 69 | + # Record ONLY the first failed scenario for the list |
| 70 | + if not first_failure_recorded: |
| 71 | + scenario_title = scenario.get('name', 'Unnamed Scenario') |
| 72 | + output_lines.append(f"* {feature_name}") |
| 73 | + output_lines.append(f" * [{status}] {scenario_title}") |
| 74 | + first_failure_recorded = True |
| 75 | + |
| 76 | + if feature_has_failure: |
| 77 | + failed_features_count += 1 |
| 78 | + |
| 79 | + # --- Print The Report --- |
| 80 | + print("=" * 30) |
| 81 | + print(" TEST REVIEW SUMMARY ") |
| 82 | + print("=" * 30 + "\n") |
| 83 | + |
| 84 | + print(f"- Failed Features: {failed_features_count}") |
| 85 | + print(f"- Failed Scenarios: {total_failed_scenarios}") |
| 86 | + |
| 87 | + # Format Breakdown |
| 88 | + breakdown = [f"- {k}: {v}\n" for k, v in sorted(status_counts.items()) if v > 0] |
| 89 | + print(f"- Breakdown by Status:\n {' '.join(breakdown)}\n") |
| 90 | + |
| 91 | + for line in output_lines: |
| 92 | + print(line) |
| 93 | + |
| 94 | +if __name__ == "__main__": |
| 95 | + parser = argparse.ArgumentParser(description="Parse Cucumber JSON report for summary.") |
| 96 | + parser.add_argument("jsonfile", help="Path to cucumber_report.html.json") |
| 97 | + args = parser.parse_args() |
| 98 | + |
| 99 | + generate_summary(args.jsonfile) |
0 commit comments