-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreport_generator.py
More file actions
165 lines (139 loc) · 5.63 KB
/
report_generator.py
File metadata and controls
165 lines (139 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# report_generator.py
import json
import os
import sys
from pathlib import Path
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.lib.enums import TA_CENTER
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
def main():
# 1) Locate the JSON report
rpt_path = Path("report.json")
if not rpt_path.exists():
print("⚠️ report.json not found, skipping PDF generation")
return
try:
data = json.loads(rpt_path.read_text(encoding="utf-8"))
except Exception as e:
print(f"❌ ERROR reading report.json: {e}", file=sys.stderr)
return
summary = data.get("summary", {})
total = summary.get("total", summary.get("collected", 0))
passed = summary.get("passed", 0)
failed = summary.get("failed", 0)
# 2) Generate a .md document
md_lines = [
"# Test Report Summary",
f"- **Total tests:** {total}",
f"- **Passed:** {passed}",
f"- **Failed:** {failed}",
"",
"## Failed Tests Details",
]
for t in data.get("tests", []):
if t.get("outcome") == "failed":
nodeid_md = t["nodeid"]
# look up the assertion message under call.crash.message
msg = t.get("call", {}) \
.get("crash", {}) \
.get("message", "<no message>")
md_lines.append(f"- `{nodeid_md}`: {msg}")
md_text = "\n".join(md_lines)
with open("TEST_REPORT.md", "w", encoding="utf-8") as md_out:
md_out.write(md_text)
print("✔️ TEST_REPORT.md generated")
# 3) Prepare the PDF document
pdf_path = Path("TEST_REPORT.pdf")
doc = SimpleDocTemplate(
str(pdf_path),
pagesize=letter,
rightMargin=40, leftMargin=40,
topMargin=40, bottomMargin=40,
)
styles = getSampleStyleSheet()
# a centered title style
styles.add(ParagraphStyle(
name="CenteredTitle",
parent=styles["Title"],
alignment=TA_CENTER,
fontSize=18,
leading=22,
))
story = []
# 4) Add your logo (centered) if it exists
logo_path = Path("assets/logo.png")
if logo_path.exists():
try:
img_logo = Image(str(logo_path), width=2*inch, height=2*inch)
img_logo.hAlign = "CENTER"
story.append(img_logo)
story.append(Spacer(1, 12))
except Exception as img_err:
print(f"⚠️ Could not embed logo.png: {img_err}", file=sys.stderr)
# 5) Add a big, centered title
story.append(Paragraph("Test Report Summary", styles["CenteredTitle"]))
story.append(Spacer(1, 12))
# 6) Summary stats
body = styles["BodyText"]
story.append(Paragraph(f"<b>Total tests:</b> {total}", body))
story.append(Paragraph(f"<b>Passed:</b> {passed}", body))
story.append(Paragraph(f"<b>Failed:</b> {failed}", body))
story.append(Spacer(1, 12))
# 7) Failed‐tests header
story.append(Paragraph("Failed Tests Details", styles["Heading2"]))
story.append(Spacer(1, 6))
# 8) Loop through each failed test
for t in data.get("tests", []):
if t.get("outcome") == "failed":
nodeid = t["nodeid"]
msg = t.get("call", {}) \
.get("crash", {}) \
.get("message", "<no message>")
# —8a) Print the nodeid (bold)
safe_node = nodeid.replace("/", " / ")
header_text = f"<b>{safe_node}</b>:"
story.append(Paragraph(header_text, body))
story.append(Spacer(1, 4))
# —8b) Print the failure message itself (normal text)
# This ensures the failure message appears immediately before any screenshot.
story.append(Paragraph(msg, body))
story.append(Spacer(1, 8))
# —8c) Check for a screenshot in user_properties
screenshot_path = None
for name, value in t.get("user_properties", []):
if name == "screenshot":
screenshot_path = value
break
if screenshot_path:
abs_path = Path(os.getcwd()) / screenshot_path
print(f"▶️ Found screenshot for {nodeid}: {abs_path} (exists? {abs_path.exists()})")
if abs_path.is_file():
try:
# Scale to a reasonable size (6" wide, 3" tall)
img = Image(abs_path, width=6 * inch, height=3 * inch)
img.hAlign = "CENTER"
story.append(img)
story.append(Spacer(1, 12))
except Exception as img_err:
story.append(Paragraph(f"[Unable to insert screenshot: {img_err}]", body))
story.append(Spacer(1, 12))
else:
story.append(Paragraph("[No screenshot file found]", body))
story.append(Spacer(1, 12))
else:
story.append(Paragraph("[No screenshot captured]", body))
story.append(Spacer(1, 12))
# 9) Build the PDF (catch any exceptions)
print("ℹ️ About to build PDF…")
try:
doc.build(story)
print("✔️ TEST_REPORT.pdf generated")
except Exception as e:
print(f"❌ ERROR generating TEST_REPORT.pdf: {e}", file=sys.stderr)
fallback = Path("TEST_REPORT_ERROR.txt")
fallback.write_text(f"PDF generation failed:\n{e}\n", encoding="utf-8")
print(f"ℹ️ Wrote fallback error to {fallback}")
if __name__ == "__main__":
main()