Skip to content

Commit

Permalink
Feature/limit step report output size (#224)
Browse files Browse the repository at this point in the history
* feat: limit step report output size
  • Loading branch information
JoSglch authored Jan 12, 2023
1 parent 608d73f commit a4a691c
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 15 deletions.
58 changes: 58 additions & 0 deletions examples/test_stepreport/stepreport_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,61 @@ def test_run(self):
self.assertAlmostEqual(voltage, 4, delta=1, msg="Check voltage device")

logging.info(f"I HAVE RUN 0.1.1 for tag {self.tag}!")


@pykiso.define_test_parameters(
suite_id=1,
case_id=3,
)
class WrapLongTextTest(pykiso.BasicTest):
"""This test shows wrapping of long results into foldable html elements"""

def setUp(self):
"""Set header information and check setup conditions"""
super().setUp()
# additional data to include in the step-report
self.step_report.header["Version_device"] = "2022-1234"

def test_run(self):
"""Write long results to the step report to show how foldable html
elements get used to make the report overview more readable
"""
logging.info(
f"--------------- RUN: {self.test_suite_id}, {self.test_case_id} ---------------"
)

# data to test
device_on = True
actual_dummy_result = {"result": True}
expected_dummy_result = {
"result": "pykiso is an integration test framework. With it, it is possible to write: Whitebox integration tests directly on my target device, Graybox integration tests to make sure the communication-link with my target device is working as expected, Blackbox integration tests to make sure my external device interfaces are working as expected",
}

# check that it works with multiple tables
self.step_report.current_table = "First table"

self.assertEqual(
expected_dummy_result,
expected_dummy_result,
msg="The very long message should be wrapped",
)

self.step_report.current_table = "Second table"

with self.subTest("Non critical checks"):
# This check will fail but the test continues
self.assertFalse(device_on, msg="Some check")

# assert with custom message
# assert msg overwritten when step_report_message not null
self.step_report.message = "Big data message"

self.assertEqual(
expected_dummy_result, expected_dummy_result, msg="Check big data"
)

self.assertEqual(
expected_dummy_result, actual_dummy_result, msg="Check big data"
)

logging.info(f"I HAVE RUN 0.1.1 for tag {self.tag}!")
5 changes: 5 additions & 0 deletions src/pykiso/test_result/templates/report_template.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ body {
text-transform: uppercase;
}

summary {
text-decoration: underline;
cursor: pointer;
}

/* Media Queries*/

@media screen and (max-width: 600px) {
Expand Down
48 changes: 33 additions & 15 deletions src/pykiso/test_result/templates/report_template.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,31 @@
<div class="navbar-header" style = " background-color: rgb(255, 255, 255); margin:0; padding:0;">
<img src = "https://github.com/eclipse/kiso-testing/raw/master/docs/images/pykiso_logo.png" alt = "Pykiso report" width="15%" height="15%">
</div>
{# For each TestClass #}
{# For each TestClass -#}
{% for class_name, class_content in ALL_STEP_REPORT.items() -%}
<hr>
<div class="col-12 text-left">
{# Add Title and description #}
{# Add Title and description -#}
<h2>ITF Test Report for: <a href="{{class_content["file_path"]}}">{{class_name}}</a>
{% if class_content["succeed"] %}
{% if class_content["succeed"] -%}
-> [<span style="color:green;">Success</span>]
{% else %}
{% else -%}
-> [<span style="color:red;">Fail</span>]
{% endif %}
{%- endif %}
</h2>
<h3>Test Description:</h3>
<p> {{class_content["description"] | replace("\n", "<br/>\n") }}</p>
<p>{{class_content["description"] | replace("\n", "<br/>\n") }}</p>
<h3>Date, Time, Software versions:</h3>
<p>
{# Add additional information from header key #}
{# Add additional information from header key -#}
{% for data in [class_content["time_result"], class_content["header"]] -%}
{% for key, value in data.items() -%}
<u>{{key}}</u>: {{value}}</br>
{%- endfor %}
{%- endfor %}
</p>

{# For each test (setUp, run, tearDown) #}
{% for test_name, test_content in class_content["test_list"].items() -%}
{#- For each test (setUp, run, tearDown) -#}
{% for test_name, test_content in class_content["test_list"].items() %}
{% set test_success = is_test_success(test_content) -%}
<details {% if not test_success %}open{% endif %}><summary><h3>{{test_name}}
{% if test_success -%}<span style="color:green;">Success</span>
Expand All @@ -38,15 +37,15 @@
<table>
<thead>
<tr>
{# Set Columns name from the first row, excluding succeed flag #}
{# Set Columns name from the first row, excluding succeed flag -#}
<th scope="col" style="width: 3%">Step</th>
{% for column_name in test_content[0].keys() if column_name != "succeed" -%}
<th scope="col">{{column_name}}</th>
{%- endfor %}
</tr>
</thead>
<tbody>
{# Loop over each assert method called (step-report) -#}
{#- Loop over each assert method called (step-report) -#}
{% for row in test_content -%}
{# Set cell color variable according to the assert result and emptiness -#}
{% if row.pop("succeed") -%}
Expand All @@ -56,13 +55,28 @@
{% set color_cell = "background-color: rgb(236, 160, 160);" -%}
{% set color_empty_cell = "background-color: rgb(236, 160, 160);" -%}
{%- endif %}
{# Needed for setting unique class per row in html in inner loop -#}
{% set row_index = loop.index -%}
<tr>
<th scope="row" style="{{color_cell}}" >{{loop.index}}</th>
{# Loop over each cell of the row -#}
{#- Loop over each cell of the row -#}
{% for col_value in row.values() -%}
{# Set the value and apply colors to the cell -#}
{#- Set the value and apply colors to the cell #}
<td {% if (col_value or col_value == False) %} style="{{color_cell}}" {% else %} style="{{color_empty_cell}}" {% endif %}>
{{col_value}}
{# Use a <details> if content is too long for better results overview and synchronize toggling them per row -#}
{% if col_value | string | length > 100 -%}
<details class="{{class_name}}{{test_name}}row_{{row_index}}" ontoggle="toggleDetailsInRow(this, '{{class_name}}{{test_name}}row_{{row_index}}')">
<summary>{{col_value | string | truncate(53, true, leeway = 0)}}</summary>
<br>
<div>
{{col_value}}
</div>
</details>
{%- else -%}
<div>
{{col_value}}
</div>
{%- endif %}
</td>
{%- endfor %}
</tr>
Expand All @@ -79,3 +93,7 @@
<style type="text/css">
{% include "templates/report_template.css" %}
</style>

<script>
{% include "templates/report_template_script.js" %}
</script>
40 changes: 40 additions & 0 deletions src/pykiso/test_result/templates/report_template_script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* synchronize the toggling of all details elements by class name
* class name is unique for each test + row combination and gets rendered in by jinja
* @param {HTMLDetailsElement} element the details element being toggled
* @param {string} className class attribute of all details elements in the row
*/
function toggleDetailsInRow(element, className) {
element.scrollIntoView();
const isOpen = element.hasAttribute("open");
const detailsElements = document.getElementsByClassName(className);
for (details of detailsElements) {
details.open = isOpen;
isOpen ? setSummary("Click to minimize", details) : setTruncatedSummary(details);
}
}

/* helper functions */

/**
* set the summary text of the details element
* @param {string} content new content of the summary element
* @param {HTMLDetailsElement} detailsElement parent of the summary being modified
*/
function setSummary(content, detailsElement) {
const summaryElement = detailsElement.getElementsByTagName("summary")[0];
summaryElement.innerHTML = content;
}

/**
* same result as jinja truncate when rendering to set summary after closing
* @param {HTMLDetailsElement} detailsElement parent of the summary being modified
* @param {number} length length to cut the content to, default is 50
* @returns the truncated string
*/
function setTruncatedSummary(detailsElement, length = 50) {
const divElement = detailsElement.getElementsByTagName("div")[0];
let shortened = divElement.textContent.trim().slice(0, length);
shortened = shortened + "...";
setSummary(shortened, detailsElement);
}

0 comments on commit a4a691c

Please sign in to comment.