修改报告逻辑,在新报告模板下载失败时使用老的报告模板

Signed-off-by: deveco_xdevice <liguangjie1@huawei.com>
This commit is contained in:
deveco_xdevice 2024-09-29 20:33:15 +08:00
parent 50302742dd
commit 988941a05d
6 changed files with 1667 additions and 64 deletions

View File

@ -15,6 +15,9 @@
-->
<user_config>
<environment>
<device type="usb-hdc" label="ohos">
<info ip="" port="" sn="" alias="" />
</device>
<device type="com" label="wifiiot">
<serial>
<com></com>
@ -63,5 +66,5 @@
<url></url>
</web_resource>>
</resource>
<loglevel>INFO</loglevel>
<loglevel>DEBUG</loglevel>
</user_config>

View File

@ -19,7 +19,6 @@
import json
import os
import re
import requests
import stat
import subprocess
import time
@ -318,6 +317,7 @@ class PushBase(ITestKit):
os.makedirs(save_path)
cli = None
try:
import requests
cli = requests.get(url, timeout=5, verify=False)
if cli.status_code == 200:
file_fd = os.open(save_file, os.O_CREAT | os.O_WRONLY, FilePermission.mode_644)
@ -355,6 +355,7 @@ class PushBase(ITestKit):
}
LOG.debug(f"query resource's params {params}")
try:
import requests
cli = requests.post(query_url, json=params, timeout=5, verify=False)
rsp_code = cli.status_code
rsp_body = cli.content.decode()

View File

