{% macro render_status_icon(status) %} {% if status|lower == "passed" %} ✓ {% elif status|lower == "failed" %} ✗ {% elif status|lower == "broken" %} ⚠ {% elif status|lower == "skipped" %} → {% else %} ø {% endif %} {% endmacro %} {% macro render_search_filter(report) %}
main-icon
{% endmacro %} {% macro render_report_header(report) %}

{{ report.proj_name }}

Environment{{ report.env | upper }}
Base URL{{ report.base_url }}
Duration{{ report.duration }}
Start Time{{ report.start_time }}
End Time{{ report.end_time }}
{% endmacro %} {% macro render_summary(report) %} {% set passed = report.run_results.PASSED %} {% set failed = report.run_results.FAILED %} {% set broken = report.run_results.BROKEN %} {% set skipped = report.run_results.SKIPPED %} {% set total = passed + failed + broken + skipped %}

Results Summary

{{ total }}
Total
100%
{% for label, count, status, icon in [('Passed', passed, 'passed', '✓'), ('Failed', failed, 'failed', '✗'), ('Broken', broken, 'broken', '⚠'), ('Skipped', skipped, 'skipped', '→')] %}
{{ count }}
{{ icon }}
{{ label }}
{{ (count / total * 100 if total > 0 else 0) | round(1) }}%
{% endfor %}
{% endmacro %} {% macro render_notes(report) %}

Notes

{% if report.notes %} {% set notes = report.notes.notes or [] %} {% for note in notes %}
● {{ note | escape }}
{% endfor %} {% endif %}
{% endmacro %} {% macro render_module(module_name, module_data, steps) %}

{{ module_name }} {% for status in ['PASSED', 'FAILED', 'BROKEN', 'SKIPPED'] %} {% if module_data.results[status] %} {{ module_data.results[status] }} {{ render_status_icon(status.lower()) }} {% endif %} {% endfor %}

{% for test_name, test_runs in module_data.tests.items() %} {{ render_test(test_name, test_runs, steps) }} {% endfor %}
{% endmacro %} {% macro render_status_summary(test_runs) %} {% set ns = namespace(passed=0, failed=0, broken=0, skipped=0) %} {% for run in test_runs %} {% if run.status == 'PASSED' %} {% set ns.passed = ns.passed + 1 %} {% elif run.status == 'FAILED' %} {% set ns.failed = ns.failed + 1 %} {% elif run.status == 'BROKEN' %} {% set ns.broken = ns.broken + 1 %} {% elif run.status == 'SKIPPED' %} {% set ns.skipped = ns.skipped + 1 %} {% endif %} {% endfor %} {% if ns.passed %}
{{ ns.passed }} {{ render_status_icon('PASSED') }}
{% endif %} {% if ns.failed %}
{{ ns.failed }} {{ render_status_icon('FAILED') }}
{% endif %} {% if ns.broken %}
{{ ns.broken }} {{ render_status_icon('BROKEN') }}
{% endif %} {% if ns.skipped %}
{{ ns.skipped }} {{ render_status_icon('SKIPPED') }}
{% endif %} {% endmacro %} {% macro render_test(test_name, test_runs, steps) %} {% if test_runs | length == 1 %} {{ render_test_block(test_runs[0], steps) }} {% else %} {% set ns = namespace(min_start=none, max_dur=0, max_exec=0, has_failed=False, has_broken=False, has_skipped=False, has_passed=False) %} {% for run in test_runs %} {% set ns.min_start = run.start_time if ns.min_start is none else (run.start_time if run.start_time < ns.min_start else ns.min_start) %} {% set dur = (run.duration or 0) %} {% set ns.max_dur = dur if dur > ns.max_dur else ns.max_dur %} {% set exec = run.execution_count %} {% set ns.max_exec = exec if exec > ns.max_exec else ns.max_exec %} {% if run.status == 'FAILED' %}{% set ns.has_failed = True %}{% endif %} {% if run.status == 'BROKEN' %}{% set ns.has_broken = True %}{% endif %} {% if run.status == 'SKIPPED' %}{% set ns.has_skipped = True %}{% endif %} {% if run.status == 'PASSED' %}{% set ns.has_passed = True %}{% endif %} {% endfor %} {% if ns.has_failed %} {% set agg_status = 'FAILED' %} {% elif ns.has_broken %} {% set agg_status = 'BROKEN' %} {% elif ns.has_skipped %} {% set agg_status = 'SKIPPED' %} {% else %} {% set agg_status = 'PASSED' %} {% endif %}
{{ test_name }}
{{ render_status_summary(test_runs) }}
{% for run in test_runs %} {{ render_test_block(run, steps, is_sub=True) }} {% endfor %}
{% endif %} {% endmacro %} {% macro render_test_block(test_run, steps, is_sub=False) %} {% set sub_class = "test-sub" if is_sub else "" %} {% set test_id = "test_" ~ (test_run.name|replace(" ", "_")) %}
{{ render_test_header(test_run) }}
{{ render_test_tabs(test_run, steps) }}
{% endmacro %} {% macro render_test_header(test_run) %}
{% if test_run.execution_count > 1 %} {{ test_run.execution_count - 1 }} {% else %} {{ render_status_icon(test_run.status) }} {% endif %}
{{ test_run.name }}
{{ test_run.duration or 0 }}s
{% endmacro %} {% macro render_test_tabs(test, steps) %}
{% set step_data = None %} {% if test.steps %} {% set step_data = steps.get(test.steps[-1]) %} {% endif %} {% if step_data %} {% if step_data.get('setup') %} {% endif %} {% if step_data.get('call') %} {% endif %} {% if step_data.get('teardown') %} {% endif %} {% endif %} {% if test.attachments %} {% endif %} {% if test.error %} {% endif %}
{% if test.description %}{{ render_description(test.description) }}{% endif %} {% if test.info %}{{ render_info(test.info) }}{% endif %} {% if test.known_bugs %}{{ render_known_bugs(test.known_bugs) }}{% endif %}
{% if test.steps %} {% if test.steps | length > 1 %} {% set last_step_data = steps.get(test.steps[-1]) %} {% if last_step_data %} {% for stage, _ in last_step_data.items() %}
{% for attempt_id in test.steps %} {% set step_data = steps.get(attempt_id).get(stage) %} {% if step_data %} {% set attempt_index = loop.index %}
{{ attempt_index - 1 }}
{% for step in step_data %} {{ render_step(step) }} {% endfor %}
{% endif %} {% endfor %}
{% endfor %} {% endif %} {% else %} {% set step_data = steps.get(test.steps[0]) %} {% if step_data %} {% for stage, stage_steps in step_data.items() %}
{% for step in stage_steps %} {{ render_step(step) }} {% endfor %}
{% endfor %} {% endif %} {% endif %} {% else %}
No step details available
{% endif %} {% if test.attachments %}
{{ render_attachments(test.attachments) }}
{% endif %} {% if test.error %}
{{ render_error(test.error, test.stacktrace, test.attachments) }}
{% endif %}
{% endmacro %} {% macro render_description(description) %}

