123 lines
5.2 KiB
Python
123 lines
5.2 KiB
Python
from datetime import datetime
|
|
import json
|
|
|
|
def format_dict(d):
|
|
"""Format a dictionary as Markdown key-value pairs."""
|
|
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(lst):
|
|
"""Format a list of dictionaries in Markdown."""
|
|
if not lst:
|
|
return " None"
|
|
return "\n".join([" - " + ", ".join(f"**{k}**: {v if v else 'None'}" for k, v in d.items()) for d in lst])
|
|
|
|
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:
|
|
# En-tête
|
|
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")
|
|
|
|
if 'summary' in data:
|
|
f.write("## 📋 Summary\n")
|
|
for key, value in data['summary'].items():
|
|
f.write(f"- **{key.capitalize()}:** `{value}`\n")
|
|
|
|
total_duration = data.get('duration')
|
|
if total_duration is not None:
|
|
f.write(f"- **Durée totale:** `{total_duration:.3f}` s\n")
|
|
f.write("\n")
|
|
|
|
if 'collectors' in data:
|
|
f.write("## 🧾 Collectors\n")
|
|
for collector in data['collectors']:
|
|
nodeid = collector.get("nodeid", "Inconnu")
|
|
emoji = "✅" if collector.get("outcome") == "passed" else "❗"
|
|
f.write(f"<details>\n<summary>{emoji} `{nodeid}`</summary>\n\n")
|
|
|
|
for key, val in collector.items():
|
|
if key == "nodeid":
|
|
continue
|
|
f.write(f"- **{key}**:\n")
|
|
if isinstance(val, dict):
|
|
f.write(format_dict(val) + "\n")
|
|
elif isinstance(val, list):
|
|
if all(isinstance(item, dict) for item in val):
|
|
f.write(format_list_of_dicts(val) + "\n")
|
|
else:
|
|
f.write(" ```\n")
|
|
f.write("\n".join(str(item) for item in val))
|
|
f.write("\n ```\n")
|
|
else:
|
|
f.write(f" {val if val else 'None'}\n")
|
|
f.write("</details>\n\n")
|
|
|
|
if 'tests' in data:
|
|
current_file = None
|
|
for test in data['tests']:
|
|
nodeid = test['nodeid']
|
|
test_name = nodeid.split("::")[-1].split('[')[0]
|
|
file_name = nodeid.split("::")[0]
|
|
|
|
if current_file != file_name:
|
|
current_file = file_name
|
|
f.write(f"\n## 📄 Fichier: `{current_file}`\n")
|
|
|
|
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")
|
|
|
|
# Statut
|
|
if "outcome" in test:
|
|
outcome = test["outcome"]
|
|
emoji_map = {
|
|
"passed": "✅",
|
|
"skipped": "⏭️",
|
|
"failed": "❌",
|
|
"error": "💥",
|
|
}
|
|
emoji = emoji_map.get(outcome, "❔")
|
|
f.write(f"- **Statut:** {emoji} `{outcome}`\n")
|
|
|
|
# Durée
|
|
if "call" in test and "duration" in test["call"]:
|
|
f.write(f"- **Durée:** `{test['call']['duration']:.6f}` s\n")
|
|
|
|
# Détails
|
|
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")
|
|
f.write("\n".join(str(item) for item in v))
|
|
f.write("\n ```\n")
|
|
else:
|
|
f.write(" ```\n")
|
|
f.write(f"{v if v else 'None'}\n")
|
|
f.write(" ```\n")
|
|
f.write("\n" + "-"*50 + "\n")
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Convert Pytest JSON report to Markdown")
|
|
parser.add_argument("--input", required=True, help="Chemin du fichier JSON d'entrée")
|
|
parser.add_argument("--output", required=True, help="Chemin du fichier Markdown de sortie")
|
|
args = parser.parse_args()
|
|
|
|
json_to_adaptive_md(args.input, args.output) |