@ -20,6 +20,7 @@ import sys
from urllib import request
from xdevice import Console
from xdevice import platform_logger
from xdevice import ReportConstant
from xdevice import VERSION
srcpath = os.path.dirname(os.path.dirname(__file__))
@ -38,58 +39,15 @@ Run failed due to missing the report template! Please follow the following instr
1.Download archived report template files
Download Link: https://gitee.com/openharmony-sig/compatibility/raw/master/test_suite/resource/xdevice/template.zip?lfs=1
2.Remove the template folder in the path '{resource_path}'
3.unzip the template.zip to the path '{resource_path}'
3.Unzip the template.zip to the path '{resource_path}'
'''
def check_report_template():
sources = [
"static/css/element-plus@2.3.4_index.css",
"static/element-plus@2.3.4_index.full.js",
"static/element-plus_icons-vue@2.0.10_index.iife.min.js",
"static/EventEmitter.js",
"static/vue@3.2.41_global.min.js",
]
resource_path = os.path.join(os.path.dirname(__file__), "_core", "resource")
template_path = os.path.join(resource_path, "template")
missing_files = []
for source in sources:
tmp_file = os.path.join(template_path, source)
if not os.path.exists(tmp_file):
missing_files.append(tmp_file)
if len(missing_files) > 0:
return False
return True
def download_template_resource():
LOG.info("There is no report template in target path. "
"Start download report template...")
sources = [
{
"file": "static/css/element-plus@2.3.4_index.css",
"url": "https://cdn.bootcdn.net/ajax/libs/element-plus/2.3.4/index.css"
},
{
"file": "static/element-plus@2.3.4_index.full.js",
"url": "https://cdn.bootcdn.net/ajax/libs/element-plus/2.3.4/index.full.js"
},
{
"file": "static/element-plus_icons-vue@2.0.10_index.iife.min.js",
"url": "https://cdn.bootcdn.net/ajax/libs/element-plus-icons-vue/2.0.10/index.iife.min.js"
},
{
"file": "static/EventEmitter.js",
"url": "https://cdn.bootcdn.net/ajax/libs/EventEmitter/5.2.8/EventEmitter.js"
},
{
"file": "static/vue@3.2.41_global.min.js",
"url": "https://cdn.bootcdn.net/ajax/libs/vue/3.2.41/vue.global.min.js"
}
]
resource_path = os.path.join(os.path.dirname(__file__), "_core", "resource")
template_path = os.path.join(resource_path, "template")
for source in sources:
for source in ReportConstant.new_template_sources:
file, url = source.get("file"), source.get("url")
to_path = os.path.join(template_path, file)
if os.path.exists(to_path):
@ -101,25 +59,23 @@ def download_template_resource():
f.write(response.read())
except Exception as e:
LOG.error(f"get report template resource error, {e}")
if not os.path.exists(to_path):
missing_files.append(to_path)
break
# check report template
if not check_report_template():
LOG.error("------" * 5)
LOG.error(notice_zh.format(resource_path=resource_path))
LOG.error(notice_en.format(resource_path=resource_path))
LOG.error("------" * 5)
return False
else:
return True
if len(missing_files) == 0:
return
LOG.warning("------" * 5)
LOG.warning(notice_zh.format(resource_path=resource_path))
LOG.warning(notice_en.format(resource_path=resource_path))
LOG.warning("------" * 5)
LOG.warning("Download report template failed, using the default report template.")
def main_process(command=None):
LOG.info(
"*************** xDevice Test Framework %s Starting ***************" %
VERSION)
if not check_report_template():
if not download_template_resource():
return
check_report_template()
if command:
args = str(command).split(" ")
args.insert(0, "xDevice")

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@ from _core.report.reporter_helper import DataHelper
from _core.report.reporter_helper import ExecInfo
from _core.report.reporter_helper import ReportConstant
from _core.report.repeater_helper import RepeatHelper
from xdevice import Variables
from _core.variables import Variables
from _core.context.center import Context
from _core.context.handler import get_case_result
from _core.context.upload import Uploader
@ -125,12 +125,12 @@ class ResultReporter(IReporter):
LOG.info("")
if self._check_params(report_path, **kwargs):
# generate vision reports
self._generate_test_report()
# generate data report
self._generate_data_report()
# generate vision reports
self._generate_test_report()
# generate task info record
self._generate_task_record()
@ -172,7 +172,19 @@ class ResultReporter(IReporter):
def _generate_test_report(self):
report_template = os.path.join(Variables.res_dir, "template")
missing_files = []
for source in ReportConstant.new_template_sources:
file = source.get("file")
to_path = os.path.join(report_template, file)
if not os.path.exists(to_path):
missing_files.append(to_path)
# 若新报告模板文件缺失,则使用旧报告模板生成测试报告
if len(missing_files) > 0:
self._generate_vision_reports()
return
copy_folder(report_template, self.report_path)
os.remove(os.path.join(self.report_path, "report.html"))
content = json.dumps(self._get_summary_data(), separators=(",", ":"))
data_js = os.path.join(self.report_path, "static", "data.js")
data_fd = os.open(data_js, os.O_CREAT | os.O_WRONLY, FilePermission.mode_644)
@ -456,6 +468,7 @@ class ResultReporter(IReporter):
if data_report.endswith(ReportConstant.summary_data_report):
continue
root = self.data_helper.parse_data_report(data_report)
self._parse_devices(root)
if module_name == ReportConstant.empty_name:
module_name = self._get_module_name(data_report, root)
total = int(root.get(ReportConstant.tests, 0))
@ -762,3 +775,93 @@ class ResultReporter(IReporter):
if modules_zero:
LOG.info("The total tests of %s module is 0", ",".join(
modules_zero))
# ******************** 使用旧报告模板的代码 BEGIN ********************
def _generate_vision_reports(self):
from _core.report.reporter_helper import VisionHelper
vision_helper = VisionHelper()
vision_helper.report_path = self.report_path
if not self._check_mode(ModeType.decc) and not \
self.summary_data_report_exist:
LOG.error("Summary data report not exists")
return
if check_pub_key_exist() or self._check_mode(ModeType.decc):
from xdevice import SuiteReporter
SuiteReporter.clear_report_result()
# parse data
if self.summary_data_str:
# only in decc mode and pub key, self.summary_data_str is not empty
summary_element_tree = self.data_helper.parse_data_report(
self.summary_data_str)
else:
summary_element_tree = self.data_helper.parse_data_report(
self.summary_data_path)
parsed_data = vision_helper.parse_element_data(
summary_element_tree, self.report_path, self.task_info)
self.parsed_data = parsed_data
self.exec_info, summary, _ = parsed_data
if self._check_mode(ModeType.decc):
return
LOG.info("Summary result: modules: %s, run modules: %s, total: "
"%s, passed: %s, failed: %s, blocked: %s, ignored: %s, "
"unavailable: %s", summary.modules, summary.run_modules,
summary.result.total, summary.result.passed,
summary.result.failed, summary.result.blocked,
summary.result.ignored, summary.result.unavailable)
LOG.info("Log path: %s", self.exec_info.log_path)
if summary.result.failed != 0 or summary.result.blocked != 0 or\
summary.result.unavailable != 0:
from xdevice import Scheduler
Scheduler.is_need_auto_retry = True
# generate summary vision report
report_generate_flag = self._generate_vision_report(
vision_helper, parsed_data, ReportConstant.summary_title,
ReportConstant.summary_vision_report)
# generate details vision report
if report_generate_flag and summary.result.total > 0:
self._generate_vision_report(
vision_helper, parsed_data, ReportConstant.details_title,
ReportConstant.details_vision_report)
# generate failures vision report
if summary.result.total != (
summary.result.passed + summary.result.ignored) or \
summary.result.unavailable > 0:
self._generate_vision_report(
vision_helper, parsed_data, ReportConstant.failures_title,
ReportConstant.failures_vision_report)
# generate passes vision report
if summary.result.passed != 0:
self._generate_vision_report(
vision_helper, parsed_data, ReportConstant.passes_title,
ReportConstant.passes_vision_report)
# generate ignores vision report
if summary.result.ignored != 0:
self._generate_vision_report(
vision_helper, parsed_data, ReportConstant.ignores_title,
ReportConstant.ignores_vision_report)
def _generate_vision_report(self, vision_helper, parsed_data, title, render_target):
# render data
report_context = vision_helper.render_data(
title, parsed_data,
render_target=render_target, devices=self.summary.get_devices())
# generate report
if report_context:
report_path = os.path.join(self.report_path, render_target)
vision_helper.generate_report(report_path, report_context)
return True
else:
LOG.error("Failed to generate %s", render_target)
return False
# ******************** 使用旧报告模板的代码 END ********************

View File

@ -0,0 +1,545 @@
<html version="1.0" lang="en">
<!-- Copyright (c) 2022 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><!--{title_name}--></title>
<style type="text/css">
body {
font-family: PingFangSC-Semibold, sans-serif;
font-size: 20px;
padding: 0;
margin: 0;
background-color: #F2F5F7;
}
div.logo {
background-image: url('data:image/jpeg;base64,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');
width: 80px;
height: 30px;
}
div.operate {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDE2IDEyIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPg0KICAgIDwhLS0gR2VuZXJhdG9yOiBTa2V0Y2ggNTMuMiAoNzI2NDMpIC0gaHR0cHM6Ly9za2V0Y2hhcHAuY29tIC0tPg0KICAgIDx0aXRsZT7lvaLnirYgY29weSAxNDwvdGl0bGU+DQogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+DQogICAgPGcgaWQ9Iumhtemdoi0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4NCiAgICAgICAgPGcgaWQ9IuS4u+mhtTIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDc3LjAwMDAwMCwgLTk3NC4wMDAwMDApIiBmaWxsPSIjMjkzMDQwIj4NCiAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDg1LDk4NiBDMTQ4Mi4zMzMzMyw5ODYgMTQ3OS42NjY2Nyw5ODQgMTQ3Nyw5ODAgQzE0NzkuNzIyOTEsOTc2IDE0ODIuMzg5NTgsOTc0IDE0ODUsOTc0IEMxNDg3LjYxMDQyLDk3NCAxNDkwLjI3NzA5LDk3NiAxNDkzLDk4MCBDMTQ5MC4zMzMzMyw5ODQgMTQ4Ny42NjY2Nyw5ODYgMTQ4NSw5ODYgWiBNMTQ4NSw5ODQgQzE0ODcuMjA5MTQsOTg0IDE0ODksOTgyLjIwOTEzOSAxNDg5LDk4MCBDMTQ4OSw5NzcuNzkwODYxIDE0ODcuMjA5MTQsOTc2IDE0ODUsOTc2IEMxNDgyLjc5MDg2LDk3NiAxNDgxLDk3Ny43OTA4NjEgMTQ4MSw5ODAgQzE0ODEsOTgyLjIwOTEzOSAxNDgyLjc5MDg2LDk4NCAxNDg1LDk4NCBaIE0xNDg1LDk4MiBDMTQ4My44OTU0Myw5ODIgMTQ4Myw5ODEuMTA0NTY5IDE0ODMsOTgwIEMxNDgzLDk3OC44OTU0MzEgMTQ4My44OTU0Myw5NzggMTQ4NSw5NzggQzE0ODYuMTA0NTcsOTc4IDE0ODcsOTc4Ljg5NTQzMSAxNDg3LDk4MCBDMTQ4Nyw5ODEuMTA0NTY5IDE0ODYuMTA0NTcsOTgyIDE0ODUsOTgyIFoiIGlkPSLlvaLnirYtY29weS0xNCI+PC9wYXRoPg0KICAgICAgICA8L2c+DQogICAgPC9nPg0KPC9zdmc+');
width: 16px;
height: 12px;
}
span.title {
float: left;
}
span.return {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgd2lkdGg9IjEycHgiIGhlaWdodD0iMTRweCIgdmlld0JveD0iMCAwIDEyIDE0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPg0KICAgIDwhLS0gR2VuZXJhdG9yOiBTa2V0Y2ggNTMuMiAoNzI2NDMpIC0gaHR0cHM6Ly9za2V0Y2hhcHAuY29tIC0tPg0KICAgIDx0aXRsZT7liIbnu4Q8L3RpdGxlPg0KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPg0KICAgIDxnIGlkPSLpobXpnaItMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+DQogICAgICAgIDxnIGlkPSLkuLvpobUyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNDg4LjAwMDAwMCwgLTEwMzIuMDAwMDAwKSIgZmlsbC1ydWxlPSJub256ZXJvIj4NCiAgICAgICAgICAgIDxnIGlkPSLliIbnu4QiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4Ni4wMDAwMDAsIDEwMzEuMDAwMDAwKSI+DQogICAgICAgICAgICAgICAgPHJlY3QgaWQ9IuefqeW9oiIgeD0iMCIgeT0iMCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48L3JlY3Q+DQogICAgICAgICAgICAgICAgPHBhdGggZD0iTTYsNSBMNiw3IEwyLDQgTDYsMSBMNiwzIEw4LDMgQzExLjMxMzcwODUsMyAxNCw1LjY4NjI5MTUgMTQsOSBDMTQsMTIuMzEzNzA4NSAxMS4zMTM3MDg1LDE1IDgsMTUgTDQsMTUgTDQsMTMgTDYsMTMgTDgsMTMgQzEwLjIwOTEzOSwxMyAxMiwxMS4yMDkxMzkgMTIsOSBDMTIsNi43OTA4NjEgMTAuMjA5MTM5LDUgOCw1IEw2LDUgWiIgaWQ9IuWQiOW5tuW9oueKtiIgZmlsbD0iIzI5MzA0MCI+PC9wYXRoPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgPC9nPg0KPC9zdmc+');
width: 12px;
height: 14px;
float: left;
}
table.logo {
width: 1920px;
height: 40px;
background-color: #FFFFFF;
margin-left: auto;
margin-right: auto;
}
table.logo th {
text-align: left;
padding: 9px 0 1px 24px;
}
div.layout {
width: 1160px;
background-color: #FFFFFF;
margin-top: 10px;
margin-right: auto;
margin-left: auto;
padding: 30px 20px 30px 20px;
}
table.exec-info {
width: 100%;
background-color: #FFFFFF;
padding: 0 0 5px 0;
}
table.exec-info th {
font-family: PingFangSC-Semibold, sans-serif;
color: #293040;
font-size: 20px;
height: 26px;
text-align: left;
padding: 0 0 20px 0;
word-break: break-all;
}
table.exec-info td.normal {
color: #5E6678;
font-size: 14px;
height: 20px;
text-align: left;
padding: 0 0 15px 0;
word-break: break-all;
}
table.exec-info td.first {
font-family: PingFangSC-Regular, sans-serif;
width: 156px;
}
table.exec-info td.second {
font-family: PingFangSC-Medium, sans-serif;
width: 424px;
}
table.exec-info td.third {
font-family: PingFangSC-Regular, sans-serif;
width: 152px;
}
table.exec-info td.fourth {
font-family: PingFangSC-Medium, sans-serif;
width: 428px;
}
table.summary {
width: 1160px;
height: 89px;
margin-left: auto;
margin-right: auto;
background-color: #F9FAFC;
}
.color-normal {
color: #293040;
}
.color-passed {
color: #3DCCA6;
}
.color-failed {
color: #F95F5B;
}
.color-blocked {
color: #FFB400;
}
.color-ignored {
color: #8C8C8C;
}
.color-unavailable {
color: #8C8C8C;
}
table.summary th.normal {
font-family: PingFangSC-Semibold, sans-serif;
font-size: 24px;
height: 24px;
width: 110px;
text-align: center;
word-break: break-all;
}
table.summary td.normal {
font-family: PingFangSC-Regular, sans-serif;
color: #5E6678;
font-size: 14px;
height: 20px;
width: 110px;
text-align: center;
}
table.summary th.modules {
padding: 20px 35px 0 34px;
}
table.summary th.run-modules, table.summary th.total-tests, table.summary th.passed {
padding: 20px 35px 0 0;
}
table.summary th.failed, table.summary th.blocked, table.summary th.ignored {
padding: 20px 35px 0 0;
}
table.summary th.unavailable {
padding: 20px 34px 0 0;
}
table.summary td.modules {
padding: 5px 35px 20px 34px;
}
table.summary td.run-modules, table.summary td.total-tests, table.summary td.passed {
padding: 5px 35px 20px 0;
}
table.summary td.failed, table.summary td.blocked, table.summary td.ignored {
padding: 5px 35px 20px 0;
}
table.summary td.unavailable {
padding: 5px 34px 20px 0;
}
table.devices {
width: 1160px;
margin-left: auto;
margin-right: auto;
margin-top: 30px;
table-layout: fixed;
}
table.devices th.normal {
font-family: Roboto-Medium, sans-serif;
color: #293040;
font-size: 12px;
height: 36px;
border-bottom: 1px #E8F0FD solid;
text-align: left;
}
table.devices td.normal {
font-family: Roboto-Regular, sans-serif;
color: #293040;
font-size: 14px;
height: 36px;
text-align: left;
}
table.devices th.device-index {
width: 3%;
}
table.devices th.device-sn,
table.devices th.device-model,
table.devices th.device-type,
table.devices th.device-platform,
table.devices th.device-version,
table.devices td.device-sn,
table.devices td.device-model,
table.devices td.device-type,
table.devices td.device-platform,
table.devices td.device-version {
width: 15%;
word-break: break-all;
}
.ellipsis {
overflow: hidden;
width: 180px;
text-overflow: ellipsis;
white-space: nowrap;
}
table.suites {
width: 1160px;
margin-left: auto;
margin-right: auto;
margin-top: 30px;
}
table.suites th.title {
font-family: PingFangSC-Semibold, sans-serif;
color: #293040;
font-size: 16px;
height: 22px;
text-align: left;
}
table.suites th.normal {
font-family: Roboto-Medium, sans-serif;
color: #293040;
font-size: 12px;
height: 36px;
border-bottom: 1px #E8F0FD solid;
text-align: left;
}
table.suites th.module {
width: 210px;
}
table.suites th.total {
width: 110px;
}
table.suites th.passed, table.suites th.failed, table.suites th.blocked {
width: 90px;
}
table.suites th.ignored, table.suites th.time {
width: 90px;
}
table.suites th.operate {
width: 58px;
}
table.suites tr.background-color{
background-color: #F9FAFC;
}
table.suites td.normal {
font-family: Roboto-Regular, sans-serif;
color: #293040;
font-size: 14px;
height: 36px;
text-align: left;
word-break: break-all;
}
table.suites td.module {
width: 210px;
}
table.suites td.total {
width: 110px;
}
table.suites td.passed, table.suites td.failed, table.suites td.blocked {
width: 90px;
}
table.suites td.ignored, table.suites td.time {
width: 90px;
}
table.suites td.operate {
width: 58px;
}
table.test-suite, table.failure-test {
width: 1160px;
margin-left: auto;
margin-right: auto;
margin-top: 30px;
}
table.test-suite th.title, table.failure-test th.title {
font-family: PingFangSC-Semibold, sans-serif;
color: #293040;
font-size: 14px;
height: 22px;
text-align: left;
overflow: hidden;
}
table.test-suite th.normal, table.failure-test th.normal {
font-family: Roboto-Medium, sans-serif;
color: #293040;
font-size: 12px;
height: 36px;
border-bottom: 1px #E8F0FD solid;
text-align: left;
}
table.test-suite th.module {
width: 210px;
}
table.test-suite th.test {
width: 427px;
}
table.test-suite th.time {
width: 90px;
}
table.test-suite th.status {
width: 11px;
}
table.test-suite th.result {
width: 90px;
}
.circle-normal {
border-radius: 50%;
width: 6px;
height: 6px;
margin: 0;
padding: 0;
}
.circle-white {
background-color: #FFFFFF;
}
.circle-passed {
background-color: #3DCCA6;
}
.circle-failed {
background-color: #F95F5B;
}
.circle-blocked {
background-color: #FFB400;
}
.circle-ignored {
background-color: #8C8C8C;
}
.circle-unavailable {
background-color: #8C8C8C;
}
table.test-suite tr.background-color, table.failure-test tr.background-color {
background-color: #F9FAFC;
}
table.test-suite td.normal, table.failure-test td.normal {
font-family: Roboto-Regular, sans-serif;
color: #293040;
font-size: 14px;
height: 36px;
text-align: left;
word-break: break-all;
}
table.test-suite td.module {
width: 210px;
}
table.test-suite td.test {
width: 427px;
}
table.test-suite td.time {
width: 90px;
}
table.test-suite td.status {
width: 11px;
}
table.test-suite td.result {
width: 90px;
}
table.failure-test th.test {
width: 569px;
}
table.failure-test th.status {
width: 11px;
}
table.failure-test th.result {
width: 80px;
}
table.failure-test th.details {
width: 480px;
}
table.failure-test td.test {
vertical-align: top;
width: 569px;
}
table.failure-test td.status {
vertical-align: top;
width: 11px;
padding: 8px;
}
table.failure-test td.result {
vertical-align: top;
width: 80px;
}
table.failure-test td.details {
vertical-align: top;
width: 480px;
}
div.hidden {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 424px;
}
.el-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
z-index: 9999;
}
.el-button {
margin-right: 10px;
}
.el-dialog__header {
background-color: #f5f7fa;
padding: 10px;
height: 30px;
}
.el-dialog__body {
background-color: #fff;
padding: 10px;
max-height: 280px;
overflow-y: auto;
}
.el-dialog__close {
font-size: 16px;
float: right;
}
table.el-dialog__table {
width: 100%;
background-color: #FFFFFF;
font-family: PingFangSC-Regular, sans-serif;
/* font-family: PingFangSC-Medium, sans-serif; */
}
table.el-dialog__table td {
color: #5E6678;
font-size: 14px;
height: 30px;
text-align: left;
word-break: break-all;
}
table.el-dialog__table td.key {
width: 20%;
font-weight: bold;
}
table.el-dialog__table td.value {
width: 30%;
}
</style>
</head>
<body>
<div class="layout">
<table class="exec-info" id="summary">
<tr>
<th colspan="4">Test Summary</th>
</tr>
<tr>
<td class="normal first">Platform:</td>
<td class="normal second"><!--{exec_info.platform}--></td>
<td class="normal third">Test Type:</td>
<td class="normal fourth"><!--{exec_info.test_type}--></td>
</tr>
<tr>
<td class="normal first">Device Name:</td>
<td class="normal second"><!--{exec_info.device_name}--></td>
<td class="normal third">Host Info:</td>
<td class="normal fourth"><!--{exec_info.host_info}--></td>
</tr>
<tr>
<td class="normal first">Test Start/ End Time:</td>
<td class="normal second"><!--{exec_info.test_time}--></td>
<td class="normal third">Execution Time:</td>
<td class="normal fourth"><!--{exec_info.execute_time}--></td>
</tr>
<tr>
<td class="normal first">Task Logs:</td>
<td class="normal second" colspan="3"><!--{exec_info.task_log}--></td>
</tr>
</table>
<table class="summary">
<tr>
<th class="normal modules color-normal"><!--{summary.modules}--></th>
<th class="normal run-modules color-passed"><!--{summary.run_modules}--></th>
<th class="normal total-tests color-normal"><!--{summary.total}--></th>
<th class="normal passed color-passed"><!--{summary.passed}--></th>
<th class="normal failed <!--{color_type.failed}-->"><!--{summary.failed}--></th>
<th class="normal blocked <!--{color_type.blocked}-->"><!--{summary.blocked}--></th>
<th class="normal ignored <!--{color_type.ignored}-->"><!--{summary.ignored}--></th>
<th class="normal unavailable <!--{color_type.unavailable}-->"><!--{summary.unavailable}--></th>
</tr>
<tr>
<td class="normal modules">Modules</td>
<td class="normal run-modules">Run Modules</td>
<td class="normal total-tests">Total Tests</td>
<td class="normal passed">Passed</td>
<td class="normal failed">Failed</td>
<td class="normal blocked">Blocked</td>
<td class="normal ignored">Ignored</td>
<td class="normal unavailable">Unavailable</td>
</tr>
</table>
<!--{devices.context}-->
<!--{devices.dialogs}-->
<h4>Test Details</h4>
<!--{suites.context}-->
<!--{cases.context}-->
<!--{failures.context}-->
</div>
<script>
function showDialog(dialog_id) {
const dialog = document.getElementById(dialog_id);
dialog.style.display = 'block';
}
function hideDialog() {
const dialogs = document.getElementsByClassName('el-dialog');
for (let i = 0; i < dialogs.length; i++) {
dialogs[i].style.display = 'none';
}
}
</script>
</body>
</html>