!220 修复报告中测试用例时间计算错误的bug

Merge pull request !220 from liguangjie/master
This commit is contained in:
openharmony_ci 2023-04-20 13:01:19 +00:00 committed by Gitee
commit 06376fb2bd
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 129 additions and 91 deletions

View File

@ -405,6 +405,8 @@ class OHJSUnitTestDriver(IDriver):
json_config.get_driver(), False) json_config.get_driver(), False)
if testcase_timeout: if testcase_timeout:
self.runner.add_arg("timeout", int(testcase_timeout)) self.runner.add_arg("timeout", int(testcase_timeout))
self.runner.compile_mode = get_config_value(
'compile-mode', json_config.get_driver(), False)
def _do_test_run(self, listener): def _do_test_run(self, listener):
test_to_run = self._collect_test_to_run() test_to_run = self._collect_test_to_run()
@ -561,6 +563,7 @@ class OHJSUnitTestRunner:
self.expect_tests_dict = dict() self.expect_tests_dict = dict()
self.finished_observer = None self.finished_observer = None
self.retry_times = 1 self.retry_times = 1
self.compile_mode = ""
def dry_run(self): def dry_run(self):
parsers = get_plugin(Plugin.PARSER, CommonParserType.oh_jsunit_list) parsers = get_plugin(Plugin.PARSER, CommonParserType.oh_jsunit_list)
@ -628,34 +631,40 @@ class OHJSUnitTestRunner:
if self.config.package_name: if self.config.package_name:
# aa test -p ${packageName} -b ${bundleName}-s # aa test -p ${packageName} -b ${bundleName}-s
# unittest OpenHarmonyTestRunner # unittest OpenHarmonyTestRunner
command = "aa test -p %s -b %s -s unittest OpenHarmonyTestRunner" \ command = "aa test -p {} -b {} -s unittest OpenHarmonyTestRunner" \
" %s" % (self.config.package_name, " {}".format(self.config.package_name,
self.config.bundle_name, self.config.bundle_name,
self.get_args_command()) self.get_args_command())
elif self.config.module_name: elif self.config.module_name:
# aa test -m ${moduleName} -b ${bundleName} # aa test -m ${moduleName} -b ${bundleName}
# -s unittest OpenHarmonyTestRunner # -s unittest OpenHarmonyTestRunner
command = "aa test -m %s -b %s -s unittest OpenHarmonyTestRunner" \ command = "aa test -m {} -b {} -s unittest {} {}".format(
" %s" % (self.config.module_name, self.config.module_name, self.config.bundle_name,
self.config.bundle_name, self.get_oh_test_runner_path(), self.get_args_command())
self.get_args_command())
return command return command
def _get_dry_run_command(self): def _get_dry_run_command(self):
command = "" command = ""
if self.config.package_name: if self.config.package_name:
command = "aa test -p %s -b %s -s unittest OpenHarmonyTestRunner" \ command = "aa test -p {} -b {} -s unittest OpenHarmonyTestRunner" \
" %s -s dryRun true" % (self.config.package_name, " {} -s dryRun true".format(self.config.package_name,
self.config.bundle_name, self.config.bundle_name,
self.get_args_command()) self.get_args_command())
elif self.config.module_name: elif self.config.module_name:
command = "aa test -m %s -b %s -s unittest OpenHarmonyTestRunner" \ command = "aa test -m {} -b {} -s unittest {}" \
" %s -s dryRun true" % (self.config.module_name, " {} -s dryRun true".format(self.config.module_name,
self.config.bundle_name, self.config.bundle_name,
self.get_args_command()) self.get_oh_test_runner_path(),
self.get_args_command())
return command return command
def get_oh_test_runner_path(self):
if self.compile_mode == "esmodule":
return "/ets/testrunner/OpenHarmonyTestRunner"
else:
return "OpenHarmonyTestRunner"
@Plugin(type=Plugin.DRIVER, id=DeviceTestType.oh_rust_test) @Plugin(type=Plugin.DRIVER, id=DeviceTestType.oh_rust_test)
class OHRustTestDriver(IDriver): class OHRustTestDriver(IDriver):

View File

