diff --git a/cmd/install b/cmd/install index 4e8639a66..6477b85fb 100755 --- a/cmd/install +++ b/cmd/install @@ -20,4 +20,8 @@ source venv/bin/activate pip3 install -r framework/requirements.txt -deactivate +# Dependency for printing reports to pdf +# required by python package weasyprint +sudo apt-get install libpangocairo-1.0-0 + +deactivate \ No newline at end of file diff --git a/framework/python/src/common/testreport.py b/framework/python/src/common/testreport.py index ba35ff27a..d57db58cf 100644 --- a/framework/python/src/common/testreport.py +++ b/framework/python/src/common/testreport.py @@ -15,6 +15,8 @@ """Store previous test run information.""" from datetime import datetime +from weasyprint import HTML +from io import BytesIO DATE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S' @@ -82,3 +84,91 @@ def from_json(self, json_file): self.add_test(test_result) return self + + # Create a pdf file in memory and return the bytes + def to_pdf(self): + # Resolve the data as html first + report_html = self.to_html() + + # Convert HTML to PDF in memory using weasyprint + pdf_bytes = BytesIO() + HTML(string=report_html).write_pdf(pdf_bytes) + return pdf_bytes + + def to_html(self): + json_data = self.to_json() + return f''' + + + {self.generate_header()} + +

Test Results Summary

+ +
+

Device Information

+

MAC Address: {json_data["device"]["mac_addr"]}

+

Manufacturer: {json_data["device"]["manufacturer"] or "Unknown"}

+

Model: {json_data["device"]["model"]}

+
+ +

Test Results

+ {self.generate_test_sections(json_data)} + + + ''' + + def generate_test_sections(self,json_data): + results = json_data["tests"]["results"] + sections = "" + for result in results: + sections += self.generate_test_section(result) + return sections + + def generate_test_section(self, result): + section_content = '
\n' + for key, value in result.items(): + if value is not None: # Check if the value is not None + formatted_key = key.replace('_', ' ').title() # Replace underscores and capitalize + section_content += f'

{formatted_key}: {value}

\n' + section_content += '
\n
\n' + return section_content + + def generate_header(self): + return f''' + + + + Test Results Summary + + + ''' + + def generate_css(self): + return ''' + body { + font-family: Arial, sans-serif; + margin: 20px; + } + h1 { + margin-bottom: 10px; + } + .summary { + border: 1px solid #ccc; + padding: 10px; + margin-bottom: 20px; + background-color: #f5f5f5; + } + .test-list { + list-style: none; + padding: 0; + } + .test-item { + margin-bottom: 10px; + } + .test-link { + text-decoration: none; + color: #007bff; + } + ''' \ No newline at end of file diff --git a/framework/python/src/test_orc/test_orchestrator.py b/framework/python/src/test_orc/test_orchestrator.py index eb5676e17..5835a4fed 100644 --- a/framework/python/src/test_orc/test_orchestrator.py +++ b/framework/python/src/test_orc/test_orchestrator.py @@ -86,6 +86,8 @@ def run_test_modules(self): report = TestReport().from_json(self._generate_report()) device.add_report(report) + self._write_reports(report) + self._test_in_progress = False self._timestamp_results(device) @@ -95,6 +97,25 @@ def run_test_modules(self): LOGGER.debug("Old test results cleaned") self._test_in_progress = False + def _write_reports(self, test_report): + out_dir = os.path.join( + self._root_path, RUNTIME_DIR, + self._session.get_target_device().mac_addr.replace(":", "")) + + # Write the json report + with open(os.path.join(out_dir,"report.json"),"w", encoding="utf-8") as f: + json.dump(test_report.to_json(), f, indent=2) + + # Write the html report + with open(os.path.join(out_dir,"report.html"),"w", encoding="utf-8") as f: + f.write(test_report.to_html()) + + # Write the pdf report + with open(os.path.join(out_dir,"report.pdf"),"wb") as f: + f.write(test_report.to_pdf().getvalue()) + + util.run_command(f"chown -R {self._host_user} {out_dir}") + def _generate_report(self): report = {} @@ -105,14 +126,6 @@ def _generate_report(self): "%Y-%m-%d %H:%M:%S") report["status"] = self._calculate_result() report["tests"] = self._session.get_report_tests() - out_file = os.path.join( - self._root_path, RUNTIME_DIR, - self._session.get_target_device().mac_addr.replace(":", ""), - "report.json") - - with open(out_file, "w", encoding="utf-8") as f: - json.dump(report, f, indent=2) - util.run_command(f"chown -R {self._host_user} {out_file}") return report def _calculate_result(self): diff --git a/framework/requirements.txt b/framework/requirements.txt index 560c2baf9..7141ae706 100644 --- a/framework/requirements.txt +++ b/framework/requirements.txt @@ -7,6 +7,9 @@ ipaddress netifaces scapy +# Requirments for the test_orc module +weasyprint + # Requirements for the API fastapi==0.99.1 psutil