Description

{{ description }}
{% endmacro %} {% macro render_info(info) %}

Information

{% for key, value in info.items() %}
{{ key }}
{{ render_info_value(value, False) }}
{% endfor %}
{% endmacro %} {% macro render_info_value(value, is_sub=False) %} {% if value is mapping %} {% for sub_key, sub_value in value.items() %} {% if is_sub %}
{% else %}
{% endif %} 🞂 {{ sub_key | escape }}: {{ render_info_value(sub_value, True) }}
{% endfor %} {% elif value is sequence and value is not string %} {% for sub_value in value %} {% if sub_value is mapping %} {{ render_info_value(sub_value, is_sub) }} {% else %} {% if is_sub %}
{% else %}
{% endif %} ● {{ render_info_value(sub_value, True) }}
{% endif %} {% endfor %} {% else %} {% if value is string %} {% if '

Known Bugs

{% for bug in known_bugs %}
{% if bug.url %} View Bug Report {% endif %} {% if bug.description %}
{{ bug.description }}
{% endif %}
{% endfor %}
{% endmacro %} {% macro render_step(step) %} {% set has_addons = step.expected or step.info or step.error or step.attachments or step.known_bugs %} {% if step.id.startswith('print_') %}
{{ step.title | escape }}
{% else %}
{% if has_addons or step.steps %}
{% else %}
{% endif %}
{{ step.title | escape }}
{{ step.duration or 0 }}s {% if has_addons or step.steps %} {% if has_addons %} {% if step.error %}{% endif %} {% if step.attachments %}{% endif %} {% if step.info %}{% endif %} {% if step.known_bugs %}{% endif %} {% if step.expected %}{% endif %} {% endif %} {% if step.steps %} {% set count_steps = namespace(count=0, prints=0) %} {% for s in step.steps %} {% if s.id.startswith('step_') %} {% set count_steps.count = count_steps.count + 1 %} {% else %} {% set count_steps.prints = count_steps.prints + 1 %} {% endif %} {% endfor %} {% if count_steps.count > 0 %} {{ count_steps.count }} sub-step{{ 's' if count_steps.count > 1 else '' }} {% endif %} {% if count_steps.prints > 0 %} {{ count_steps.prints }} print{{ 's' if count_steps.prints > 1 else '' }} {% endif %} {% endif %} {% endif %}
{% if has_addons %}
{% if step.expected %}

Expected

{{ step.expected }}
{% endif %} {% if step.error %} {{ render_error(step.error.exc, step.error.tb) }} {% endif %} {% if step.info %} {{ render_info(step.info) }} {% endif %} {% if step.attachments %} {{ render_attachments(step.attachments) }} {% endif %} {% if step.known_bugs %} {{ render_known_bugs(step.known_bugs) }} {% endif %}
{% endif %} {% if step.steps %}
{% for child_step in step.steps %} {{ render_step(child_step) }} {% endfor %}
{% endif %}
{% endif %} {% endmacro %} {% macro render_attachments(attachments) %}
{% for attachment in attachments %} {% set name = attachment.name %} {% set type = attachment.type_ or '' %} {% set lower_name = name.lower() %}
{% if type.startswith('image/') or lower_name.endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')) %} {{ name }} {% elif type == 'application/pdf' or lower_name.endswith('.pdf') %} {% elif 'spreadsheet' in type or lower_name.endswith(('.xls', '.xlsx', '.ods')) %} {% elif type.startswith('text/') or lower_name.endswith(('.txt', '.log', '.json', '.md', '.py', '.yml', '.yaml')) %} {% elif lower_name.endswith(('.zip', '.tar', '.gz', '.rar')) %} {% else %} {% endif %} {{ name }}
{% endfor %}
{% endmacro %} {% macro render_error(exc, stacktrace, attachments=None) %} {% if attachments %} {% set ns = namespace(items=[]) %} {% for attachment in attachments %} {% if attachment.name.startswith('err_') %} {% set _ = ns.items.append(attachment) %} {% endif %} {% endfor %} {% if ns.items %}
{% for attachment in ns.items %}
{{ attachment.name }} {{ attachment.name }}
{% endfor %}
{% endif %} {% endif %}
{{ exc | escape }}
{% if stacktrace %}

Stacktrace

{{ stacktrace | escape }}
{% endif %}
{% endmacro %}