Fix highlight_tables.py (#18090)

This commit is contained in:
Sofya Balandina 2023-06-23 12:12:42 +01:00 committed by GitHub
parent 098a4089c7
commit a9ef0b0678
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 206 additions and 228 deletions

View File

@ -65,6 +65,12 @@ def collect_xml_pathes(xmls):
opset_xmls = []
api_xmls = []
if sys.platform.startswith('win'):
if xmls.startswith("\\"):
xmls = "\\\\?\\UNC\\%s" % xmls
else:
xmls = "\\\\?\\%s" % xmls
for xml in list(Path(xmls).glob('**/*.xml')):
if re.match(OPSET_REPORT_NAME_RE, xml.as_posix()):
opset_xmls.append(xml)
@ -80,7 +86,8 @@ class HighlightTableCreator():
prev_xmls_opset,
current_xmls_api,
prev_xmls_api,
expected_devices=None) -> None:
expected_devices=None,
expected_test_mode=None) -> None:
self.current_xmls_opset = current_xmls_opset
self.prev_xmls_opset = prev_xmls_opset
@ -91,28 +98,20 @@ class HighlightTableCreator():
self.expected_devices = expected_devices
self.sw_plugins = set()
self.test_modes = ['Other']
self.test_modes_re = ''
self.expected_test_modes = expected_test_mode
self.ops_info = {}
self.general_pass_rate = {}
self.api_info = {}
def setup_test_modes(self, expected_test_modes):
self.test_modes = expected_test_modes + self.test_modes
self.test_modes_re = '|'.join(expected_test_modes)
logger.info(f'Test modes {self.test_modes}')
def get_test_mode_by_path(self, xml_path):
# Other
test_mode = self.test_modes[-1]
test_mode_match = None
if self.test_modes_re:
test_mode_match = re.match(f'.*({self.test_modes_re}).*', xml_path.as_posix())
if test_mode_match:
test_mode = test_mode_match.group(1)
# Expected name: report_[opset/api]_[device]_[test_mode].xml
# for apiConformance test_mode will be empty
test_mode = 'API'
xml_path_com = xml_path.stem.split('_')
if len(xml_path_com) == 4:
test_mode = xml_path_com[-1]
return test_mode
@ -156,16 +155,15 @@ class HighlightTableCreator():
logger.info("Opset info collecting is started")
ops_devices = set()
for test_mode in self.test_modes:
self.ops_info[test_mode] = {}
self.general_pass_rate[test_mode] = {}
for xml_path in self.current_xmls_opset:
test_mode = self.get_test_mode_by_path(xml_path)
if sys.platform.startswith('win') and xml_path.as_posix().startswith("\\"):
xml_path = "\\\\?\\UNC\\%s" % xml_path.as_posix()
else:
xml_path = "\\\\?\\%s" % xml_path.as_posix()
if self.expected_test_modes and test_mode not in self.expected_test_modes:
continue
self.ops_info.setdefault(test_mode, {})
self.general_pass_rate.setdefault(test_mode, {})
try:
xml_root = ET.parse(Path(xml_path)).getroot()
for device in xml_root.findall("results/*"):
@ -178,16 +176,21 @@ class HighlightTableCreator():
self.ops_info[test_mode][device.tag] = {'totalAmount': total_amount_ops,
'diffTotalAmount': 0,
'totalPass': total_passed_tests,
'diffTotalPass': 0}
'diffTotalPass': 0,
'title': f"{total_passed_tests} operations were successfully " +\
f"completed among {total_amount_ops} tested operations." }
self.general_pass_rate[test_mode][device.tag] = {'current': self.get_general_passrate(test_count, passed_tests), 'prev': 0,
'rel_current': self.get_general_passrate(rel_all, rel_passed), 'rel_prev': 0}
self.general_pass_rate[test_mode][device.tag] = {'current': self.get_general_passrate(test_count, passed_tests), 'diff': 0,
'rel_current': self.get_general_passrate(rel_all, rel_passed), 'rel_diff': 0,
'title': 'Total passrate on all operation set', 'rel_title': 'Relative passrate, calculated based on weight of operation'}
except ET.ParseError:
logger.error(f'Error parsing {xml_path}')
for xml_path in self.prev_xmls_opset:
test_mode = self.get_test_mode_by_path(xml_path)
if test_mode not in self.ops_info:
continue
try:
xml_root = ET.parse(xml_path).getroot()
for device in xml_root.findall("results/*"):
@ -198,10 +201,25 @@ class HighlightTableCreator():
self.ops_info[test_mode][device.tag]['diffTotalAmount'] = self.ops_info[test_mode][device.tag]['totalAmount'] - total_amount_ops
self.ops_info[test_mode][device.tag]['diffTotalPass'] = self.ops_info[test_mode][device.tag]['totalPass'] - total_passed_tests
self.general_pass_rate[test_mode][device.tag]['prev'] = round(self.general_pass_rate[test_mode][device.tag]['current'] -\
if self.ops_info[test_mode][device.tag]['diffTotalPass'] != 0:
self.ops_info[test_mode][device.tag]['title'] += f"\nThis is {'an increase' if self.ops_info[test_mode][device.tag]['diffTotalPass'] > 0 else 'a decrease'} of " +\
f"{self.ops_info[test_mode][device.tag]['diffTotalPass']} operations from the previous launch."
if self.ops_info[test_mode][device.tag]['diffTotalAmount'] != 0:
self.ops_info[test_mode][device.tag]['title'] += f"\nThe total number of operations has also changed, {self.ops_info[test_mode][device.tag]['diffTotalAmount']} operations " +\
f"{'more' if self.ops_info[test_mode][device.tag]['diffTotalAmount'] > 0 else 'less'}"
self.general_pass_rate[test_mode][device.tag]['diff'] = round(self.general_pass_rate[test_mode][device.tag]['current'] -\
self.get_general_passrate(test_count, passed_tests), 1)
self.general_pass_rate[test_mode][device.tag]['rel_prev'] = round(self.general_pass_rate[test_mode][device.tag]['rel_current'] -\
self.general_pass_rate[test_mode][device.tag]['rel_diff'] = round(self.general_pass_rate[test_mode][device.tag]['rel_current'] -\
self.get_general_passrate(rel_all, rel_passed), 1)
if self.general_pass_rate[test_mode][device.tag]['diff'] != 0:
self.general_pass_rate[test_mode][device.tag]['title'] += f"{' increased' if self.general_pass_rate[test_mode][device.tag]['diff'] > 0 else ' decreased'} of " +\
f"{self.general_pass_rate[test_mode][device.tag]['diff']}%"
if self.general_pass_rate[test_mode][device.tag]['rel_diff'] != 0:
self.general_pass_rate[test_mode][device.tag]['rel_title'] += f",{' increased' if self.general_pass_rate[test_mode][device.tag]['rel_diff'] > 0 else ' decreased'} of " +\
f"{self.general_pass_rate[test_mode][device.tag]['rel_diff']}%"
except ET.ParseError:
logger.error(f'Error parsing {xml_path}')
@ -230,7 +248,8 @@ class HighlightTableCreator():
self.sw_plugins.add(sw_plugin_name)
self.api_info[test_type.tag].setdefault(sw_plugin_name, {device.tag: {}})
self.api_info[test_type.tag][sw_plugin_name][device.tag] = {'passrate': float(sw_plugin.get('passrate', 0)), 'diff': 0,
'rel_passrate': float(sw_plugin.get('relative_passrate', 0)), "rel_diff": 0}
'rel_passrate': float(sw_plugin.get('relative_passrate', 0)), "rel_diff": 0,
'title': 'Passrate on optional API scope', 'rel_title': 'Passrate on mandatory API scope'}
except ET.ParseError:
logger.error(f'Error parsing {xml_path}')
@ -252,6 +271,13 @@ class HighlightTableCreator():
self.api_info[test_type.tag][sw_plugin_name][device.tag]['rel_diff'] = round(self.api_info[test_type.tag][sw_plugin_name][device.tag].get('rel_passrate', 0) -\
float(sw_plugin.get('relative_passrate')), 0)
if self.api_info[test_type.tag][sw_plugin_name][device.tag]['diff'] != 0:
self.api_info[test_type.tag][sw_plugin_name][device.tag]['title'] += f",{' increased' if self.api_info[test_type.tag][sw_plugin_name][device.tag]['diff'] > 0 else ' decreased'} of " +\
f"{self.api_info[test_type.tag][sw_plugin_name][device.tag]['diff']}% from previous run"
if self.api_info[test_type.tag][sw_plugin_name][device.tag]['rel_diff'] != 0:
self.api_info[test_type.tag][sw_plugin_name][device.tag]['rel_title'] += f",{' increased' if self.api_info[test_type.tag][sw_plugin_name][device.tag]['rel_diff'] > 0 else ' decreased'} of " +\
f"{self.api_info[test_type.tag][sw_plugin_name][device.tag]['rel_diff']}% from previous run"
except ET.ParseError:
logger.error(f'Error parsing {xml_path}')
@ -259,11 +285,6 @@ class HighlightTableCreator():
def create_html(self, output_folder=None, output_filename=None, report_tag="",
report_version="", current_commit="", prev_commit=""):
if 'Other' in self.ops_info and self.ops_info['Other'] == {}:
self.ops_info.pop('Other')
self.general_pass_rate.pop('Other')
self.test_modes.remove('Other')
sw_plugins = list(self.sw_plugins)
sw_plugins.sort()
if 'HW PLUGIN' in sw_plugins:
@ -278,7 +299,7 @@ class HighlightTableCreator():
res_summary = template.render(devices=self.devices,
ops_info=self.ops_info,
general_pass_rate=self.general_pass_rate,
expected_test_mode=self.test_modes,
expected_test_mode=self.ops_info.keys(),
api_info=self.api_info,
sw_plugins=sw_plugins,
report_tag=report_tag,
@ -303,27 +324,19 @@ if __name__ == "__main__":
current_xmls_opset, current_xmls_api = collect_xml_pathes(args.current_xmls)
prev_xmls_opset, prev_xmls_api = collect_xml_pathes(args.prev_xmls)
if len(current_xmls_opset) == 0 and len(current_xmls_api) == 0:
logger.error(f'It was not found xmls with name report_opset_[plugin].xml by path {args.current_xmls}')
logger.error(f'It was not found xmls with name report_api_[].xml by path {args.prev_xmls}')
exit(1)
elif len(current_xmls_opset) == 0 and args.expected_test_mode and\
if len(current_xmls_opset) == 0 and args.expected_test_mode and\
("static" in args.expected_test_mode or "dynamic" in args.expected_test_mode):
logger.error(f'It was not found xmls with name report_opset_[plugin].xml by path {args.current_xmls}')
exit(1)
elif len(current_xmls_api) == 0 and args.expected_test_mode and\
if len(current_xmls_api) == 0 and args.expected_test_mode and\
"apiConformance" in args.expected_test_mode:
logger.error(f'It was not found xmls with name report_api_[plugin].xml by path {args.current_xmls}')
exit(1)
table = HighlightTableCreator(current_xmls_opset,
prev_xmls_opset,
current_xmls_api,
prev_xmls_api,
args.expected_devices)
if args.expected_test_mode:
table.setup_test_modes(args.expected_test_mode)
args.expected_devices,
args.expected_test_mode)
table.collect_opset_info()
table.collect_api_info()

View File

@ -1,192 +1,156 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="template/style.css" />
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="template/filters.js"></script>
<script src="template/chosen.jquery.min.js" type="text/javascript"></script>
<title>Report</title>
<title>{% block title %}highlight_table{% endblock %}</title>
</head>
<body>
<div class="main">
<h2>Operations coverage summary: Tag: {{report_tag}} | Version: {{report_version}} | Time: {{ timestamp }}</h2>
<div class="legend">
<div>
<span class="table-primary border"></span><span>Collected statistic info</span>
</div>
<div>
<span class="table-secondary border">N/A</span><span>No Tests</span>
</div>
<div>
<span><b>Passrates are based on relative weights each subgraphs! You can check absolute value in `General passrate` row!</b></span>
</div>
<div>
<span><b>Status:</b></span>
<span class="green">P:85</span><span>Passed</span>
<span class="red">F:0</span><span>Failed</span>
<span class="grey">S:2</span><span>Skipped</span>
<span class="dark">C:0</span><span>Crashed</span>
<span class="grey-red">H:0</span><span>Hanged</span>
</div>
<div>
<span><b>Plugin operation implementation status:</b></span>
<div class="checkmark"></div><div>Implemented</div>
<div class="check"></div><div>Not implemented</div>
</div>
</div>
</div>
<!-- Filters block -->
<div class="filters">
<form id="filters">
<div class="form-group">
<label for="operationName"><b>Operation Name</b></label>
<input id="operationName" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="opsetNumber"><b>Opset Number</b></label>
<select id="opsetNumber" class="form-control"></select>
</div>
<div class="form-group">
<label for="devices"><b>Devices</b></label>
<select id="devices" class="form-control"></select>
</div>
<div class="form-group">
<label for="implementation"><b>Plugin Implementation</b></label>
<select id="implementation" class="form-control">
<option value="0">All</option>
<option value="i">Implemented</option>
<option value="ni">Not implemented</option>
<option value="ns">No status</option>
</select>
</div>
<div class="form-group col-5" style="padding-left:0">
<label for="status"><b>Status</b></label>
<select id="status" class="form-control" multiple>
<option value="100p">100% Passed</option>
<option value="100f">100% Failed</option>
<option value="p">Passed</option>
<option value="f">Failed</option>
<option value="s">Skipped</option>
<option value="c">Crashed</option>
<option value="h">Hanged</option>
<option value="ex">Existing tests</option>
<option value="na">No tests</option>
<option value="ns">No status</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Apply filters</button>
<button type="button" class="btn btn-secondary" id="reset">Reset filters</button>
</form>
</div>
{{api_info}}
<!-- Results -->
<table class="table table-hover table-bordered" id="report">
<thead>
<tr>
<th class="table-dark">Plugins</th>
<th class="table-dark">SW Plugins</th>
{% for device in devices %}
<th class="table-dark" style="text-align: center;">{{ device }}</th>
{% endfor %}
</tr>
</thead>
<tbody id="statistic">
<td class="table-primary" rowspan="{{ sw_plugins|length + 1 }}">General passrate (=passed_tests/all_tests):</td>
{% for sw_plugin in sw_plugins %}
<tr>
<td>{{sw_plugin}}</td>
{% for device in devices %}
{% if device in general_pass_rate[sw_plugin] %}
<td style="text-align: center;">
{{ general_pass_rate["ov_plugin"][sw_plugin][device]['passrate'] }}%
</td>
{% else %}
<td style="text-align: center;">NOT RUN</td>
{% endif %}
{% endfor %}
</tr>
{% block content%}
<h1 class="ml-3 mt-3">Conformance Highlights</h1>
{% if report_tag != "" or report_version != "" %}
<h3 class="ml-3 mt-3">Tag: {{report_tag}} | Version: {{report_version}}</h3>
{% endif %}
{% if current_commit != "" %}
<h3 class="ml-3 mt-3">Current state: {{current_commit}}</h3>
{% endif %}
{% if prev_commit != "" %}
<h3 class="ml-3 mt-3">Previous state: {{prev_commit}}</h3>
{% endif %}
{% if ops_info|length == 0 and api_info|length == 0 %}
<h3 style="text-align: center;" class="mt-10">Unfortunately report is empty. Data for analysis wasn't found.</h3>
{% else %}
{% for test_mode in expected_test_mode %}
<h3 class="ml-3" style="margin-top: 30px;">
{% if expected_test_mode|length > 1 %}
<span class="mr-3">&#9679</span>{{ test_mode }}
{% endif %}
</h3>
<table class="table table-hover table-bordered" style="margin-left: auto; margin-right: auto; width: 98%; font-size: 12px;">
<thead>
<tr>
<th class="diagonal"><span class="th-devices">Devices</span><span class="th-sw-plugin">Statistic</span></th>
{% for device in devices %}
<th colspan="2" class="table-dark" style="text-align: center; vertical-align: middle !important;">{{ device }}</th>
{% endfor %}
</tr>
</thead>
<tbody style="text-align: center;">
<tr>
<td class="table-primary" style="text-align: left; width: 20%;">Total ops pass (total pass)/(all ops amount):</td>
{% for device in devices %}
{% if device in ops_info[test_mode] %}
<td colspan="2" title="{{ops_info[test_mode][device]['title']}}">
<!-- 10(+3)/(205)(-10) -->
<span>{{ ops_info[test_mode][device]['totalPass'] }}</span>
{% if ops_info[test_mode][device]['diffTotalPass'] > 0 %}
(<span class="text-success font-weight-bold">+{{ ops_info[test_mode][device]['diffTotalPass'] }}</span>)
{% elif ops_info[test_mode][device]['diffTotalPass'] < 0 %}
(<span class="text-danger font-weight-bold">{{ ops_info[test_mode][device]['diffTotalPass'] }}</span>)
{% endif %}
/<span>{{ ops_info[test_mode][device]['totalAmount'] }}</span>
{% if ops_info[test_mode][device]['diffTotalAmount'] > 0 %}
(<span class="text-success font-weight-bold">+{{ ops_info[test_mode][device]['diffTotalAmount'] }}</span>)
{% elif ops_info[test_mode][device]['diffTotalAmount'] < 0 %}
(<span class="text-danger font-weight-bold">{{ ops_info[test_mode][device]['diffTotalAmount'] }}</span>)
{% endif %}
</td>
{% else %}
<td colspan="2" title="Opset conformanace wasn't run on {{device}}">
NOT RUN
</td>
{% endif %}
{% endfor %}
</tr>
<tr>
<td class="table-primary" style="text-align: left; width: 20%;">Passrate:</td>
{% for device in devices %}
{% if device in general_pass_rate[test_mode] %}
<td title="{{general_pass_rate[test_mode][device]['title']}}">
<span>Total:</span>
{{ general_pass_rate[test_mode][device]['current'] }}
{% if general_pass_rate[test_mode][device]['diff'] > 0 %}
(<span class="text-success font-weight-bold" >+{{ general_pass_rate[test_mode][device]['diff'] }}</span>)
{% elif general_pass_rate[test_mode][device]['diff'] < 0 %}
(<span class="text-danger font-weight-bold">{{ general_pass_rate[test_mode][device]['diff'] }}</span>)
{% endif %}
%
</td>
<td title="{{general_pass_rate[test_mode][device]['rel_title']}}">
<span>Rel:</span>
{{ general_pass_rate[test_mode][device]['rel_current'] }}
{% if general_pass_rate[test_mode][device]['rel_diff'] > 0 %}
(<span class="text-success font-weight-bold">+{{ general_pass_rate[test_mode][device]['rel_diff'] }}</span>)
{% elif general_pass_rate[test_mode][device]['rel_diff'] < 0 %}
(<span class="text-danger font-weight-bold">{{ general_pass_rate[test_mode][device]['rel_diff'] }}</span>)
{% endif %}
%
</td>
{% else %}
<td colspan="2" title="Opset conformanace wasn't run on {{device}}">NOT RUN</td>
{% endif %}
{% endfor %}
</tr>
</tbody>
</table>
{% endfor %}
{% if api_info.keys()|length > 0 %}
<h3 class="ml-3" style="margin-top: 30px;"><span class="mr-3">&#9679</span> API </h3>
<table class="table table-hover table-bordered" style="margin-left: auto; margin-right: auto; width: 98%; font-size: 12px;">
<thead>
<tr>
<th class="table-dark" style="text-align: left; vertical-align: middle !important;">Entity</th>
<th class="diagonal"><span class="th-devices">Devices</span><span class="th-sw-plugin">Plugins</span></th>
{% for device in devices %}
<th class="table-dark" colspan="2" style="text-align: center; vertical-align: middle !important;">{{ device }}</th>
{% endfor %}
</tr>
</thead>
<tbody style="text-align: center;">
{% for test_type in api_info %}
<td class="table-primary" style="text-align: left;" rowspan="{{ api_info[test_type].keys()|length + 1 }}" style="vertical-align: middle !important;">{{ test_type }}</td>
{% for sw_plugin in sw_plugins %}
<tr>
<td style="text-align: left;">{{sw_plugin}}</td>
{% for device in devices %}
{% if device in api_info[test_type][sw_plugin] %}
<td title="{{api_info[test_type][sw_plugin][device]['title']}}">
<span>Total:</span>
<span>{{ api_info[test_type][sw_plugin][device]['passrate'] }}</span>
{% if api_info[test_type][sw_plugin][device]['diff'] > 0 %}
(<span class="text-success font-weight-bold">+{{ api_info[test_type][sw_plugin][device]['diff'] }}</span>)
{% elif api_info[test_type][sw_plugin][device]['diff'] < 0 %}
(<span class="text-danger font-weight-bold">{{ api_info[test_type][sw_plugin][device]['diff'] }}</span>)
{% endif %}
%
</td>
<td title="{{api_info[test_type][sw_plugin][device]['rel_title']}}">
<span>Rel:</span>
<span>{{ api_info[test_type][sw_plugin][device]['rel_passrate'] }}</span>
{% if api_info[test_type][sw_plugin][device]['rel_diff'] > 0 %}
(<span class="text-success font-weight-bold">+{{ api_info[test_type][sw_plugin][device]['rel_diff'] }}</span>)
{% elif api_info[test_type][sw_plugin][device]['rel_diff'] < 0 %}
(<span class="text-danger font-weight-bold">{{ api_info[test_type][sw_plugin][device]['rel_diff'] }}</span>)
{% endif %}
%
</td>
{% else %}
<td colspan="2" style="text-align: center;" title="API conformanace wasn't run on {{device}} {{sw_plugin}}">NOT RUN</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
<td class="table-primary" rowspan="{{ sw_plugins|length + 1 }}">AVG passrate (=sum_pass_rates/covered_ops_num):</td>
{% for sw_plugin in sw_plugins %}
<tr>
<td>{{sw_plugin}}</td>
{% for device in devices %}
{% if device in general_pass_rate[sw_plugin] %}
<td style="text-align: center;">
{{ general_pass_rate["ov_plugin"][sw_plugin][device]['real_passrate'] }}%
</td>
{% else %}
<td style="text-align: center;">NOT RUN</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
<tbody id="data">
{% for test_type in api_info %}
<td class="table-primary" rowspan="{{ api_info[test_type].keys()|length + 1 }}">{{ test_type }}</td>
{% for sw_plugin in sw_plugins %}
<tr>
<td>{{sw_plugin}}</td>
{% for device in devices %}
{% if device in api_info[test_type][sw_plugin] %}
<td style="text-align: center;">
<span>Rel:</span>
{{ api_info[test_type][sw_plugin][device]['rel_passrate'] }}
{% if api_info[test_type][sw_plugin][device]['diff'] > 0 %}
(<span class="text-success font-weight-bold" title="Passrate have increased since last run">+{{ api_info[test_type][sw_plugin][device]['diff'] }}</span>)
{% elif api_info[test_type][sw_plugin][device]['diff'] < 0 %}
(<span class="text-danger font-weight-bold" title="Passrate have decreased since last run">{{ api_info[test_type][sw_plugin][device]['diff'] }}</span>)
{% endif %}
%
<span>Total:</span>
{{ api_info[test_type][sw_plugin][device]['passrate'] }}
{% if api_info[test_type][sw_plugin][device]['diff'] > 0 %}
(<span class="text-success font-weight-bold" title="Passrate have increased since last run">+{{ api_info[test_type][sw_plugin][device]['diff'] }}</span>)
{% elif api_info[test_type][sw_plugin][device]['diff'] < 0 %}
(<span class="text-danger font-weight-bold" title="Passrate have decreased since last run">{{ api_info[test_type][sw_plugin][device]['diff'] }}</span>)
{% endif %}
%
<div class="flex">
<div>
<span class="green" title="Passed">P:{{ api_info[test_type][sw_plugin][device]['passrate'] }}</span>
<span class="red" title="Failed">F:{{ api_info[test_type][sw_plugin][device]['passrate'] }}</span>
<span class="grey" title="Skipped">S:{{ api_info[test_type][sw_plugin][device]['passrate'] }}</span>
<span class="dark" title="Crashed">C:{{ api_info[test_type][sw_plugin][device]['passrate'] }}</span>
<span class="grey-red" title="Hanged">H:{{ api_info[test_type][sw_plugin][device]['passrate'] }}</span>
</div>
</div>
</td>
{% else %}
<td style="text-align: center;">NOT RUN</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
<div id="message" style="display:none">
There is no data related to selected filters. Please set new filters.
</div>
{% endif %}
{% endif %}
{% endblock %}
</body>
</html>

View File

@ -723,4 +723,5 @@ h2 {
.entity {
vertical-align: middle !important;
width: 20%;
}
}