176e6818aSopenharmony_ci#!/usr/bin/env python3 276e6818aSopenharmony_ci# coding=utf-8 376e6818aSopenharmony_ci 476e6818aSopenharmony_ci# 576e6818aSopenharmony_ci# Copyright (c) 2022 Huawei Device Co., Ltd. 676e6818aSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 776e6818aSopenharmony_ci# you may not use this file except in compliance with the License. 876e6818aSopenharmony_ci# You may obtain a copy of the License at 976e6818aSopenharmony_ci# 1076e6818aSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 1176e6818aSopenharmony_ci# 1276e6818aSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 1376e6818aSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 1476e6818aSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1576e6818aSopenharmony_ci# See the License for the specific language governing permissions and 1676e6818aSopenharmony_ci# limitations under the License. 1776e6818aSopenharmony_ci# 1876e6818aSopenharmony_ci 1976e6818aSopenharmony_ciimport copy 2076e6818aSopenharmony_ciimport os 2176e6818aSopenharmony_ciimport sys 2276e6818aSopenharmony_ciimport traceback 2376e6818aSopenharmony_cifrom typing import Union 2476e6818aSopenharmony_ci 2576e6818aSopenharmony_cifrom xdevice import calculate_elapsed_time 2676e6818aSopenharmony_cifrom xdevice import check_result_report 2776e6818aSopenharmony_cifrom xdevice import StateRecorder 2876e6818aSopenharmony_cifrom xdevice import LifeCycle 2976e6818aSopenharmony_cifrom xdevice import ResultCode 3076e6818aSopenharmony_cifrom xdevice import get_cst_time 3176e6818aSopenharmony_cifrom xdevice import platform_logger 3276e6818aSopenharmony_cifrom xdevice import EnvPool 3376e6818aSopenharmony_cifrom xdevice import CaseEnd 3476e6818aSopenharmony_cifrom xdevice import Binder 3576e6818aSopenharmony_ci 3676e6818aSopenharmony_cifrom devicetest.runner.prepare import PrepareHandler 3776e6818aSopenharmony_cifrom devicetest.core.constants import RunResult 3876e6818aSopenharmony_cifrom devicetest.utils.util import clean_sys_resource 3976e6818aSopenharmony_cifrom devicetest.utils.util import get_base_name 4076e6818aSopenharmony_cifrom devicetest.utils.util import get_dir_path 4176e6818aSopenharmony_cifrom devicetest.utils.util import import_from_file 4276e6818aSopenharmony_cifrom devicetest.core.variables import DeccVariable 4376e6818aSopenharmony_cifrom devicetest.core.variables import ProjectVariables 4476e6818aSopenharmony_cifrom devicetest.core.variables import CurCase 4576e6818aSopenharmony_cifrom devicetest.core.exception import DeviceTestError 4676e6818aSopenharmony_cifrom devicetest.core.test_case import DeviceRoot 4776e6818aSopenharmony_cifrom devicetest.core.test_case import BaseCase 4876e6818aSopenharmony_cifrom devicetest.error import ErrorMessage 4976e6818aSopenharmony_cifrom devicetest.log.logger import DeviceTestLog as Log 5076e6818aSopenharmony_cifrom devicetest.report.generation import add_log_caching_handler 5176e6818aSopenharmony_cifrom devicetest.report.generation import del_log_caching_handler 5276e6818aSopenharmony_cifrom devicetest.report.generation import get_caching_logs 5376e6818aSopenharmony_cifrom devicetest.report.generation import generate_report 5476e6818aSopenharmony_ci 5576e6818aSopenharmony_ci 5676e6818aSopenharmony_ciclass RunnerMode: 5776e6818aSopenharmony_ci PIPELINE = "pipeline" 5876e6818aSopenharmony_ci DEBUG = "debug" 5976e6818aSopenharmony_ci 6076e6818aSopenharmony_ci 6176e6818aSopenharmony_ciclass TestRunner: 6276e6818aSopenharmony_ci """executes test cases and 6376e6818aSopenharmony_ci """ 6476e6818aSopenharmony_ci 6576e6818aSopenharmony_ci def __init__(self): 6676e6818aSopenharmony_ci self.run_mode = RunnerMode.PIPELINE 6776e6818aSopenharmony_ci self.run_list = None 6876e6818aSopenharmony_ci self.no_run_list = None 6976e6818aSopenharmony_ci self.running = None 7076e6818aSopenharmony_ci self.configs = None 7176e6818aSopenharmony_ci self.devices = None 7276e6818aSopenharmony_ci self.log = Log 7376e6818aSopenharmony_ci self.start_time = None 7476e6818aSopenharmony_ci self.test_results = None 7576e6818aSopenharmony_ci self.upload_result_handler = None 7676e6818aSopenharmony_ci self.project = None 7776e6818aSopenharmony_ci self.prepare = None 7876e6818aSopenharmony_ci self.cur_case = None 7976e6818aSopenharmony_ci self._repeat = 1 8076e6818aSopenharmony_ci self._repeat_round = 1 8176e6818aSopenharmony_ci 8276e6818aSopenharmony_ci def init_pipeline_runner(self, run_list, configs, devices, upload_result_handler): 8376e6818aSopenharmony_ci self.run_list = run_list 8476e6818aSopenharmony_ci self.no_run_list = copy.copy(self.run_list) 8576e6818aSopenharmony_ci self.running = False 8676e6818aSopenharmony_ci self.configs = configs 8776e6818aSopenharmony_ci self.devices = devices 8876e6818aSopenharmony_ci self.start_time = get_cst_time() 8976e6818aSopenharmony_ci self.test_results = [] 9076e6818aSopenharmony_ci self.upload_result_handler = upload_result_handler 9176e6818aSopenharmony_ci self.project = ProjectVariables(self.log) 9276e6818aSopenharmony_ci self.prepare = None 9376e6818aSopenharmony_ci self.__init_project_variables() 9476e6818aSopenharmony_ci self.run_mode = RunnerMode.PIPELINE 9576e6818aSopenharmony_ci self._repeat = self.configs.get("request").config.repeat 9676e6818aSopenharmony_ci self._repeat_round = self.configs.get("request").get_repeat_round() 9776e6818aSopenharmony_ci 9876e6818aSopenharmony_ci def init_case_runner(self, run_list: Union[BaseCase, list]): 9976e6818aSopenharmony_ci # simple case runner 10076e6818aSopenharmony_ci self.run_list = run_list 10176e6818aSopenharmony_ci self.run_mode = RunnerMode.DEBUG 10276e6818aSopenharmony_ci self.log = platform_logger("TestRunner") 10376e6818aSopenharmony_ci 10476e6818aSopenharmony_ci def __init_project_variables(self): 10576e6818aSopenharmony_ci """ 10676e6818aSopenharmony_ci testargs:为xDevice透传过来的数据,用户调用CONFIG可获取 10776e6818aSopenharmony_ci :return: 10876e6818aSopenharmony_ci """ 10976e6818aSopenharmony_ci self.log.debug("configs:{}".format(self.configs)) 11076e6818aSopenharmony_ci testcases_path = self.configs.get('testcases_path', "") 11176e6818aSopenharmony_ci testargs = self.configs.get("testargs", {}) 11276e6818aSopenharmony_ci self.__flash_run_list(testargs) 11376e6818aSopenharmony_ci 11476e6818aSopenharmony_ci self.cur_case = CurCase(self.log) 11576e6818aSopenharmony_ci self.project.set_project_path() 11676e6818aSopenharmony_ci self.project.set_testcase_path(testcases_path) 11776e6818aSopenharmony_ci self.project.set_task_report_dir(self.configs.get("report_path")) 11876e6818aSopenharmony_ci self.project.set_resource_path(self.get_local_resource_path()) 11976e6818aSopenharmony_ci 12076e6818aSopenharmony_ci def get_local_resource_path(self): 12176e6818aSopenharmony_ci local_resource_path = os.path.join( 12276e6818aSopenharmony_ci self.project.project_path, "testcases", "DeviceTest", "resource") 12376e6818aSopenharmony_ci return local_resource_path 12476e6818aSopenharmony_ci 12576e6818aSopenharmony_ci def get_local_aw_path(self): 12676e6818aSopenharmony_ci local_aw_path = os.path.join( 12776e6818aSopenharmony_ci self.project.project_path, "testcases", "DeviceTest", "aw") 12876e6818aSopenharmony_ci return local_aw_path 12976e6818aSopenharmony_ci 13076e6818aSopenharmony_ci def __flash_run_list(self, testargs): 13176e6818aSopenharmony_ci """ 13276e6818aSopenharmony_ci retry 场景更新run list 13376e6818aSopenharmony_ci :param testargs: 13476e6818aSopenharmony_ci :return: 13576e6818aSopenharmony_ci """ 13676e6818aSopenharmony_ci get_test = testargs.get("test") 13776e6818aSopenharmony_ci self.log.info("get test:{}".format(get_test)) 13876e6818aSopenharmony_ci retry_test_list = self.parse_retry_test_list(get_test) 13976e6818aSopenharmony_ci if retry_test_list is not None: 14076e6818aSopenharmony_ci self.run_list = retry_test_list 14176e6818aSopenharmony_ci self.no_run_list = copy.copy(self.run_list) 14276e6818aSopenharmony_ci self.log.info("retry test list:{}".format(retry_test_list)) 14376e6818aSopenharmony_ci 14476e6818aSopenharmony_ci def parse_retry_test_list(self, retry_test_list): 14576e6818aSopenharmony_ci if retry_test_list is None: 14676e6818aSopenharmony_ci return None 14776e6818aSopenharmony_ci elif not isinstance(retry_test_list, list): 14876e6818aSopenharmony_ci err_msg = ErrorMessage.TestCase.Code_0203005 14976e6818aSopenharmony_ci self.log.error(err_msg) 15076e6818aSopenharmony_ci raise DeviceTestError(err_msg) 15176e6818aSopenharmony_ci 15276e6818aSopenharmony_ci elif len(retry_test_list) == 1 and "#" not in str(retry_test_list[0]): 15376e6818aSopenharmony_ci return None 15476e6818aSopenharmony_ci else: 15576e6818aSopenharmony_ci history_case_list = [] 15676e6818aSopenharmony_ci history_case_dict = dict() 15776e6818aSopenharmony_ci retry_case_list = [] 15876e6818aSopenharmony_ci for abd_file_path in self.run_list: 15976e6818aSopenharmony_ci base_file_name = get_base_name(abd_file_path) 16076e6818aSopenharmony_ci if base_file_name not in history_case_dict.keys(): 16176e6818aSopenharmony_ci history_case_dict.update({base_file_name: []}) 16276e6818aSopenharmony_ci history_case_dict.get(base_file_name).append(abd_file_path) 16376e6818aSopenharmony_ci history_case_list.append(base_file_name) 16476e6818aSopenharmony_ci self.log.debug("history case list:{}".format(history_case_list)) 16576e6818aSopenharmony_ci 16676e6818aSopenharmony_ci for _value in retry_test_list: 16776e6818aSopenharmony_ci case_id = str(_value).split("#")[0] 16876e6818aSopenharmony_ci if case_id in history_case_dict.keys(): 16976e6818aSopenharmony_ci retry_case_list.append(history_case_dict.get(case_id)[0]) 17076e6818aSopenharmony_ci return retry_case_list 17176e6818aSopenharmony_ci 17276e6818aSopenharmony_ci def parse_config(self, test_configs): 17376e6818aSopenharmony_ci pass 17476e6818aSopenharmony_ci 17576e6818aSopenharmony_ci def add_value_to_configs(self): 17676e6818aSopenharmony_ci self.configs["log"] = self.log 17776e6818aSopenharmony_ci self.configs["devices"] = self.devices 17876e6818aSopenharmony_ci self.configs["project"] = self.project 17976e6818aSopenharmony_ci 18076e6818aSopenharmony_ci def run(self): 18176e6818aSopenharmony_ci self._pipeline_run() 18276e6818aSopenharmony_ci 18376e6818aSopenharmony_ci def _pipeline_run(self): 18476e6818aSopenharmony_ci self.running = True 18576e6818aSopenharmony_ci aw_path = self.add_aw_path_to_sys(self.project.aw_path) 18676e6818aSopenharmony_ci self.log.info("Executing run list {}.".format(self.run_list)) 18776e6818aSopenharmony_ci 18876e6818aSopenharmony_ci self.add_value_to_configs() 18976e6818aSopenharmony_ci 19076e6818aSopenharmony_ci self.prepare = PrepareHandler(self.log, self.cur_case, 19176e6818aSopenharmony_ci self.project, self.configs, 19276e6818aSopenharmony_ci self.devices, self.run_list) 19376e6818aSopenharmony_ci # **********混合root和非root************** 19476e6818aSopenharmony_ci try: 19576e6818aSopenharmony_ci for device in self.devices: 19676e6818aSopenharmony_ci if hasattr(device, "is_root"): 19776e6818aSopenharmony_ci DeviceRoot.is_root_device = device.is_root 19876e6818aSopenharmony_ci self.log.debug(DeviceRoot.is_root_device) 19976e6818aSopenharmony_ci setattr(device, "is_device_root", DeviceRoot.is_root_device) 20076e6818aSopenharmony_ci 20176e6818aSopenharmony_ci except Exception as _: 20276e6818aSopenharmony_ci self.log.error('set branch api error.') 20376e6818aSopenharmony_ci # **************混合root和非root end********************** 20476e6818aSopenharmony_ci self.prepare.run_prepare() 20576e6818aSopenharmony_ci 20676e6818aSopenharmony_ci for test_cls_name in self.run_list: 20776e6818aSopenharmony_ci case_name = get_base_name(test_cls_name) 20876e6818aSopenharmony_ci if self.project.record.is_shutdown(raise_exception=False): 20976e6818aSopenharmony_ci break 21076e6818aSopenharmony_ci self.log.info("Executing test class {}".format(test_cls_name)) 21176e6818aSopenharmony_ci self.project.execute_case_name = case_name 21276e6818aSopenharmony_ci self.run_test_class(test_cls_name, case_name) 21376e6818aSopenharmony_ci self.prepare.run_prepare(is_teardown=True) 21476e6818aSopenharmony_ci clean_sys_resource(file_path=aw_path) 21576e6818aSopenharmony_ci DeccVariable.reset() 21676e6818aSopenharmony_ci 21776e6818aSopenharmony_ci def add_aw_path_to_sys(self, aw_path): 21876e6818aSopenharmony_ci 21976e6818aSopenharmony_ci sys_aw_path = os.path.dirname(aw_path) 22076e6818aSopenharmony_ci if os.path.exists(sys_aw_path): 22176e6818aSopenharmony_ci sys.path.insert(1, sys_aw_path) 22276e6818aSopenharmony_ci self.log.info("add {} to sys path.".format(sys_aw_path)) 22376e6818aSopenharmony_ci return sys_aw_path 22476e6818aSopenharmony_ci return None 22576e6818aSopenharmony_ci 22676e6818aSopenharmony_ci def run_test_class(self, case_path, case_name): 22776e6818aSopenharmony_ci """Instantiates and executes a test class. 22876e6818aSopenharmony_ci If the test cases list is not None, all the test cases in the test 22976e6818aSopenharmony_ci class should be executed. 23076e6818aSopenharmony_ci Args: 23176e6818aSopenharmony_ci case_path: case path 23276e6818aSopenharmony_ci case_name: case name 23376e6818aSopenharmony_ci Returns: 23476e6818aSopenharmony_ci A tuple, with the number of cases passed at index 0, and the total 23576e6818aSopenharmony_ci number of test cases at index 1. 23676e6818aSopenharmony_ci """ 23776e6818aSopenharmony_ci # 开始收集日志 23876e6818aSopenharmony_ci case_log_buffer_hdl = add_log_caching_handler() 23976e6818aSopenharmony_ci 24076e6818aSopenharmony_ci tests = "__init__" 24176e6818aSopenharmony_ci case_result = RunResult.FAILED 24276e6818aSopenharmony_ci start_time = get_cst_time() 24376e6818aSopenharmony_ci case_dir_path = get_dir_path(case_path) 24476e6818aSopenharmony_ci test_cls_instance = None 24576e6818aSopenharmony_ci 24676e6818aSopenharmony_ci # 用例测试结果的拓展内容 24776e6818aSopenharmony_ci result_content = None 24876e6818aSopenharmony_ci try: 24976e6818aSopenharmony_ci self.project.cur_case_full_path = case_path 25076e6818aSopenharmony_ci DeccVariable.set_cur_case_obj(self.cur_case) 25176e6818aSopenharmony_ci test_cls = import_from_file(case_dir_path, case_name) 25276e6818aSopenharmony_ci self.log.info("Success to import {}.".format(case_name)) 25376e6818aSopenharmony_ci with test_cls(self.configs) as test_cls_instance: 25476e6818aSopenharmony_ci self.cur_case.set_case_instance(test_cls_instance) 25576e6818aSopenharmony_ci test_cls_instance.run() 25676e6818aSopenharmony_ci 25776e6818aSopenharmony_ci tests = test_cls_instance.tests 25876e6818aSopenharmony_ci start_time = test_cls_instance.start_time 25976e6818aSopenharmony_ci 26076e6818aSopenharmony_ci case_result = test_cls_instance.result 26176e6818aSopenharmony_ci error_msg = test_cls_instance.error_msg 26276e6818aSopenharmony_ci result_content = getattr(test_cls_instance, "result_content", None) 26376e6818aSopenharmony_ci except ImportError as exception: 26476e6818aSopenharmony_ci error_msg = str(exception) 26576e6818aSopenharmony_ci self.log.error(error_msg) 26676e6818aSopenharmony_ci self.log.error(traceback.format_exc()) 26776e6818aSopenharmony_ci except Exception as exception: 26876e6818aSopenharmony_ci error_msg = ErrorMessage.TestCase.Code_0203002.format(exception) 26976e6818aSopenharmony_ci self.log.error(error_msg) 27076e6818aSopenharmony_ci self.log.error(traceback.format_exc()) 27176e6818aSopenharmony_ci if test_cls_instance: 27276e6818aSopenharmony_ci try: 27376e6818aSopenharmony_ci del test_cls_instance 27476e6818aSopenharmony_ci self.log.debug("del test_cls_instance success.") 27576e6818aSopenharmony_ci except Exception as exception: 27676e6818aSopenharmony_ci self.log.warning("del test_cls_instance exception. {}".format(exception)) 27776e6818aSopenharmony_ci 27876e6818aSopenharmony_ci Binder.notify_stage(CaseEnd(case_name, case_result, error_msg)) 27976e6818aSopenharmony_ci 28076e6818aSopenharmony_ci end_time = get_cst_time() 28176e6818aSopenharmony_ci environment = self.configs.get("request").config.environment 28276e6818aSopenharmony_ci steps = self.cur_case.get_steps_info() 28376e6818aSopenharmony_ci # 停止收集日志 28476e6818aSopenharmony_ci del_log_caching_handler(case_log_buffer_hdl) 28576e6818aSopenharmony_ci # 生成报告 28676e6818aSopenharmony_ci case_info = { 28776e6818aSopenharmony_ci "name": case_name, 28876e6818aSopenharmony_ci "result": case_result, 28976e6818aSopenharmony_ci "begin": start_time.strftime("%Y-%m-%d %H:%M:%S"), 29076e6818aSopenharmony_ci "end": end_time.strftime("%Y-%m-%d %H:%M:%S"), 29176e6818aSopenharmony_ci 'elapsed': calculate_elapsed_time(start_time, end_time), 29276e6818aSopenharmony_ci "error": error_msg, 29376e6818aSopenharmony_ci "logs": "", 29476e6818aSopenharmony_ci "devices": [] if environment is None else environment.get_description(), 29576e6818aSopenharmony_ci "steps": steps 29676e6818aSopenharmony_ci } 29776e6818aSopenharmony_ci log_content = { 29876e6818aSopenharmony_ci "content": get_caching_logs(case_log_buffer_hdl) 29976e6818aSopenharmony_ci } 30076e6818aSopenharmony_ci round_folder = f"round{self._repeat_round}" if self._repeat > 1 else "" 30176e6818aSopenharmony_ci report_path = os.path.join("details", round_folder, case_name + ".html") 30276e6818aSopenharmony_ci to_file = os.path.join(self.project.task_report_dir, report_path) 30376e6818aSopenharmony_ci generate_report(to_file, case=case_info, logs=log_content) 30476e6818aSopenharmony_ci steps.clear() 30576e6818aSopenharmony_ci del case_log_buffer_hdl 30676e6818aSopenharmony_ci self.cur_case.set_case_instance(None) 30776e6818aSopenharmony_ci self.record_current_case_result( 30876e6818aSopenharmony_ci case_name, tests, case_result, start_time, error_msg, report_path, 30976e6818aSopenharmony_ci result_content=result_content) 31076e6818aSopenharmony_ci return case_result, error_msg 31176e6818aSopenharmony_ci 31276e6818aSopenharmony_ci def record_current_case_result(self, case_name, tests, case_result, 31376e6818aSopenharmony_ci start_time, error_msg, report, **kwargs): 31476e6818aSopenharmony_ci test_result = self.record_cls_result( 31576e6818aSopenharmony_ci case_name, tests, case_result, start_time, error_msg, report, **kwargs) 31676e6818aSopenharmony_ci self.log.debug("test result: {}".format(test_result)) 31776e6818aSopenharmony_ci self.test_results.append(test_result) 31876e6818aSopenharmony_ci self.upload_result_handler.report_handler.test_results.append(test_result) 31976e6818aSopenharmony_ci 32076e6818aSopenharmony_ci def stop(self): 32176e6818aSopenharmony_ci """ 32276e6818aSopenharmony_ci Releases resources from test run. Should be called right after run() 32376e6818aSopenharmony_ci finishes. 32476e6818aSopenharmony_ci """ 32576e6818aSopenharmony_ci if self.running: 32676e6818aSopenharmony_ci self.running = False 32776e6818aSopenharmony_ci 32876e6818aSopenharmony_ci @staticmethod 32976e6818aSopenharmony_ci def record_cls_result(case_name, tests_step, result, start_time, error, report, **kwargs): 33076e6818aSopenharmony_ci dict_result = { 33176e6818aSopenharmony_ci "case_name": case_name, 33276e6818aSopenharmony_ci "tests_step": tests_step or "__init__", 33376e6818aSopenharmony_ci "result": result or RunResult.FAILED, 33476e6818aSopenharmony_ci "start_time": start_time or get_cst_time(), 33576e6818aSopenharmony_ci "error": error, 33676e6818aSopenharmony_ci "end_time": get_cst_time(), 33776e6818aSopenharmony_ci "report": report 33876e6818aSopenharmony_ci } 33976e6818aSopenharmony_ci dict_result.update(kwargs) 34076e6818aSopenharmony_ci return dict_result 34176e6818aSopenharmony_ci 34276e6818aSopenharmony_ci 34376e6818aSopenharmony_ciclass TestSuiteRunner: 34476e6818aSopenharmony_ci """ 34576e6818aSopenharmony_ci executes test suite cases 34676e6818aSopenharmony_ci """ 34776e6818aSopenharmony_ci 34876e6818aSopenharmony_ci def __init__(self, suite, configs, devices): 34976e6818aSopenharmony_ci self.suite = suite 35076e6818aSopenharmony_ci self.running = False 35176e6818aSopenharmony_ci self.configs = configs 35276e6818aSopenharmony_ci self.devices = devices 35376e6818aSopenharmony_ci self.log = Log 35476e6818aSopenharmony_ci self.start_time = get_cst_time() 35576e6818aSopenharmony_ci self.listeners = self.configs["listeners"] 35676e6818aSopenharmony_ci self.state_machine = StateRecorder() 35776e6818aSopenharmony_ci self.suite_name = "" 35876e6818aSopenharmony_ci 35976e6818aSopenharmony_ci def add_value_to_configs(self): 36076e6818aSopenharmony_ci self.configs["log"] = self.log 36176e6818aSopenharmony_ci self.configs["devices"] = self.devices 36276e6818aSopenharmony_ci self.configs["suite_name"] = self.suite_name 36376e6818aSopenharmony_ci 36476e6818aSopenharmony_ci def run(self): 36576e6818aSopenharmony_ci self.running = True 36676e6818aSopenharmony_ci self.log.info("Executing test suite: {}.".format(self.suite)) 36776e6818aSopenharmony_ci 36876e6818aSopenharmony_ci self.suite_name = get_base_name(self.suite) 36976e6818aSopenharmony_ci self.add_value_to_configs() 37076e6818aSopenharmony_ci self.run_test_suite(self.suite) 37176e6818aSopenharmony_ci 37276e6818aSopenharmony_ci def run_test_suite(self, test_cls_name): 37376e6818aSopenharmony_ci """Instantiates and executes a test class. 37476e6818aSopenharmony_ci If the test cases list is not None, all the test cases in the test 37576e6818aSopenharmony_ci class should be executed. 37676e6818aSopenharmony_ci Args: 37776e6818aSopenharmony_ci test_cls_name: Name of the test class to execute. 37876e6818aSopenharmony_ci Returns: 37976e6818aSopenharmony_ci A tuple, with the number of cases passed at index 0, and the total 38076e6818aSopenharmony_ci number of test cases at index 1. 38176e6818aSopenharmony_ci """ 38276e6818aSopenharmony_ci suite_dir_path = get_dir_path(test_cls_name) 38376e6818aSopenharmony_ci test_cls_instance = None 38476e6818aSopenharmony_ci self.handle_suites_started() 38576e6818aSopenharmony_ci self.handle_suite_started() 38676e6818aSopenharmony_ci try: 38776e6818aSopenharmony_ci test_cls = import_from_file(suite_dir_path, self.suite_name) 38876e6818aSopenharmony_ci self.log.info("Success to import {}.".format(self.suite_name)) 38976e6818aSopenharmony_ci self.configs["cur_suite"] = test_cls 39076e6818aSopenharmony_ci with test_cls(self.configs, suite_dir_path) as test_cls_instance: 39176e6818aSopenharmony_ci test_cls_instance.run() 39276e6818aSopenharmony_ci 39376e6818aSopenharmony_ci error_msg = test_cls_instance.error_msg 39476e6818aSopenharmony_ci self.handle_suite_ended(test_cls_instance) 39576e6818aSopenharmony_ci except Exception as e: 39676e6818aSopenharmony_ci error_msg = ErrorMessage.TestCase.Code_0203017.format(e) 39776e6818aSopenharmony_ci self.log.error(error_msg) 39876e6818aSopenharmony_ci self.log.error(traceback.format_exc()) 39976e6818aSopenharmony_ci self.handle_suites_ended(error_msg) 40076e6818aSopenharmony_ci result_path = os.path.join(self.configs["report_path"], "result") 40176e6818aSopenharmony_ci report_file = os.path.join(result_path, "%s.xml" % self.suite_name) 40276e6818aSopenharmony_ci os.makedirs(result_path, exist_ok=True) 40376e6818aSopenharmony_ci check_result_report("", report_file, error_message=error_msg) 40476e6818aSopenharmony_ci if test_cls_instance: 40576e6818aSopenharmony_ci try: 40676e6818aSopenharmony_ci del test_cls_instance 40776e6818aSopenharmony_ci self.log.debug("del test suite instance success.") 40876e6818aSopenharmony_ci except Exception as e: 40976e6818aSopenharmony_ci self.log.warning("del test suite instance exception. " 41076e6818aSopenharmony_ci "Exception: {}".format(e)) 41176e6818aSopenharmony_ci return error_msg 41276e6818aSopenharmony_ci 41376e6818aSopenharmony_ci def stop(self): 41476e6818aSopenharmony_ci """ 41576e6818aSopenharmony_ci Releases resources from test run. Should be called right after run() 41676e6818aSopenharmony_ci finishes. 41776e6818aSopenharmony_ci """ 41876e6818aSopenharmony_ci if self.running: 41976e6818aSopenharmony_ci self.running = False 42076e6818aSopenharmony_ci 42176e6818aSopenharmony_ci def handle_suites_started(self): 42276e6818aSopenharmony_ci self.state_machine.get_suites(reset=True) 42376e6818aSopenharmony_ci test_suites = self.state_machine.get_suites() 42476e6818aSopenharmony_ci test_suites.suites_name = self.suite_name 42576e6818aSopenharmony_ci test_suites.test_num = 0 42676e6818aSopenharmony_ci for listener in self.listeners: 42776e6818aSopenharmony_ci suite_report = copy.copy(test_suites) 42876e6818aSopenharmony_ci listener.__started__(LifeCycle.TestSuites, suite_report) 42976e6818aSopenharmony_ci 43076e6818aSopenharmony_ci def handle_suites_ended(self, error_msg): 43176e6818aSopenharmony_ci suites = self.state_machine.get_suites() 43276e6818aSopenharmony_ci suites.is_completed = True 43376e6818aSopenharmony_ci suites.stacktrace = error_msg 43476e6818aSopenharmony_ci for listener in self.listeners: 43576e6818aSopenharmony_ci listener.__ended__(LifeCycle.TestSuites, suites) 43676e6818aSopenharmony_ci 43776e6818aSopenharmony_ci def handle_suite_started(self): 43876e6818aSopenharmony_ci self.state_machine.suite(reset=True) 43976e6818aSopenharmony_ci self.state_machine.running_test_index = 0 44076e6818aSopenharmony_ci test_suite = self.state_machine.suite() 44176e6818aSopenharmony_ci test_suite.suite_name = self.suite_name 44276e6818aSopenharmony_ci test_suite.test_num = 0 44376e6818aSopenharmony_ci for listener in self.listeners: 44476e6818aSopenharmony_ci suite_report = copy.copy(test_suite) 44576e6818aSopenharmony_ci listener.__started__(LifeCycle.TestSuite, suite_report) 44676e6818aSopenharmony_ci 44776e6818aSopenharmony_ci def handle_suite_ended(self, testsuite_cls): 44876e6818aSopenharmony_ci suite = self.state_machine.suite() 44976e6818aSopenharmony_ci suites = self.state_machine.get_suites() 45076e6818aSopenharmony_ci self.handle_one_case_result(testsuite_cls) 45176e6818aSopenharmony_ci suite.is_completed = True 45276e6818aSopenharmony_ci # 设置测试套的报告路径 45376e6818aSopenharmony_ci suite.report = testsuite_cls.suite_report_path 45476e6818aSopenharmony_ci for listener in self.listeners: 45576e6818aSopenharmony_ci listener.__ended__(LifeCycle.TestSuite, copy.copy(suite), is_clear=True) 45676e6818aSopenharmony_ci suites.run_time += suite.run_time 45776e6818aSopenharmony_ci 45876e6818aSopenharmony_ci def handle_one_case_result(self, testsuite_cls): 45976e6818aSopenharmony_ci status_dict = {RunResult.PASSED: ResultCode.PASSED, 46076e6818aSopenharmony_ci RunResult.FAILED: ResultCode.FAILED, 46176e6818aSopenharmony_ci RunResult.BLOCKED: ResultCode.BLOCKED, 46276e6818aSopenharmony_ci "ignore": ResultCode.SKIPPED} 46376e6818aSopenharmony_ci for case_name, case_result in testsuite_cls.case_result.items(): 46476e6818aSopenharmony_ci result = case_result.get("result") 46576e6818aSopenharmony_ci error = case_result.get("error") 46676e6818aSopenharmony_ci run_time = case_result.get("run_time") 46776e6818aSopenharmony_ci report = case_result.get("report") 46876e6818aSopenharmony_ci result_content = case_result.get("result_content") 46976e6818aSopenharmony_ci 47076e6818aSopenharmony_ci test_result = self.state_machine.test(reset=True) 47176e6818aSopenharmony_ci test_suite = self.state_machine.suite() 47276e6818aSopenharmony_ci test_result.test_class = test_suite.suite_name 47376e6818aSopenharmony_ci test_result.test_name = case_name 47476e6818aSopenharmony_ci test_result.code = status_dict.get(result).value 47576e6818aSopenharmony_ci test_result.stacktrace = error 47676e6818aSopenharmony_ci test_result.run_time = run_time 47776e6818aSopenharmony_ci test_result.report = report 47876e6818aSopenharmony_ci if result_content: 47976e6818aSopenharmony_ci test_result.result_content = result_content 48076e6818aSopenharmony_ci test_result.current = self.state_machine.running_test_index + 1 48176e6818aSopenharmony_ci 48276e6818aSopenharmony_ci self.state_machine.suite().run_time += run_time 48376e6818aSopenharmony_ci for listener in self.listeners: 48476e6818aSopenharmony_ci listener.__started__( 48576e6818aSopenharmony_ci LifeCycle.TestCase, copy.copy(test_result)) 48676e6818aSopenharmony_ci test_suites = self.state_machine.get_suites() 48776e6818aSopenharmony_ci test_suites.test_num += 1 48876e6818aSopenharmony_ci for listener in self.listeners: 48976e6818aSopenharmony_ci listener.__ended__( 49076e6818aSopenharmony_ci LifeCycle.TestCase, copy.copy(test_result)) 49176e6818aSopenharmony_ci self.state_machine.running_test_index += 1 492