@ -215,7 +215,10 @@ class Device(IDevice):
return False return False
LOG.debug("Wait device %s to recover" % self.device_sn) LOG.debug("Wait device %s to recover" % self.device_sn)
return self.device_state_monitor.wait_for_device_available() result = self.device_state_monitor.wait_for_device_available()
if result:
self.device_log_collector.restart_catch_device_log()
return result
def get_device_type(self): def get_device_type(self):
self.label = self.model_dict.get("default", None) self.label = self.model_dict.get("default", None)
@ -496,7 +499,9 @@ class Device(IDevice):
self.log.debug('start uitest, {}'.format(result)) self.log.debug('start uitest, {}'.format(result))
def start_harmony_rpc(self, port=8080, re_install_rpc=False): def start_harmony_rpc(self, port=8080, re_install_rpc=False):
if hasattr(sys, ConfigConst.env_pool_cache) and getattr(sys, ConfigConst.env_pool_cache, False) and self.is_harmony_rpc_running(): if hasattr(sys, ConfigConst.env_pool_cache) \
and getattr(sys, ConfigConst.env_pool_cache, False) \
and self.is_harmony_rpc_running():
self.log.debug('harmony rpc is running') self.log.debug('harmony rpc is running')
return return
from devicetest.core.error_message import ErrorMessage from devicetest.core.error_message import ErrorMessage
@ -768,7 +773,7 @@ class DeviceLogCollector:
# 清空日志 # 清空日志
cmd = "hilog -r" cmd = "hilog -r"
out = self.device.execute_shell_command(cmd) out = self.device.execute_shell_command(cmd)
cmd = "rm -rf /data/log/hilog/*" cmd = "rm -rf /data/log/hilog/*.gz"
out = self.device.execute_shell_command(cmd) out = self.device.execute_shell_command(cmd)
# 开始日志任务 设置落盘文件个数最大值1000, 单个文件20M链接https://gitee.com/openharmony/hiviewdfx_hilog # 开始日志任务 设置落盘文件个数最大值1000, 单个文件20M链接https://gitee.com/openharmony/hiviewdfx_hilog
cmd = "hilog -w start -l {} -n 1000".format(log_size) cmd = "hilog -w start -l {} -n 1000".format(log_size)

View File

@ -124,6 +124,7 @@ class DeviceLite(IDevice):
self.device_kernel = "" self.device_kernel = ""
self.device = None self.device = None
self.ifconfig = None self.ifconfig = None
self.device_id = None
self.extend_value = {} self.extend_value = {}
self.device_lock = threading.RLock() self.device_lock = threading.RLock()

View File

@ -189,7 +189,9 @@ class LiteHelper:
while time.time() - start_time < timeout: while time.time() - start_time < timeout:
if not Scheduler.is_execute: if not Scheduler.is_execute:
raise ExecuteTerminate("Execute terminate", error_no="00300") raise ExecuteTerminate("Execute terminate", error_no="00300")
data = com.readline().decode('gbk', errors='ignore') if com.in_waiting == 0:
continue
data = com.read(com.in_waiting).decode('gbk', errors='ignore')
data = PATTERN.sub('', data).replace("\r", "") data = PATTERN.sub('', data).replace("\r", "")
result = "{}{}".format(result, data) result = "{}{}".format(result, data)
if receiver and data: if receiver and data:

View File

