diff --git a/json_to_md.py b/json_to_md.py index 3003bee6c..d1d5e69b0 100644 --- a/json_to_md.py +++ b/json_to_md.py @@ -2,37 +2,31 @@ import json from datetime import datetime import argparse -def strip_params(nodeid): - return nodeid.split('[')[0] if nodeid else "" -def get_emoji(outcome): - icons = { - "passed": "✅", - "failed": "❌", - "skipped": "⏭️", - "error": "🛑" - } - return icons.get(outcome, "🧐") +def format_dict(d): + """Formate un dictionnaire en Markdown lisible""" + if not d: + return "None" + return "\n".join(f"- **{k}:** `{v if v else 'None'}`" for k, v in d.items()) + + +def format_list_of_dicts(l): + if not l: + return "None" + result = "" + for i, item in enumerate(l, 1): + result += f"\n - Entrée {i}:\n" + result += "\n".join(f" - {k}: `{v if v else 'None'}`" for k, v in item.items()) + result += "\n" + return result -def pretty_dict_md(d, indent=0, exclude_keys=None): - lines = [] - exclude_keys = exclude_keys or [] - for k, v in d.items(): - if k in exclude_keys: - continue - value = "None" if v in [None, "", [], {}] else v - if isinstance(value, dict): - lines.append(" " * indent + f"- **{k}**:") - lines += pretty_dict_md(value, indent + 1) - else: - lines.append(" " * indent + f"- **{k}**: `{value}`") - return lines def json_to_adaptive_md(json_path, md_path): with open(json_path) as f: data = json.load(f) with open(md_path, 'w', encoding='utf-8') as f: + # Titre principal f.write(f"# 🏗 Rapport de Tests (Générique)\n") f.write(f"*Généré le {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n\n") @@ -40,69 +34,81 @@ def json_to_adaptive_md(json_path, md_path): if 'summary' in data: f.write("## 📋 Summary\n") for key, value in data['summary'].items(): - val = "None" if value in [None, "", [], {}] else value - f.write(f"- **{key.capitalize()}:** `{val}`\n") - if 'duration' in data: - f.write(f"- **Durée totale:** `{data['duration']:.3f}` s\n") - f.write("\n") + f.write(f"- **{key.capitalize()}:** `{value}`\n") - # Collectors - if 'collectors' in data: - f.write("## 📦 Collectors\n") - for collector in data['collectors']: - nodeid = strip_params(collector.get('nodeid', '')) - outcome = collector.get('outcome', 'unknown') - emoji = get_emoji(outcome) - f.write(f"
\n{emoji} `{nodeid}`\n\n") - for line in pretty_dict_md(collector, exclude_keys=['nodeid']): - f.write(line + "\n") - f.write("\n
\n\n") + if "duration" in data: + f.write(f"- **Durée totale:** `{data['duration']:.3f}` s\n\n") - # Tests + # Section Collector + if "collectors" in data: + f.write("## 📚 Collectors\n") + for collector in data["collectors"]: + nodeid = collector.get("nodeid", "Sans nom") + status = collector.get("outcome", "unknown") + emoji = "✅" if status == "passed" else "⚠️" + f.write(f"\n
\n{emoji} `{nodeid}`\n\n") + f.write(f"- **Outcome:** `{status}`\n") + result = collector.get("result", []) + if isinstance(result, list): + f.write("- **Resultats:**\n") + f.write(format_list_of_dicts(result)) + else: + f.write("- **Resultat:**\n") + f.write(f"{format_dict(result)}\n") + f.write("\n
\n") + + # Section Tests if 'tests' in data: - f.write("## 🧪 Tests\n") + f.write("\n## 🧪 Tests\n") current_file = None for test in data['tests']: - nodeid = test.get('nodeid', '') - if '::' in nodeid: - file_path = nodeid.split('::')[0] - if file_path != current_file: - current_file = file_path - f.write(f"\n## 📄 Fichier: `{current_file}`\n") + if '::' in test['nodeid']: + new_file = test['nodeid'].split('::')[0] + if new_file != current_file: + current_file = new_file + f.write(f"\n### 📄 Fichier: `{current_file}`\n") - test_name = strip_params(nodeid.split('::')[-1]) - f.write(f"\n### 🧪 {test_name}\n") + test_name = test['nodeid'].split('::')[-1].split('[')[0] + f.write(f"\n#### 🔹 {test_name}\n") - # Paramètres - if '[' in nodeid: - params = nodeid.split('[')[1].rstrip(']') - f.write("- **Paramètres:**\n") - for i, param in enumerate(params.split('-'), 1): - f.write(f" - Param {i}: `{param}`\n") + if '[' in test['nodeid']: + params = test['nodeid'].split('[')[1].rstrip(']') + f.write("- **Paramètres:**\n") + for i, param in enumerate(params.split('-'), 1): + f.write(f" - Param {i}: `{param}`\n") - # Statut - outcome = test.get("outcome", "None") - emoji = get_emoji(outcome) - f.write(f"- **Statut:** {emoji} `{outcome}`\n") + outcome = test.get("outcome", "unknown") + emoji = { + "passed": "✅", + "failed": "❌", + "skipped": "⏭️", + "error": "🚫" + }.get(outcome, "🔍") + f.write(f"- **Statut:** {emoji} `{outcome}`\n") - # Durée - duration = test.get("call", {}).get("duration") - if duration is not None: - f.write(f"- **Durée:** `{duration:.6f}` s\n") - else: - f.write(f"- **Durée:** `None`\n") + if "call" in test and "duration" in test["call"]: + f.write(f"- **Durée:** `{test['call']['duration']:.6f}` s\n") - # Détails supplémentaires si != passed - if outcome != "passed": - call_data = test.get("call", {}) - if call_data: - f.write("\n
\n🔍 Détails\n\n") - for line in pretty_dict_md(call_data): - f.write(line + "\n") - f.write("\n
\n") + if outcome != "passed": + call_data = test.get("call", {}) + if call_data: + f.write("\n- **Détails:**\n") + for k, v in call_data.items(): + f.write(f" - **{k}:**\n") + if isinstance(v, dict): + f.write(format_dict(v) + "\n") + elif isinstance(v, list): + if all(isinstance(item, dict) for item in v): + f.write(format_list_of_dicts(v) + "\n") + else: + f.write(" ``` +" + "\n".join(str(item) for item in v) + "\n ```\n") + else: + f.write(f" ``` +{v if v else 'None'}\n ```\n") + f.write("\n" + "-" * 40 + "\n") - f.write("\n" + "-" * 50 + "\n") if __name__ == "__main__": parser = argparse.ArgumentParser(description="Convert Pytest JSON report to Markdown")