Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Meson test log to HTML conversion script
#!/usr/bin/env python3
# Turns a Meson test log into an HTML report
# Copyright 2019 GNOME Foundation
# SPDX-License-Identifier: LGPL-2.1-or-later
import argparse
import datetime
import json
import os
import sys
from jinja2 import Template
<!DOCTYPE html>
<html lang="en">
<title>{{ report.project_name }} Test Report</title>
<meta charset="utf-8" />
<h1>{{ report.project_name }} :: Test Reports</h1>
<div class="report-meta">
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
<p><strong>Date:</strong> <time datetime="{{ }}">{{ report.locale_date }}</time></p>
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
<div class="summary">
<li><strong>Total units:</strong> {{ report.total_units }}</li>
<li><strong>Passed:</strong> {{ report.total_successes }}</li>
<li><strong>Failed:</strong> {{ report.total_failures }}</li>
{% for suite_result in report.results_list %}
<div class="result">
<h3>Suite: {{ suite_result.suite_name }}</h3>
<li><strong>Units:</strong> {{ suite_result.n_units }}</li>
<li><strong>Passed:</strong> {{ suite_result.n_successes }}</li>
<li><strong>Failed:</strong> {{ suite_result.n_failures }}</li>
{% for failure in suite_result.failures %}
{% if loop.first %}
{% endif %}
<li>{{ }} - result: <span class="failure">{{ failure.result }}</span><br/>
<pre>{{ failure.stdout }}</pre>
{% if loop.last %}
{% endif %}
{% endfor %}
{% endfor %}
aparser = argparse.ArgumentParser(description='Turns a Meson test log into an HTML report')
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
aparser.add_argument('--output', metavar='FILE',
help='The output HTML file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
aparser.add_argument('infile', metavar='FILE',
help='The input testlog.json, stdin by default',
type=argparse.FileType('r', encoding='UTF-8'),
args = aparser.parse_args()
outfile = args.output
suites = {}
for line in args.infile:
data = json.loads(line)
(full_suite, unit_name) = data['name'].split(' / ')
(project_name, suite_name) = full_suite.split(':')
unit = {
'project-name': project_name,
'suite': suite_name,
'name': unit_name,
'duration': data['duration'],
'returncode': data['returncode'],
'result': data['result'],
'stdout': data['stdout'],
units = suites.setdefault(full_suite, [])
report = {}
report['date'] = datetime.datetime.utcnow()
report['locale_date'] = report['date'].strftime("%c")
report['project_name'] = args.project_name
report['job_id'] = args.job_id
report['branch_name'] = args.branch
report['total_successes'] = 0
report['total_failures'] = 0
report['total_units'] = 0
report['results_list'] = []
for name, units in suites.items():
(project_name, suite_name) = name.split(':')
print('Processing {} suite {}:'.format(project_name, suite_name))
def if_failed(unit):
if unit['result'] in ['FAIL', 'TIMEOUT']:
return True
return False
def if_succeded(unit):
if unit['result'] in ['OK', 'EXPECTEDFAIL', 'SKIP']:
return True
return False
successes = list(filter(if_succeded, units))
failures = list(filter(if_failed, units))
n_units = len(units)
n_successes = len(successes)
n_failures = len(failures)
report['total_units'] += n_units
report['total_successes'] += n_successes
report['total_failures'] += n_failures
print(' - {}: {} total, {} pass, {} fail'.format(suite_name, n_units, n_successes, n_failures))
suite_report = {
'suite_name': suite_name,
'n_units': n_units,
'successes': successes,
'n_successes': n_successes,
'failures': failures,
'n_failures': n_failures,
template = Template(REPORT_TEMPLATE)
outfile.write(template.render({'report': report}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.