@ -33,6 +33,7 @@ from xdevice import TestDescription
from xdevice import ResultCode from xdevice import ResultCode
from xdevice import CommonParserType from xdevice import CommonParserType
from xdevice import get_cst_time from xdevice import get_cst_time
from xdevice import get_delta_time_ms
__all__ = ["CppTestParser", "CppTestListParser", "JunitParser", "JSUnitParser", __all__ = ["CppTestParser", "CppTestListParser", "JunitParser", "JSUnitParser",
"OHKernelTestParser", "OHJSUnitTestParser", "OHKernelTestParser", "OHJSUnitTestParser",
@ -83,6 +84,8 @@ class CppTestParser(IParser):
self.product_info = {} self.product_info = {}
self.is_params = False self.is_params = False
self.result_data = "" self.result_data = ""
self.start_time = get_cst_time()
self.suite_start_time = get_cst_time()
def get_suite_name(self): def get_suite_name(self):
return self.suite_name return self.suite_name
@ -199,6 +202,7 @@ class CppTestParser(IParser):
test_result = self.state_machine.test(reset=True) test_result = self.state_machine.test(reset=True)
test_result.test_class = test_class test_result.test_class = test_class
test_result.test_name = test_name test_result.test_name = test_name
self.start_time = get_cst_time()
for listener in self.get_listeners(): for listener in self.get_listeners():
test_result = copy.copy(test_result) test_result = copy.copy(test_result)
listener.__started__(LifeCycle.TestCase, test_result) listener.__started__(LifeCycle.TestCase, test_result)
@ -218,7 +222,9 @@ class CppTestParser(IParser):
test_class, test_name, run_time = self.parse_test_description( test_class, test_name, run_time = self.parse_test_description(
message) message)
test_result = self.state_machine.test() test_result = self.state_machine.test()
test_result.run_time = int(run_time) test_result.run_time = get_delta_time_ms(self.start_time)
if test_result.run_time == 0 or test_result.run_time < run_time:
test_result.run_time = run_time
test_result.code = test_status.value test_result.code = test_status.value
test_result.current = self.state_machine.running_test_index + 1 test_result.current = self.state_machine.running_test_index + 1
if not test_result.is_running(): if not test_result.is_running():
@ -277,6 +283,7 @@ class CppTestParser(IParser):
test_suite = self.state_machine.suite() test_suite = self.state_machine.suite()
test_suite.suite_name = matcher.group(2) test_suite.suite_name = matcher.group(2)
test_suite.test_num = expected_test_num test_suite.test_num = expected_test_num
self.suite_start_time = get_cst_time()
for listener in self.get_listeners(): for listener in self.get_listeners():
suite_report = copy.copy(test_suite) suite_report = copy.copy(test_suite)
listener.__started__(LifeCycle.TestSuite, suite_report) listener.__started__(LifeCycle.TestSuite, suite_report)
@ -284,8 +291,9 @@ class CppTestParser(IParser):
def handle_suite_ended_tag(self, message): def handle_suite_ended_tag(self, message):
self.state_machine.running_test_index = 0 self.state_machine.running_test_index = 0
suite_result = self.state_machine.suite() suite_result = self.state_machine.suite()
suite_result.run_time = get_delta_time_ms(self.suite_start_time)
matcher = re.match(r'.*\((\d+) ms total\)', message) matcher = re.match(r'.*\((\d+) ms total\)', message)
if matcher: if matcher and suite_result.run_time == 0:
suite_result.run_time = int(matcher.group(1)) suite_result.run_time = int(matcher.group(1))
suite_result.is_completed = True suite_result.is_completed = True
for listener in self.get_listeners(): for listener in self.get_listeners():
@ -672,7 +680,7 @@ class JSUnitParser(IParser):
def parse_test_description(self, message): def parse_test_description(self, message):
pattern = r".*\[(pass|fail|error)\]" pattern = r".*\[(pass|fail|error)\]"
year = time.strftime("%Y") year = time.strftime("%Y")
match_list = ["app Log:", "JSApp:", "JsApp:"] match_list = ["app Log:", "JSApp:", "JsApp:", "JSAPP:"]
filter_message = "" filter_message = ""
for keyword in match_list: for keyword in match_list:
if keyword in message: if keyword in message:
@ -1039,6 +1047,7 @@ class OHJSUnitItemConstants(Enum):
NUM_TESTS = "numtests" NUM_TESTS = "numtests"
STACK = "stack" STACK = "stack"
SUITE_CONSUMING = "suiteconsuming" SUITE_CONSUMING = "suiteconsuming"
CONSUMING = "consuming"
APP_DIED = "App died" APP_DIED = "App died"
@ -1052,6 +1061,7 @@ class OHJSUnitTestParser(IParser):
self.current_key = None self.current_key = None
self.current_value = None self.current_value = None
self.start_time = get_cst_time() self.start_time = get_cst_time()
self.suite_start_time = get_cst_time()
self.test_time = 0 self.test_time = 0
self.test_run_finished = False self.test_run_finished = False
self.cur_sum = -1 self.cur_sum = -1
@ -1106,6 +1116,7 @@ class OHJSUnitTestParser(IParser):
self.current_key = None self.current_key = None
self.current_value = None self.current_value = None
self.state_machine.running_test_index = 0 self.state_machine.running_test_index = 0
self.suite_start_time = get_cst_time()
for listener in self.get_listeners(): for listener in self.get_listeners():
suite = copy.copy(current_suite) suite = copy.copy(current_suite)
listener.__started__(LifeCycle.TestSuite, suite) listener.__started__(LifeCycle.TestSuite, suite)
@ -1114,6 +1125,9 @@ class OHJSUnitTestParser(IParser):
if self.current_key == OHJSUnitItemConstants.SUITE_CONSUMING.value: if self.current_key == OHJSUnitItemConstants.SUITE_CONSUMING.value:
self.test_time = int(self.current_value) self.test_time = int(self.current_value)
self.handle_suite_end() self.handle_suite_end()
elif self.current_key == OHJSUnitItemConstants.CONSUMING.value:
self.test_time = int(self.current_value)
self.handle_case_end()
else: else:
self.submit_current_key_value() self.submit_current_key_value()
self.parse_key(line, len(OHJSUnitPrefixes.STATUS.value)) self.parse_key(line, len(OHJSUnitPrefixes.STATUS.value))
@ -1147,7 +1161,6 @@ class OHJSUnitTestParser(IParser):
if self.check_legality(test_info.test_class) and \ if self.check_legality(test_info.test_class) and \
self.check_legality(test_info.test_name): self.check_legality(test_info.test_name):
self.report_result(test_info) self.report_result(test_info)
self.clear_current_test_info()
def clear_current_test_info(self): def clear_current_test_info(self):
self.state_machine.current_test = None self.state_machine.current_test = None
@ -1165,44 +1178,18 @@ class OHJSUnitTestParser(IParser):
if test_info.code == StatusCodes.FAILURE.value: if test_info.code == StatusCodes.FAILURE.value:
self.state_machine.running_test_index += 1 self.state_machine.running_test_index += 1
test_info.current = self.state_machine.running_test_index test_info.current = self.state_machine.running_test_index
end_time = get_cst_time() test_info.code = ResultCode.FAILED.value
run_time = (end_time - self.start_time).total_seconds() test_info.run_time = get_delta_time_ms(self.start_time)
test_info.run_time = int(run_time * 1000)
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = ResultCode.FAILED.value
listener.__ended__(LifeCycle.TestCase, result)
if listener.__class__.__name__ == "ReportListener" \
and self.runner.retry_times > 1:
index = list(listener.tests.keys())[-1]
listener.tests.pop(index)
test_info.is_completed = True
elif test_info.code == StatusCodes.ERROR.value: elif test_info.code == StatusCodes.ERROR.value:
self.state_machine.running_test_index += 1 self.state_machine.running_test_index += 1
test_info.current = self.state_machine.running_test_index test_info.current = self.state_machine.running_test_index
end_time = get_cst_time() test_info.code = ResultCode.FAILED.value
run_time = (end_time - self.start_time).total_seconds() test_info.run_time = get_delta_time_ms(self.start_time)
test_info.run_time = int(run_time * 1000)
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = ResultCode.FAILED.value
listener.__ended__(LifeCycle.TestCase, result)
if listener.__class__.__name__ == "ReportListener" \
and self.runner.retry_times > 1:
index = list(listener.tests.keys())[-1]
listener.tests.pop(index)
test_info.is_completed = True
elif test_info.code == StatusCodes.SUCCESS.value: elif test_info.code == StatusCodes.SUCCESS.value:
self.state_machine.running_test_index += 1 self.state_machine.running_test_index += 1
test_info.current = self.state_machine.running_test_index test_info.current = self.state_machine.running_test_index
end_time = get_cst_time() test_info.code = ResultCode.PASSED.value
run_time = (end_time - self.start_time).total_seconds() test_info.run_time = get_delta_time_ms(self.start_time)
test_info.run_time = int(run_time * 1000)
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = ResultCode.PASSED.value
listener.__ended__(LifeCycle.TestCase, result)
test_info.is_completed = True
@classmethod @classmethod
def output_stack_trace(cls, test_info): def output_stack_trace(cls, test_info):
@ -1227,9 +1214,26 @@ class OHJSUnitTestParser(IParser):
LOG.debug(self.result_data) LOG.debug(self.result_data)
self.result_data = "" self.result_data = ""
def handle_case_end(self):
test_info = self.state_machine.test()
if test_info.run_time == 0 or test_info.run_time < self.test_time:
test_info.run_time = self.test_time
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = test_info.code
listener.__ended__(LifeCycle.TestCase, result)
if listener.__class__.__name__ == "ReportListener" \
and self.runner.retry_times > 1:
index = list(listener.tests.keys())[-1]
listener.tests.pop(index)
test_info.is_completed = True
self.clear_current_test_info()
def handle_suite_end(self): def handle_suite_end(self):
suite_result = self.state_machine.suite() suite_result = self.state_machine.suite()
suite_result.run_time = self.test_time suite_result.run_time = get_delta_time_ms(self.suite_start_time)
if suite_result.run_time == 0:
suite_result.run_time = self.test_time
suite_result.is_completed = True suite_result.is_completed = True
for listener in self.get_listeners(): for listener in self.get_listeners():
suite = copy.copy(suite_result) suite = copy.copy(suite_result)
@ -1264,7 +1268,7 @@ class OHJSUnitTestParser(IParser):
for suite in report_listener.suites.values(): for suite in report_listener.suites.values():
test_des_list = self.runner.expect_tests_dict.get( test_des_list = self.runner.expect_tests_dict.get(
suite.suite_name, []) suite.suite_name, [])
pos = self.runner.suite_recorder.get(suite.suite_name)[0] pos = self.runner.suite_recorder.get(suite.suite_name)[0]
if len(test_des_list) == len(report_listener.result[pos][1]): if len(test_des_list) == len(report_listener.result[pos][1]):
continue continue
interval = len(test_des_list) - len(report_listener.result[pos][1]) interval = len(test_des_list) - len(report_listener.result[pos][1])

View File

@ -104,6 +104,7 @@ from _core.utils import modify_props
from _core.utils import get_shell_handler from _core.utils import get_shell_handler
from _core.utils import get_decode from _core.utils import get_decode
from _core.utils import get_cst_time from _core.utils import get_cst_time
from _core.utils import get_delta_time_ms
from _core.utils import get_device_proc_pid from _core.utils import get_device_proc_pid
from _core.utils import start_standing_subprocess from _core.utils import start_standing_subprocess
from _core.utils import stop_standing_subprocess from _core.utils import stop_standing_subprocess
@ -238,6 +239,7 @@ __all__ = [
"get_shell_handler", "get_shell_handler",
"get_decode", "get_decode",
"get_cst_time", "get_cst_time",
"get_delta_time_ms",
"get_device_proc_pid", "get_device_proc_pid",
"start_standing_subprocess", "start_standing_subprocess",
"stop_standing_subprocess", "stop_standing_subprocess",

View File

@ -20,6 +20,7 @@ import os
import time import time
import datetime import datetime
import sys import sys
import tempfile
from abc import abstractmethod from abc import abstractmethod
from abc import ABCMeta from abc import ABCMeta
@ -354,8 +355,7 @@ class DeviceSelector(Selector):
class Cache: class Cache:
def __init__(self): def __init__(self):
from xdevice import Variables self.cache_file = os.path.join(tempfile.gettempdir(), "cache.dat")
self.cache_file = os.path.join(Variables.res_dir, "cache.dat")
self.expire_time = 1 # days self.expire_time = 1 # days
def check_cache_if_expire(self): def check_cache_if_expire(self):

View File

@ -261,8 +261,8 @@ class SuiteReporter:
case_stacktrace = case_stacktrace.replace(chr(char_index), "") case_stacktrace = case_stacktrace.replace(chr(char_index), "")
test_case_attributes = {ReportConstant.name: case_result.test_name, test_case_attributes = {ReportConstant.name: case_result.test_name,
ReportConstant.status: "", ReportConstant.status: "",
ReportConstant.time: float( ReportConstant.time: round(float(
case_result.run_time) / 1000, case_result.run_time) / 1000, 3),
ReportConstant.class_name: ReportConstant.class_name:
case_result.test_class, case_result.test_class,
ReportConstant.result: "", ReportConstant.result: "",

View File

@ -137,6 +137,37 @@ def junit_para_parse(device, junit_paras, prefix_char="-e"):
return " ".join(ret_str) return " ".join(ret_str)
def get_include_tests(para_datas, test_types, runner):
case_list = []
if test_types == "class":
case_list = para_datas
else:
for case_file in para_datas:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(case_file, flags, modes), "r") as file_desc:
case_list.extend(file_desc.read().splitlines())
runner.add_instrumentation_arg("gtest_filter", ":".join(case_list).replace("#", "."))
def get_all_test_include(para_datas, test_types, runner, request):
case_list = []
if test_types == "notClass":
case_list = para_datas
else:
if para_datas:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(para_datas[0], flags, modes), "r") as file_handler:
json_data = json.load(file_handler)
exclude_list = json_data.get(DeviceTestType.cpp_test, [])
for exclude in exclude_list:
if request.get_module_name() in exclude:
temp = exclude.get(request.get_module_name())
case_list.extend(temp)
runner.add_instrumentation_arg("gtest_filter", "{}{}".format("-", ":".join(case_list)).replace("#", "."))
def gtest_para_parse(gtest_paras, runner, request): def gtest_para_parse(gtest_paras, runner, request):
"""To parse the para of gtest """To parse the para of gtest
Args: Args:
@ -144,40 +175,18 @@ def gtest_para_parse(gtest_paras, runner, request):
Returns: Returns:
the new para using in gtest the new para using in gtest
""" """
ret_str = []
if not isinstance(gtest_paras, dict): if not isinstance(gtest_paras, dict):
LOG.warning("The para of gtest is not the dict format as required") LOG.warning("The para of gtest is not the dict format as required")
return "" return ""
for para in gtest_paras.keys(): for para in gtest_paras.keys():
if para.strip() == 'test-file-include-filter': test_types = para.strip()
case_list = [] para_datas = gtest_paras.get(para)
files = gtest_paras.get(para) if test_types in ["test-file-include-filter", "class"]:
for case_file in files: get_include_tests(para_datas, test_types, runner)
flags = os.O_RDONLY elif test_types in ["all-test-file-exclude-filter", "notClass"]:
modes = stat.S_IWUSR | stat.S_IRUSR get_all_test_include(para_datas, test_types, runner, request)
with os.fdopen(os.open(case_file, flags, modes), return ""
"r") as file_desc:
case_list.extend(file_desc.read().splitlines())
runner.add_instrumentation_arg("gtest_filter", ":".join(case_list))
if para.strip() == 'all-test-file-exclude-filter':
json_file_list = gtest_paras.get("all-test-file-exclude-filter")
if json_file_list:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(json_file_list[0], flags, modes),
"r") as file_handler:
json_data = json.load(file_handler)
exclude_list = json_data.get(DeviceTestType.cpp_test, [])
for exclude in exclude_list:
if request.get_module_name() in exclude:
case_list = exclude.get(request.get_module_name())
runner.add_instrumentation_arg(
"gtest_filter",
"%s%s" % ("-", ":".join(case_list)))
return " ".join(ret_str)
def reset_junit_para(junit_para_str, prefix_char="-e", ignore_keys=None): def reset_junit_para(junit_para_str, prefix_char="-e", ignore_keys=None):

View File

@ -702,6 +702,12 @@ def get_cst_time():
return datetime.now(tz=cn_tz) return datetime.now(tz=cn_tz)
def get_delta_time_ms(start_time):
end_time = get_cst_time()
delta = round(float((end_time - start_time).total_seconds()) * 1000, 3)
return delta
def get_device_proc_pid(device, proc_name, double_check=False): def get_device_proc_pid(device, proc_name, double_check=False):
if not hasattr(device, "execute_shell_command") or \ if not hasattr(device, "execute_shell_command") or \
not hasattr(device, "log") or \ not hasattr(device, "log") or \