Update json_to_md.py
This commit is contained in:
+60
-102
@@ -45,6 +45,7 @@ def load_allure_metadata(allure_test_cases_dir):
|
||||
"parameters": params,
|
||||
"severity": severity
|
||||
}
|
||||
# ✅ Debug print
|
||||
param_vals = tuple(p["value"] for p in params)
|
||||
print(f"[✔️] Parsed: {full_name} {param_vals}")
|
||||
except Exception as e:
|
||||
@@ -69,26 +70,49 @@ def json_to_md_nested(json_path, md_path, allure_dir=None):
|
||||
f.write(f"- **Durée totale**: `{duration:.3f}`s\n" if duration else "- **Durée totale**: `None`\n")
|
||||
f.write("\n")
|
||||
|
||||
if "tests" in data:
|
||||
# Numérotation globale avant séparation
|
||||
all_tests = data["tests"]
|
||||
for idx, test in enumerate(all_tests, 1):
|
||||
test['global_index'] = idx
|
||||
if "collectors" in data:
|
||||
f.write("## 📚 Collectés\n")
|
||||
for collector in data["collectors"]:
|
||||
outcome = collector.get("outcome", "unknown")
|
||||
emoji = "✅" if outcome == "passed" else "❌"
|
||||
nodeid = collector.get("nodeid", "unknown")
|
||||
short_node = nodeid.split("[")[0]
|
||||
f.write(f"<details>\n<summary>{emoji} `{short_node}`</summary>\n\n")
|
||||
f.write(f"- **outcome:** `{outcome}`\n")
|
||||
results = collector.get("result", [])
|
||||
if results:
|
||||
f.write("- **result:**\n```\n")
|
||||
for item in results:
|
||||
if isinstance(item, dict):
|
||||
for k, v in item.items():
|
||||
f.write(f"{k}: {v}\n")
|
||||
f.write("\n")
|
||||
else:
|
||||
f.write(f"{item}\n")
|
||||
f.write("```\n")
|
||||
else:
|
||||
f.write("- **result:** `None`\n")
|
||||
f.write("</details>\n\n")
|
||||
|
||||
if "tests" in data and "summary" in data:
|
||||
f.write("## 🔎 Tests (Groupés par Statut)\n")
|
||||
|
||||
# Récupérer l'ordre des statuts depuis le summary
|
||||
# 1. Préparer la numérotation globale
|
||||
all_tests = data["tests"]
|
||||
test_counter = 1 # Compteur global
|
||||
|
||||
# 2. Récupérer l'ordre des statuts depuis le summary
|
||||
summary_items = list(data["summary"].items())
|
||||
total_index = next((i for i, (k,_) in enumerate(summary_items) if k == "total"), len(summary_items))
|
||||
status_order = [k for k, _ in summary_items[:total_index] if k not in ['collected', 'duration']]
|
||||
|
||||
# Grouper les tests par statut
|
||||
# 3. Grouper les tests par statut
|
||||
tests_by_status = defaultdict(list)
|
||||
for test in all_tests:
|
||||
outcome = test.get("outcome", "unknown")
|
||||
tests_by_status[outcome].append(test)
|
||||
|
||||
# Afficher dans l'ordre du summary
|
||||
# 4. Afficher dans l'ordre exact du summary
|
||||
for status in status_order:
|
||||
if status not in tests_by_status:
|
||||
continue
|
||||
@@ -99,102 +123,36 @@ def json_to_md_nested(json_path, md_path, allure_dir=None):
|
||||
|
||||
f.write(f"<details>\n<summary>{emoji} {status_label} ({count})</summary>\n\n")
|
||||
|
||||
# Grouper par fichier/fonction
|
||||
grouped = defaultdict(lambda: defaultdict(list))
|
||||
for test in tests_by_status[status]:
|
||||
f.write(f"<details>\n<summary>{emoji} #{test['global_index']}</summary>\n\n")
|
||||
|
||||
nodeid = test.get("nodeid", "")
|
||||
f.write(f"- **Statut:** {emoji} `{status}`\n")
|
||||
duration = test.get("call", {}).get("duration")
|
||||
f.write(f"- **Durée:** `{duration:.6f}` s\n" if duration else "- **Durée:** `None`\n")
|
||||
parts = nodeid.split("::")
|
||||
filename = parts[0].replace("tests\\", "").replace("tests/", "")
|
||||
funcname = parts[1].split("[")[0]
|
||||
grouped[filename][funcname].append(test)
|
||||
|
||||
# Afficher la structure fichier/fonction
|
||||
for filename, funcs in grouped.items():
|
||||
f.write(f"<details>\n<summary>📁 {filename}</summary>\n\n")
|
||||
for funcname, tests in funcs.items():
|
||||
f.write(f"<details>\n<summary>🔧 Fonction: `{funcname}`</summary>\n\n")
|
||||
for test in tests: # On ne fait plus enumerate(tests, 1)
|
||||
f.write(f"<details>\n<summary>{emoji} #{test_counter}</summary>\n\n")
|
||||
test_counter += 1 # Incrémenter le compteur global
|
||||
|
||||
# Détails du test (inchangé)
|
||||
nodeid = test.get("nodeid", "")
|
||||
f.write(f"- **Statut:** {emoji} `{status}`\n")
|
||||
duration = test.get("call", {}).get("duration")
|
||||
f.write(f"- **Durée:** `{duration:.6f}` s\n" if duration else "- **Durée:** `None`\n")
|
||||
|
||||
# Partie Allure
|
||||
full_name = normalize_nodeid(nodeid)
|
||||
allure_info = allure_data.get(full_name)
|
||||
if allure_info:
|
||||
if allure_info["parameters"]:
|
||||
f.write("- **Paramètres (Allure):**\n")
|
||||
for param in allure_info["parameters"]:
|
||||
name = param.get("name")
|
||||
val = param.get("value")
|
||||
f.write(f" - `{name}` = `{val}`\n")
|
||||
f.write("\n")
|
||||
if allure_info["severity"]:
|
||||
f.write(f"- **Sévérité:** `{allure_info['severity']}`\n")
|
||||
|
||||
if status != "passed":
|
||||
f.write("- **Détails d'erreur:**\n")
|
||||
f.write("<details>\n<summary>Détails complets</summary>\n\n")
|
||||
call_data = test.get("call", {})
|
||||
if call_data:
|
||||
for key, value in call_data.items():
|
||||
f.write(f"- **{key}:**\n")
|
||||
f.write("```\n")
|
||||
if isinstance(value, (dict, list)):
|
||||
f.write(f"{json.dumps(value, indent=2, ensure_ascii=False)}\n")
|
||||
else:
|
||||
f.write(f"{str(value)}\n")
|
||||
f.write("```\n\n")
|
||||
else:
|
||||
f.write("Aucun détail disponible\n")
|
||||
f.write("</details>\n")
|
||||
|
||||
if "collectors" in data:
|
||||
f.write("## 📚 Collectés (Arborescence)\n")
|
||||
|
||||
# Construire l'arborescence hiérarchique
|
||||
def build_tree(collectors):
|
||||
tree = {}
|
||||
for collector in collectors:
|
||||
nodeid = collector.get("nodeid", "")
|
||||
parts = [p for p in nodeid.replace("\\", "/").split("/") if p]
|
||||
|
||||
current = tree
|
||||
for part in parts[:-1]:
|
||||
if part not in current:
|
||||
current[part] = {}
|
||||
current = current[part]
|
||||
|
||||
if parts:
|
||||
last_part = parts[-1]
|
||||
if last_part not in current:
|
||||
current[last_part] = [] # Initialise comme liste
|
||||
if isinstance(current[last_part], list):
|
||||
current[last_part].append(collector)
|
||||
else:
|
||||
current[last_part] = [collector] # Convertit en liste si nécessaire
|
||||
return tree
|
||||
|
||||
# Afficher l'arborescence récursivement
|
||||
def print_tree(node, level=0):
|
||||
indent = " " * level
|
||||
for key, value in node.items():
|
||||
if isinstance(value, dict):
|
||||
f.write(f"{indent}<details>\n{indent}<summary>📁 {key}</summary>\n\n")
|
||||
print_tree(value, level+1)
|
||||
f.write(f"{indent}</details>\n\n")
|
||||
elif isinstance(value, list):
|
||||
for collector in value:
|
||||
outcome = collector.get("outcome", "unknown")
|
||||
emoji = "✅" if outcome == "passed" else "❌"
|
||||
f.write(f"{indent}<details>\n{indent}<summary>{emoji} {key}</summary>\n\n")
|
||||
f.write(f"{indent}- **outcome:** `{outcome}`\n")
|
||||
results = collector.get("result", [])
|
||||
if results:
|
||||
f.write(f"{indent}- **result:**\n```\n")
|
||||
for item in results:
|
||||
if isinstance(item, dict):
|
||||
for k, v in item.items():
|
||||
f.write(f"{k}: {v}\n")
|
||||
f.write("\n")
|
||||
else:
|
||||
f.write(f"{item}\n")
|
||||
f.write("```\n")
|
||||
else:
|
||||
f.write(f"{indent}- **result:** `None`\n")
|
||||
f.write(f"{indent}</details>\n\n")
|
||||
|
||||
collectors_tree = build_tree(data["collectors"])
|
||||
print_tree(collectors_tree)
|
||||
# ... (le reste du code pour Allure et les détails d'erreur reste inchangé)
|
||||
|
||||
f.write("</details>\n\n")
|
||||
f.write("</details>\n\n")
|
||||
f.write("</details>\n\n")
|
||||
f.write("</details>\n\n")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Convert JSON test results to Markdown.")
|
||||
@@ -207,4 +165,4 @@ def main():
|
||||
print(f"✅ Rapport généré dans {args.output}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user