Update json_to_md.py
This commit is contained in:
+80
-74
@@ -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"<details>\n<summary>{emoji} `{nodeid}`</summary>\n\n")
|
||||
for line in pretty_dict_md(collector, exclude_keys=['nodeid']):
|
||||
f.write(line + "\n")
|
||||
f.write("\n</details>\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<details>\n<summary>{emoji} `{nodeid}`</summary>\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</details>\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<details>\n<summary>🔍 Détails</summary>\n\n")
|
||||
for line in pretty_dict_md(call_data):
|
||||
f.write(line + "\n")
|
||||
f.write("\n</details>\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")
|
||||
|
||||
Reference in New Issue
Block a user