From 0f9f2ea33dd5e220cbe9b8f26c37f6c673aacb56 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 8 Jan 2026 09:28:10 +0000 Subject: [PATCH 1/3] Initial plan From 2820960f01313479ca45496fbaaf662d56e3beb3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 8 Jan 2026 09:35:51 +0000 Subject: [PATCH 2/3] Add markdown export with emoji indicators Co-authored-by: dev-ankit <1901680+dev-ankit@users.noreply.github.com> --- README.md | 30 +++++- compare_runs.py | 182 +++++++++++++++++++++++++++------ tests/test_markdown_output.py | 187 ++++++++++++++++++++++++++++++++++ 3 files changed, 366 insertions(+), 33 deletions(-) create mode 100644 tests/test_markdown_output.py diff --git a/README.md b/README.md index de25609..0034325 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Compare performance results between two Locust runs and show changes relative to - Compare any two runs (base vs. current). - Parses CSV `report.csv` for aggregated and per-endpoint metrics. - Parses per-feature `.html` pages and compares the latest history sample. -- Outputs human-readable tables or machine-friendly JSON. +- Outputs human-readable tables, markdown with emoji indicators, or machine-friendly JSON. ## Requirements @@ -39,6 +39,12 @@ python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --js python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --color ``` +- Markdown output with emoji indicators (✅ better, ❌ worse, ➖ same): + +``` +python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --markdown +``` + Exit code is `0` on success and `1` on error. ## What It Compares @@ -61,6 +67,28 @@ If a metric is not available for an item, it is shown as `-`. image +## Markdown Output Example + +The `--markdown` flag produces markdown tables with emoji indicators for verdicts: + +```markdown +## Aggregated + +| Metric | Base | Current | Diff | % Change | Verdict | +| --- | --- | --- | --- | --- | --- | +| Requests/s | 286.200 | 300 | +13.800 | +4.8% | ✅ | +| Request Count | 1500 | 1800 | +300 | +20.0% | ✅ | +| Failure Count | 7 | 4 | -3 | -42.9% | ✅ | +| Average Response Time | 85.200 | 78.500 | -6.700 | -7.9% | ✅ | +| 95% | 150 | 140 | -10 | -6.7% | ✅ | +``` + +Verdict emojis: +- ✅ Better performance +- ❌ Worse performance +- ➖ No change + + ## JSON Schema The `--json` output is a single JSON object containing keys for each compared item. diff --git a/compare_runs.py b/compare_runs.py index 2a0afe5..4c6054d 100644 --- a/compare_runs.py +++ b/compare_runs.py @@ -333,6 +333,13 @@ def print_section(title: str): print("-" * len(title)) +def print_section_markdown(title: str, level: int = 2): + """Print a markdown section header.""" + print("") + print("#" * level + " " + title) + print("") + + def _metric_direction(metric: str) -> str: """Return 'higher', 'lower', or 'neutral' for a metric's desirable direction. @@ -365,6 +372,70 @@ def _verdict_for(metric: str, b: Optional[float], c: Optional[float]) -> Optiona return None +def _verdict_to_emoji(verdict: Optional[str]) -> str: + """Convert verdict to emoji for markdown output.""" + if verdict == "better": + return "✅" + elif verdict == "worse": + return "❌" + elif verdict == "same": + return "➖" + return "" + + +def render_comparison_markdown( + base_row: Optional[Row], + curr_row: Optional[Row], + important_fields: List[str], + *, + show_verdict: bool = True, +): + """Render comparison as markdown table with emoji indicators.""" + headers = [ + "Metric", + "Base", + "Current", + "Diff", + "% Change", + ] + if show_verdict: + headers.append("Verdict") + rows: List[List[str]] = [] + + base_data = base_row.data if base_row else {} + curr_data = curr_row.data if curr_row else {} + + fields = important_fields[:] + # Also include any extra percentile columns present in data + extra_fields = [k for k in curr_data.keys() | base_data.keys() if k.endswith("%") and k not in fields] + fields.extend(sorted(extra_fields)) + + for field in fields: + b = base_data.get(field) + c = curr_data.get(field) + d = diff(b, c) + p = pct_change(b, c) + p_str = "-" if p is None else f"{p:+.1f}%" + row = [ + field, + format_number(b), + format_number(c), + ("-" if d is None else (f"{d:+.3f}" if abs(d - round(d)) > 1e-9 else f"{int(d):+d}")), + p_str, + ] + if show_verdict: + v = _verdict_for(field, b, c) + emoji = _verdict_to_emoji(v) + row.append(emoji) + rows.append(row) + + # Print markdown table + print("| " + " | ".join(headers) + " |") + print("| " + " | ".join(["---"] * len(headers)) + " |") + for r in rows: + print("| " + " | ".join(r) + " |") + + def render_comparison( base_row: Optional[Row], curr_row: Optional[Row], @@ -437,6 +508,7 @@ def compare_reports( *, colorize: bool = False, show_verdict: bool = True, + as_markdown: bool = False, ) -> int: # Resolve paths (extract zip files if needed) base_path = _resolve_path(base_path) @@ -517,45 +589,85 @@ def compare_reports( return 0 # Human readable output - print_section("Aggregated") - render_comparison( - base_idx.get("__Aggregated__"), - curr_idx.get("__Aggregated__"), - important_fields, - colorize=colorize, - show_verdict=show_verdict, - ) + if as_markdown: + print("# Locust Performance Comparison") + print("") + print_section_markdown("Aggregated", 2) + render_comparison_markdown( + base_idx.get("__Aggregated__"), + curr_idx.get("__Aggregated__"), + important_fields, + show_verdict=show_verdict, + ) - endpoint_keys = [k for k in all_keys if k != "__Aggregated__"] - for ek in endpoint_keys: - title = f"Endpoint: {ek}" - print_section(title) + endpoint_keys = [k for k in all_keys if k != "__Aggregated__"] + for ek in endpoint_keys: + title = f"Endpoint: {ek}" + print_section_markdown(title, 3) + render_comparison_markdown( + base_idx.get(ek), + curr_idx.get(ek), + important_fields, + show_verdict=show_verdict, + ) + + # Render HTML features + feature_keys = sorted(set(base_html_map.keys()) | set(curr_html_map.keys())) + if feature_keys: + print_section_markdown("HTML Features", 2) + for fk in feature_keys: + print_section_markdown(f"Feature: {fk}", 3) + b_map = base_html_map.get(fk, {}) + c_map = curr_html_map.get(fk, {}) + ep_keys = sorted(set(b_map.keys()) | set(c_map.keys())) + for ep in ep_keys: + print_section_markdown(f"Endpoint: {ep}", 4) + render_comparison_markdown( + b_map.get(ep), + c_map.get(ep), + important_fields, + show_verdict=show_verdict, + ) + else: + print_section("Aggregated") render_comparison( - base_idx.get(ek), - curr_idx.get(ek), + base_idx.get("__Aggregated__"), + curr_idx.get("__Aggregated__"), important_fields, colorize=colorize, show_verdict=show_verdict, ) - # Render HTML features - feature_keys = sorted(set(base_html_map.keys()) | set(curr_html_map.keys())) - if feature_keys: - print_section("HTML Features") - for fk in feature_keys: - print_section(f"Feature: {fk}") - b_map = base_html_map.get(fk, {}) - c_map = curr_html_map.get(fk, {}) - ep_keys = sorted(set(b_map.keys()) | set(c_map.keys())) - for ep in ep_keys: - print_section(f"Endpoint: {ep}") - render_comparison( - b_map.get(ep), - c_map.get(ep), - important_fields, - colorize=colorize, - show_verdict=show_verdict, - ) + endpoint_keys = [k for k in all_keys if k != "__Aggregated__"] + for ek in endpoint_keys: + title = f"Endpoint: {ek}" + print_section(title) + render_comparison( + base_idx.get(ek), + curr_idx.get(ek), + important_fields, + colorize=colorize, + show_verdict=show_verdict, + ) + + # Render HTML features + feature_keys = sorted(set(base_html_map.keys()) | set(curr_html_map.keys())) + if feature_keys: + print_section("HTML Features") + for fk in feature_keys: + print_section(f"Feature: {fk}") + b_map = base_html_map.get(fk, {}) + c_map = curr_html_map.get(fk, {}) + ep_keys = sorted(set(b_map.keys()) | set(c_map.keys())) + for ep in ep_keys: + print_section(f"Endpoint: {ep}") + render_comparison( + b_map.get(ep), + c_map.get(ep), + important_fields, + colorize=colorize, + show_verdict=show_verdict, + ) return 0 @@ -570,6 +682,11 @@ def main(): parser.add_argument("base", type=Path, help="Base run directory or report.csv path") parser.add_argument("current", type=Path, help="Current run directory or report.csv path") parser.add_argument("--json", action="store_true", help="Output results as JSON") + parser.add_argument( + "--markdown", + action="store_true", + help="Output results as Markdown with emoji indicators (✅ better, ❌ worse, ➖ same)", + ) parser.add_argument( "--color", action="store_true", @@ -590,6 +707,7 @@ def main(): as_json=args.json, colorize=args.color, show_verdict=args.show_verdict, + as_markdown=args.markdown, ) except Exception as e: print(f"Error: {e}") diff --git a/tests/test_markdown_output.py b/tests/test_markdown_output.py new file mode 100644 index 0000000..b7a8cec --- /dev/null +++ b/tests/test_markdown_output.py @@ -0,0 +1,187 @@ +"""Tests for markdown output functionality.""" +import pytest +import sys +import json +import tempfile +from pathlib import Path +from io import StringIO + +sys.path.insert(0, str(Path(__file__).parent.parent)) +from compare_runs import compare_reports, _verdict_to_emoji + + +class TestMarkdownOutput: + """Tests for markdown output functionality.""" + + def test_verdict_to_emoji_better(self): + """Test emoji for 'better' verdict.""" + assert _verdict_to_emoji("better") == "✅" + + def test_verdict_to_emoji_worse(self): + """Test emoji for 'worse' verdict.""" + assert _verdict_to_emoji("worse") == "❌" + + def test_verdict_to_emoji_same(self): + """Test emoji for 'same' verdict.""" + assert _verdict_to_emoji("same") == "➖" + + def test_verdict_to_emoji_none(self): + """Test emoji for None verdict.""" + assert _verdict_to_emoji(None) == "" + + def test_markdown_output_structure(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that markdown output has correct structure.""" + result = compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + assert result == 0 + + captured = capsys.readouterr() + output = captured.out + + # Should have markdown headers + assert "# Locust Performance Comparison" in output + assert "## Aggregated" in output + assert "### Endpoint:" in output + + # Should have markdown table syntax + assert "|" in output + assert "---" in output + + def test_markdown_output_includes_metrics(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that markdown output includes all expected metrics.""" + compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + + captured = capsys.readouterr() + output = captured.out + + # Should have metric names in tables + assert "Requests/s" in output + assert "Request Count" in output + assert "Average Response Time" in output + assert "95%" in output + + def test_markdown_output_includes_emojis(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that markdown output includes emoji indicators.""" + compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True, show_verdict=True) + + captured = capsys.readouterr() + output = captured.out + + # Should have emoji indicators for verdicts + assert "✅" in output or "❌" in output or "➖" in output + + def test_markdown_output_no_verdict(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test markdown output without verdict column.""" + compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True, show_verdict=False) + + captured = capsys.readouterr() + output = captured.out + + # Should NOT have Verdict column in tables + lines = output.split('\n') + header_lines = [l for l in lines if 'Metric' in l and '|' in l] + assert len(header_lines) > 0 + for header in header_lines: + assert "Verdict" not in header + + def test_markdown_output_no_color_codes(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that markdown output does not contain ANSI color codes.""" + compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + + captured = capsys.readouterr() + output = captured.out + + # Should NOT have ANSI color codes + assert "\033[32m" not in output + assert "\033[31m" not in output + assert "\033[0m" not in output + + def test_markdown_table_format(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that markdown tables are properly formatted.""" + compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True, show_verdict=True) + + captured = capsys.readouterr() + output = captured.out + lines = output.split('\n') + + # Find table lines + table_lines = [l for l in lines if l.startswith('|') and 'Metric' in l] + assert len(table_lines) > 0 + + # Check that separator line follows header + for i, line in enumerate(lines): + if 'Metric' in line and line.startswith('|'): + # Next line should be separator + if i + 1 < len(lines): + next_line = lines[i + 1] + assert '---' in next_line + assert next_line.startswith('|') + + def test_markdown_with_html_features(self, temp_dir_with_html, capsys): + """Test markdown output includes HTML features section.""" + with tempfile.TemporaryDirectory() as other_dir: + other = Path(other_dir) + (other / "report.csv").write_text("""Type,Name,Request Count +GET,/api/test,100 +,Aggregated,100 +""") + # Copy the HTML file + import shutil + for html_file in temp_dir_with_html.glob("*.html"): + if html_file.name != "htmlpublisher-wrapper.html": + shutil.copy(html_file, other / html_file.name) + + compare_reports(temp_dir_with_html, other, as_markdown=True) + + captured = capsys.readouterr() + output = captured.out + + # Should have HTML Features section + assert "## HTML Features" in output + assert "### Feature:" in output + + def test_markdown_output_values(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that markdown output contains correct values.""" + compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + + captured = capsys.readouterr() + output = captured.out + + # Should contain values from both base and current + assert "1000" in output # base request count + assert "1200" in output # current request count + + +class TestMarkdownCompatibility: + """Test that markdown output doesn't break existing functionality.""" + + def test_json_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that JSON output is not affected by markdown changes.""" + result = compare_reports(temp_test_dir, temp_test_dir_v2, as_json=True) + assert result == 0 + + captured = capsys.readouterr() + data = json.loads(captured.out) + assert "__Aggregated__" in data + + def test_normal_output_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that normal human-readable output still works.""" + result = compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False, as_markdown=False) + assert result == 0 + + captured = capsys.readouterr() + output = captured.out + + # Should have section headers without markdown syntax + assert "Aggregated" in output + assert "# Locust" not in output # No markdown headers + + def test_color_output_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): + """Test that colorized output still works.""" + result = compare_reports(temp_test_dir, temp_test_dir_v2, colorize=True, as_markdown=False) + assert result == 0 + + captured = capsys.readouterr() + output = captured.out + + # Should have ANSI color codes + assert "\033[32m" in output or "\033[31m" in output From d9bfc492befc869ff2ced1c384eb990c1e7827de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 8 Jan 2026 09:48:12 +0000 Subject: [PATCH 3/3] Consolidate output format flags into --output/-o Co-authored-by: dev-ankit <1901680+dev-ankit@users.noreply.github.com> --- README.md | 12 ++++++------ compare_runs.py | 21 ++++++++++----------- tests/test_compare_reports.py | 28 ++++++++++++++-------------- tests/test_markdown_output.py | 22 +++++++++++----------- tests/test_zip_support.py | 10 +++++----- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 0034325..0314bd0 100644 --- a/README.md +++ b/README.md @@ -30,19 +30,19 @@ python3 compare_runs.py test_runs/HTML-Report-292/report.csv test_runs/HTML-Repo - JSON output for scripting: ``` -python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --json +python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 -o json ``` -- Colorize output and show verdicts (green=better, red=worse): +- Markdown output with emoji indicators (✅ better, ❌ worse, ➖ same): ``` -python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --color +python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 -o markdown ``` -- Markdown output with emoji indicators (✅ better, ❌ worse, ➖ same): +- Colorize text output (green=better, red=worse): ``` -python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --markdown +python3 compare_runs.py test_runs/HTML-Report-292 test_runs/HTML-Report-294 --color ``` Exit code is `0` on success and `1` on error. @@ -69,7 +69,7 @@ If a metric is not available for an item, it is shown as `-`. ## Markdown Output Example -The `--markdown` flag produces markdown tables with emoji indicators for verdicts: +The `-o markdown` flag produces markdown tables with emoji indicators for verdicts: ```markdown ## Aggregated diff --git a/compare_runs.py b/compare_runs.py index 4c6054d..1c0fcbe 100644 --- a/compare_runs.py +++ b/compare_runs.py @@ -504,11 +504,10 @@ def render_comparison( def compare_reports( base_path: Path, curr_path: Path, - as_json: bool = False, + output_format: str = "text", *, colorize: bool = False, show_verdict: bool = True, - as_markdown: bool = False, ) -> int: # Resolve paths (extract zip files if needed) base_path = _resolve_path(base_path) @@ -537,7 +536,7 @@ def compare_reports( base_html_map = load_html_feature_map(base_path if base_path.is_dir() else base_path.parent) curr_html_map = load_html_feature_map(curr_path if curr_path.is_dir() else curr_path.parent) - if as_json: + if output_format == "json": # Produce a structured JSON dict out: Dict[str, Dict[str, Dict[str, Optional[float]]]] = {} for key in all_keys: @@ -589,7 +588,7 @@ def compare_reports( return 0 # Human readable output - if as_markdown: + if output_format == "markdown": print("# Locust Performance Comparison") print("") print_section_markdown("Aggregated", 2) @@ -681,16 +680,17 @@ def main(): ) parser.add_argument("base", type=Path, help="Base run directory or report.csv path") parser.add_argument("current", type=Path, help="Current run directory or report.csv path") - parser.add_argument("--json", action="store_true", help="Output results as JSON") parser.add_argument( - "--markdown", - action="store_true", - help="Output results as Markdown with emoji indicators (✅ better, ❌ worse, ➖ same)", + "-o", + "--output", + choices=["text", "json", "markdown"], + default="text", + help="Output format: text (default), json, or markdown with emoji indicators (✅ better, ❌ worse, ➖ same)", ) parser.add_argument( "--color", action="store_true", - help="Colorize rows: green if better, red if worse", + help="Colorize rows: green if better, red if worse (only for text output)", ) parser.add_argument( "--no-verdict", @@ -704,10 +704,9 @@ def main(): return compare_reports( args.base, args.current, - as_json=args.json, + output_format=args.output, colorize=args.color, show_verdict=args.show_verdict, - as_markdown=args.markdown, ) except Exception as e: print(f"Error: {e}") diff --git a/tests/test_compare_reports.py b/tests/test_compare_reports.py index 7919c5f..54cd875 100644 --- a/tests/test_compare_reports.py +++ b/tests/test_compare_reports.py @@ -15,7 +15,7 @@ class TestCompareReportsJson: """Tests for compare_reports with JSON output.""" def test_json_output_structure(self, temp_test_dir, temp_test_dir_v2, capsys): - result = compare_reports(temp_test_dir, temp_test_dir_v2, as_json=True) + result = compare_reports(temp_test_dir, temp_test_dir_v2, output_format="json") assert result == 0 captured = capsys.readouterr() @@ -27,7 +27,7 @@ def test_json_output_structure(self, temp_test_dir, temp_test_dir_v2, capsys): assert "/api/login" in data def test_json_output_metrics(self, temp_test_dir, temp_test_dir_v2, capsys): - compare_reports(temp_test_dir, temp_test_dir_v2, as_json=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="json") captured = capsys.readouterr() data = json.loads(captured.out) @@ -42,7 +42,7 @@ def test_json_output_metrics(self, temp_test_dir, temp_test_dir_v2, capsys): assert "pct_change" in metric def test_json_output_values(self, temp_test_dir, temp_test_dir_v2, capsys): - compare_reports(temp_test_dir, temp_test_dir_v2, as_json=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="json") captured = capsys.readouterr() data = json.loads(captured.out) @@ -61,7 +61,7 @@ class TestCompareReportsHuman: """Tests for compare_reports with human-readable output.""" def test_human_output_includes_sections(self, temp_test_dir, temp_test_dir_v2, capsys): - result = compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False) + result = compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text") assert result == 0 captured = capsys.readouterr() @@ -72,7 +72,7 @@ def test_human_output_includes_sections(self, temp_test_dir, temp_test_dir_v2, c assert "Endpoint:" in output def test_human_output_includes_metrics(self, temp_test_dir, temp_test_dir_v2, capsys): - compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text") captured = capsys.readouterr() output = captured.out @@ -83,7 +83,7 @@ def test_human_output_includes_metrics(self, temp_test_dir, temp_test_dir_v2, ca assert "Average Response Time" in output def test_human_output_includes_verdict(self, temp_test_dir, temp_test_dir_v2, capsys): - compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False, show_verdict=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text", show_verdict=True) captured = capsys.readouterr() output = captured.out @@ -94,7 +94,7 @@ def test_human_output_includes_verdict(self, temp_test_dir, temp_test_dir_v2, ca assert "better" in output or "worse" in output or "same" in output def test_human_output_no_verdict(self, temp_test_dir, temp_test_dir_v2, capsys): - compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False, show_verdict=False) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text", show_verdict=False) captured = capsys.readouterr() output = captured.out @@ -105,7 +105,7 @@ def test_human_output_no_verdict(self, temp_test_dir, temp_test_dir_v2, capsys): assert "Verdict" not in header_line def test_human_output_colorize(self, temp_test_dir, temp_test_dir_v2, capsys): - compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False, colorize=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text", colorize=True) captured = capsys.readouterr() output = captured.out @@ -119,7 +119,7 @@ class TestCompareReportsEdgeCases: def test_compare_same_report(self, temp_test_dir, capsys): """Comparing a report to itself should show no changes.""" - compare_reports(temp_test_dir, temp_test_dir, as_json=True) + compare_reports(temp_test_dir, temp_test_dir, output_format="json") captured = capsys.readouterr() data = json.loads(captured.out) @@ -141,7 +141,7 @@ def test_compare_with_missing_endpoint(self, sample_csv_content, sample_csv_cont base_path.write_text(base_csv) curr_path.write_text(sample_csv_content_v2) - compare_reports(Path(base_dir), Path(curr_dir), as_json=True) + compare_reports(Path(base_dir), Path(curr_dir), output_format="json") captured = capsys.readouterr() data = json.loads(captured.out) @@ -164,7 +164,7 @@ def test_compare_with_new_endpoint(self, sample_csv_content, sample_csv_content_ base_path.write_text(sample_csv_content) curr_path.write_text(curr_csv) - compare_reports(Path(base_dir), Path(curr_dir), as_json=True) + compare_reports(Path(base_dir), Path(curr_dir), output_format="json") captured = capsys.readouterr() data = json.loads(captured.out) @@ -195,7 +195,7 @@ def test_json_includes_html_features(self, temp_dir_with_html, capsys): if html_file.name != "htmlpublisher-wrapper.html": shutil.copy(html_file, other / html_file.name) - compare_reports(temp_dir_with_html, other, as_json=True) + compare_reports(temp_dir_with_html, other, output_format="json") captured = capsys.readouterr() data = json.loads(captured.out) @@ -218,7 +218,7 @@ def test_human_output_includes_html_section(self, temp_dir_with_html, capsys): if html_file.name != "htmlpublisher-wrapper.html": shutil.copy(html_file, other / html_file.name) - compare_reports(temp_dir_with_html, other, as_json=False) + compare_reports(temp_dir_with_html, other, output_format="text") captured = capsys.readouterr() output = captured.out @@ -238,7 +238,7 @@ def test_compare_real_reports(self, real_test_runs_path, capsys): if not base.exists() or not curr.exists(): pytest.skip("Real test data not available") - result = compare_reports(base, curr, as_json=True) + result = compare_reports(base, curr, output_format="json") assert result == 0 captured = capsys.readouterr() diff --git a/tests/test_markdown_output.py b/tests/test_markdown_output.py index b7a8cec..901c185 100644 --- a/tests/test_markdown_output.py +++ b/tests/test_markdown_output.py @@ -31,7 +31,7 @@ def test_verdict_to_emoji_none(self): def test_markdown_output_structure(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that markdown output has correct structure.""" - result = compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + result = compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown") assert result == 0 captured = capsys.readouterr() @@ -48,7 +48,7 @@ def test_markdown_output_structure(self, temp_test_dir, temp_test_dir_v2, capsys def test_markdown_output_includes_metrics(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that markdown output includes all expected metrics.""" - compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown") captured = capsys.readouterr() output = captured.out @@ -61,7 +61,7 @@ def test_markdown_output_includes_metrics(self, temp_test_dir, temp_test_dir_v2, def test_markdown_output_includes_emojis(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that markdown output includes emoji indicators.""" - compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True, show_verdict=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown", show_verdict=True) captured = capsys.readouterr() output = captured.out @@ -71,7 +71,7 @@ def test_markdown_output_includes_emojis(self, temp_test_dir, temp_test_dir_v2, def test_markdown_output_no_verdict(self, temp_test_dir, temp_test_dir_v2, capsys): """Test markdown output without verdict column.""" - compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True, show_verdict=False) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown", show_verdict=False) captured = capsys.readouterr() output = captured.out @@ -85,7 +85,7 @@ def test_markdown_output_no_verdict(self, temp_test_dir, temp_test_dir_v2, capsy def test_markdown_output_no_color_codes(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that markdown output does not contain ANSI color codes.""" - compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown") captured = capsys.readouterr() output = captured.out @@ -97,7 +97,7 @@ def test_markdown_output_no_color_codes(self, temp_test_dir, temp_test_dir_v2, c def test_markdown_table_format(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that markdown tables are properly formatted.""" - compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True, show_verdict=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown", show_verdict=True) captured = capsys.readouterr() output = captured.out @@ -130,7 +130,7 @@ def test_markdown_with_html_features(self, temp_dir_with_html, capsys): if html_file.name != "htmlpublisher-wrapper.html": shutil.copy(html_file, other / html_file.name) - compare_reports(temp_dir_with_html, other, as_markdown=True) + compare_reports(temp_dir_with_html, other, output_format="markdown") captured = capsys.readouterr() output = captured.out @@ -141,7 +141,7 @@ def test_markdown_with_html_features(self, temp_dir_with_html, capsys): def test_markdown_output_values(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that markdown output contains correct values.""" - compare_reports(temp_test_dir, temp_test_dir_v2, as_markdown=True) + compare_reports(temp_test_dir, temp_test_dir_v2, output_format="markdown") captured = capsys.readouterr() output = captured.out @@ -156,7 +156,7 @@ class TestMarkdownCompatibility: def test_json_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that JSON output is not affected by markdown changes.""" - result = compare_reports(temp_test_dir, temp_test_dir_v2, as_json=True) + result = compare_reports(temp_test_dir, temp_test_dir_v2, output_format="json") assert result == 0 captured = capsys.readouterr() @@ -165,7 +165,7 @@ def test_json_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): def test_normal_output_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that normal human-readable output still works.""" - result = compare_reports(temp_test_dir, temp_test_dir_v2, as_json=False, as_markdown=False) + result = compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text") assert result == 0 captured = capsys.readouterr() @@ -177,7 +177,7 @@ def test_normal_output_still_works(self, temp_test_dir, temp_test_dir_v2, capsys def test_color_output_still_works(self, temp_test_dir, temp_test_dir_v2, capsys): """Test that colorized output still works.""" - result = compare_reports(temp_test_dir, temp_test_dir_v2, colorize=True, as_markdown=False) + result = compare_reports(temp_test_dir, temp_test_dir_v2, output_format="text", colorize=True) assert result == 0 captured = capsys.readouterr() diff --git a/tests/test_zip_support.py b/tests/test_zip_support.py index b7445a7..7ffe4e3 100644 --- a/tests/test_zip_support.py +++ b/tests/test_zip_support.py @@ -112,7 +112,7 @@ def test_compare_zip_to_zip(self, sample_csv_content, sample_csv_content_v2, cap with zipfile.ZipFile(curr_zip, "w") as zf: zf.writestr("report.csv", sample_csv_content_v2) - result = compare_reports(base_zip, curr_zip, as_json=True) + result = compare_reports(base_zip, curr_zip, output_format="json") assert result == 0 captured = capsys.readouterr() @@ -126,7 +126,7 @@ def test_compare_zip_to_directory(self, sample_csv_content, temp_test_dir_v2, ca with zipfile.ZipFile(base_zip, "w") as zf: zf.writestr("report.csv", sample_csv_content) - result = compare_reports(base_zip, temp_test_dir_v2, as_json=True) + result = compare_reports(base_zip, temp_test_dir_v2, output_format="json") assert result == 0 def test_compare_directory_to_zip(self, temp_test_dir, sample_csv_content_v2, capsys): @@ -137,7 +137,7 @@ def test_compare_directory_to_zip(self, temp_test_dir, sample_csv_content_v2, ca with zipfile.ZipFile(curr_zip, "w") as zf: zf.writestr("report.csv", sample_csv_content_v2) - result = compare_reports(temp_test_dir, curr_zip, as_json=True) + result = compare_reports(temp_test_dir, curr_zip, output_format="json") assert result == 0 def test_zip_with_nested_directory_structure(self, sample_csv_content, sample_csv_content_v2, capsys): @@ -152,7 +152,7 @@ def test_zip_with_nested_directory_structure(self, sample_csv_content, sample_cs with zipfile.ZipFile(curr_zip, "w") as zf: zf.writestr("HTML-Report-200/report.csv", sample_csv_content_v2) - result = compare_reports(base_zip, curr_zip, as_json=True) + result = compare_reports(base_zip, curr_zip, output_format="json") assert result == 0 def test_zip_with_html_files(self, sample_csv_content, sample_html_template_args, capsys): @@ -169,7 +169,7 @@ def test_zip_with_html_files(self, sample_csv_content, sample_html_template_args zf.writestr("report.csv", sample_csv_content) zf.writestr("feature_test.html", sample_html_template_args) - result = compare_reports(base_zip, curr_zip, as_json=True) + result = compare_reports(base_zip, curr_zip, output_format="json") assert result == 0 captured = capsys.readouterr()