框架核心API接口

资源模块

我们将自动化测试过程中的所有测试实体,如测试设备类、测试服务类、测试软件类等均看做测试资源。在这一层,测试资源将提供其所拥有的所有基础接口,并对外开放。

  • 测试设备类

测试设备类资源是测试过程中用到的硬件设备,如测试TV设备、测试手机设备、机械手设备、色彩分析仪设备等。

  • 测试服务类

测试服务类资源是测试过程中用到的系统服务,如HTTP服务、FTP服务、TCP服务等。

  • 测试软件类

测试软件类资源是测试过程中用到的软件,可以是命令行形式的也可以是GUI形式的。

资源拓扑图

_images/topo.svg

资源类Resource

class testbot.resource.resource.Resource(name: str = '', *args, **kwargs)[source]

代表所有测试资源设备的配置类,字段动态定义

MODULES = ['testbot.resource.modules.device_module.PowerModule'][source]
description[source]
classmethod from_dict()[source]
name[source]
classmethod register_module(module: str)[source]

注册接口模块类

Parameters:

module (str) – 接口模块类包路径

Returns:

Return type:

abstract to_dict()[source]
type[source]

设备类Device

class testbot.resource.device.Device(name: str = '', *args: tuple, **kwargs: dict)[source]

Bases: testbot.resource.resource.Resource

代表所有测试设备类

add_port(name: str, *args: tuple, **kwargs: dict)[source]

添加端口

Parameters:
  • name (str) – 端口名称

  • args (tuple) – 元祖参数

  • kwargs (dict) – 键值对参数

Returns:

None

Return type:

NoneType

static from_dict(dict_obj)[source]
get_comm_instance(new=False)[source]
get_port_count(**kwargs: dict)[source]

获取端口数量

Parameters:

kwargs (dict) – 键值对参数

Returns:

端口数量

Return type:

int

to_dict()[source]

端口类Port

class testbot.resource.device.Port(parent_device: Device = None, name: str = '', *args: tuple, **kwargs: dict)[source]

Bases: testbot.resource.resource.Resource

代表所有端口类

static from_dict(dict_obj, parent)[source]
get_comm_instance(new=False)[source]
to_dict()[source]

资源池类ResourcePool

class testbot.resource.pool.ResourcePool(*args, **kwargs)[source]

Bases: object

资源池类,负责资源的序列化和反序列化以及储存和读取

add_device(device_name: str, **kwargs)[source]

添加设备到资源池

Parameters:
  • device_name (str) – 设备名称

  • kwargs (dict) – 键值对参数

Returns:

None

Return type:

NoneType

collect_all_device(device_type, constraints=list())[source]
collect_connection_route(resource: str, constraints: list = list())[source]

获取资源连接路由

Parameters:
  • resource

  • constraints

Returns:

链接路由

Return type:

list

collect_device(device_type, count, constraints=list())[source]
discover_resources()[source]

发现测试资源

load(filename: str, owner: str)[source]

加载文件

Parameters:
  • filename (str) – 文件路径

  • owner (str) – 资源所有人

Returns:

None

Return type:

NoneType

release()[source]

释放当前资源

Returns:

Return type:

reserve()[source]

占用当前资源

Returns:

Return type:

save(filename: str)[source]

保存文件

Parameters:

filename (str) – 文件路径

Returns:

None

Return type:

NoneType

资源池序列化反序列化

下面是一个例子,介绍了如何创建一个资源池,并进行序列化和反序列化:

资源池类可以从json文件将json数据反序列化为资源池对象,反之亦可,即可以将资源池对象序列化为json数据并保存到本地json文件。如下是一个序列化后的json格式的资源池:

插件模块

配置模块

支持静态配置和动态配置。静态配置,既可以将本地json文件反序列化为类对象,也可以将类对象序列化为本地json文件,一般用于框架公共模块配置文件的持久化;动态配置,将本地json文件反序列化为类对象,一般用于用例类的特有参数配置。

配置基类SettingBase

class testbot.config.setting.SettingBase[source]

配置基类

file_name[source]
classmethod load()[source]

加载配置文件

Returns:

None

Return type:

NoneType

classmethod save()[source]

保存配置文件

Returns:

None

Return type:

NoneType

setting_path[source]

静态配置管理器类StaticSettingManager

class testbot.config.setting.StaticSettingManager[source]

Bases: object

静态配置管理类

add_setting(setting_name: str, setting_class: object)[source]

添加配置对象

Parameters:
  • setting_name (str) – 配置名称

  • setting_class (object) – 配置类

Returns:

Return type:

load_all()[source]

读取所有配置

save_all()[source]

保存所有配置

setting(setting_name: str, *args: tuple, **kwargs: dict)[source]

配置文件的注册装饰器

Parameters:
  • setting_name (str) – 配置名称

  • args

  • kwargs

Returns:

Return type:

property setting_path[source]

设置路径

Returns:

设置路径

Return type:

str

sync_path()[source]

同步所有配置的路径

创建静态配置

下面是一个创建静态配置的例子。该例子为Resource模块创建了一个配置文件ResourceSetting.json,可通过ResourceSetting类对配置文件的json数据进行双向读取和保存。我们可以手动往配置文件里添加新属性,类ResourceSetting就可访问该属性。

 1#!/usr/bin/env python
 2# -*- coding: utf-8 -*-
 3
 4__copyright__ = "Copyright (c) 2024 Nuanguang Gu(Sunny) Reserved"
 5__author__ = "Nuanguang Gu(Sunny)"
 6__email__ = "nuanguang.gu@aliyun.com"
 7
 8
 9import os
10from pathlib import Path
11from testbot.config.setting import static_setting, SettingBase
12
13
14if __name__ == "__main__":
15    # 基于配置基类SettingBase,创建一个配置子类,该配置子类使用装饰器static_setting装饰
16    @static_setting.setting("ResourceSetting")
17    class ResourceSetting(SettingBase):
18        """
19        资源设置类
20        """
21        file_name = "ResourceSetting.json"
22
23        resource_path = os.path.join(str(Path.home()), "TBOT", "configs")
24        auto_connect = False
25
26
27    # 从本地json文件ResourceSetting.json加载属性信息到类ResourceSetting,由于第一次没有该文件,会创建并使用类的默认属性值
28    ResourceSetting.load()
29
30    # 读取属性ResourceSetting.auto_connect
31    print(f"ResourceSetting.auto_connect={ResourceSetting.auto_connect}")
32
33    # 设置属性ResourceSetting.auto_connect
34    ResourceSetting.auto_connect = True
35
36    # 读取属性ResourceSetting.auto_connect
37    print(f"ResourceSetting.auto_connect={ResourceSetting.auto_connect}")
38
39    # 将当前的属性信息保存到本地文件ResourceSetting.json
40    ResourceSetting.save()
41
42    # 从本地json文件ResourceSetting.json加载属性信息到类ResourceSetting,由于第一次没有该文件,会创建并使用类的默认属性值
43    ResourceSetting.load()
44
45    # 读取属性ResourceSetting.auto_connect
46    print(f"ResourceSetting.auto_connect={ResourceSetting.auto_connect}")

该Resource模块的静态配置文件内容如下:

1{
2    "resource_path": "C:\\Users\\nuanguang.gu\\TBOT\\configs",
3    "auto_connect": true,
4    "hello": "HelloWorld"
5}

创建动态配置

下面是一个创建动态配置的例子。该例子为用例类创建了一个配置文件

该用例的动态配置文件内容如下:

1{
2    "field1": 3,
3    "field2": 2
4}

配置文件目录

默认情况下,模块配置文件将会保存到目录~/TESTBOT/configs下。

C:\USERS\NUANGUANG.GU\TESTBOT
├───configs
│       CaseRunnerSetting.json
│       ModuleSetting.json
│       ResourcePool.json
│       ResourceSetting.json
│
└───logs
    ├───cases
    │   └───20240905180219
    │       └───A Demo Test List
    │               TCDemo.log
    │
    ├───modules
    │       Resource.log
    │
    └───runner
            CaseRunner.log

用例模块

用例基类TestCaseBase

该类定义了所有用例的父类,该基类提供了collect_resource()、setup_class()/setup()/test()/cleanup()/cleanup_class()等抽象方法,子类需实现这些方法。

子类示例

下面是一个子类例子。该子类实现了collect_resource()、setup_class()/setup()/test()/cleanup()/cleanup_class()等方法。此外,如果该用例需要从外部配置文件读取一些用例特有的配置信息,可以在该用例类里创建一个配置类,该类是一个类中类。 默认该配置文件名称与该配置类名相同。

  1#!/usr/bin/env python
  2# -*- coding: utf-8 -*-
  3
  4__copyright__ = "Copyright (c) 2024 Nuanguang Gu(Sunny) Reserved"
  5__author__ = "Nuanguang Gu(Sunny)"
  6__email__ = "nuanguang.gu@aliyun.com"
  7
  8"""
  9@TC_ID          : SQAOSTC-78198
 10@Introduction   : Idle期按红外遥控器数字键唤醒电视
 11@Description    : 功能描述:
 12串口出现:DeviceIdleController: Moved from STATE_LOCATING to STATE_IDLE.时,电视进入Idle界面
 13@Precondition   : 
 141、STR为ON,Doze mode为ON
 152、调整Idle时间的方法:串口执行:dumpsys deviceidle IDLE_TIMEOUT set 300000(300000为时间,可修改)
 163、遥控器未配对
 17@Steps:
 181、连接网络,切换到HDMI信源
 192、串口执行:
 201.dumpsys deviceidle tlog set DEBUG 1 ;
 212.logcat | grep DeviceIdleController&;按Power键待机
 223、有切换到idle状态的打印后,使用红外遥控器,按数字键,检查电视变化
 234、Doze mode设置为关,使用红外遥控器按数字键待机开机
 24
 25【备注】仅适用海外
 26@Expected       :
 272、串口打印:DeviceIdleController: Moved from STATE_LOCATING to STATE_IDLE.
 283、电视整响应遥控器按键操作,成功唤醒
 294、待机串口不会有Doze模式打印,电视可以响应遥控器按键操作,成功唤醒
 30"""
 31
 32from testbot.case.base import TestCaseBase, TestType
 33from testbot.case.decorator import case
 34from testbot.config.setting import TestSettingBase
 35from testbot.resource.pool import ResourcePool
 36from testbot.result.testreporter import CaseEntry
 37
 38
 39@case(priority=1, test_type=TestType.SMOKE_TEST.name, testcase_id="SQAOSTC-78198", testcase_name="测试用例Demo演示")
 40class TCDemo(TestCaseBase):
 41
 42    def collect_resource(self, node: CaseEntry, pool: ResourcePool):
 43        self.logger.info("执行collect_resource方法")
 44        # 结构化验证点实现方式
 45        # with node.start(headline="筛选设备", message="") as step:
 46        #     with step.start(headline="筛选PC设备", message="") as step2:
 47        #         self.pc = pool.collect_device(device_type="PCDevice", count=1)[0]
 48        #         if self.pc:
 49        #             step2.passed(message="筛选PC设备成功")
 50        #         else:
 51        #             step2.failed(message="筛选PC设备失败")
 52        #     with step.start(headline="筛选TV设备", message="") as step2:
 53        #         self.tv = pool.collect_device(device_type="TVDevice", count=1)[0]
 54        #         if self.tv:
 55        #             step2.passed(message="筛选TV设备成功")
 56        #         else:
 57        #             step2.failed(message="筛选TV设备失败")
 58        pass
 59
 60    def setup(self, node: CaseEntry, **kwargs):
 61        self.logger.info("执行setup方法")
 62        # 结构化验证点实现方式
 63        # self.logger.info(f"case_setting1={self.setting.case_setting1}, case_setting2={self.setting.case_setting2}, TIMEOUT={self.setting.TIMEOUT}")
 64        with node.start(headline="", message="") as step:
 65            step.passed(message="设置STR为ON")
 66        with node.start(headline="", message="") as step:
 67            step.passed(message="设置STR为ON")
 68        with node.start(headline="", message="设置待机时长") as step:
 69            pass
 70        with node.start(headline="", message="") as step:
 71            step.info(message="安装WIFI apk")
 72        with node.start(headline="", message="断开有线连接") as step:
 73            step.passed(message="断开有线连接")
 74        with node.start(headline="", message="") as step:
 75            step.passed(message="连接并检查WIFI热点")
 76
 77    def test(self, node: CaseEntry, **kwargs):
 78        self.logger.info("执行test方法")
 79        with node.start(headline="", message="") as step:
 80            step.passed(message="打开Youtube播放任意视频")
 81        with node.start(headline="", message="") as step:
 82            step.passed(message="按power键进入待机状态")
 83        with node.start(headline="", message="") as step:
 84            step.passed(message="等待5秒后,按power键唤醒电视")
 85        with node.start(headline="", message="") as step:
 86            step.passed(message="开机后检查WIFI热点")
 87        with node.start(headline="", message="") as step:
 88            step.passed(message="开机后进入在线视频")
 89        with node.start(headline="", message="") as step:
 90            # self.tv.PowerModule.power_off()
 91            step.passed(message="给电视断电")
 92        with node.start(headline="", message="") as step:
 93            # self.tv.PowerModule.power_on()
 94            step.passed(message="给电视上电")
 95        with node.start(headline="", message="") as step:
 96            step.passed(message="等待30秒后,按power键唤醒电视")
 97        with node.start(headline="", message="") as step:
 98            step.passed(message="开机后检查WIFI热点")
 99        with node.start(headline="", message="") as step:
100            1 / 0
101            pass
102            step.passed(message="开机后进入Launcher页面")
103        with step.start(headline="", message="") as step:
104            step.passed(message="打开Youtube播放任意视频")
105
106    def cleanup(self, node: CaseEntry, **kwargs):
107        self.logger.info("执行cleanup方法")
108        with node.start(headline="", message="") as step:
109            step.passed(message="断开WIFI热点")
110        with node.start(headline="", message="") as step:
111            step.passed(message="关闭WIFI开关")
112
113    class TCDemoSetting(TestSettingBase):
114        case_setting1 = "setting1"
115        case_setting2 = 10
116        TIMEOUT = 60
117
118
119if __name__ == "__main__":
120    tc = TCDemo()
121    tc.start()

执行模块

用例执行器类CaseRuner

class testbot.testengine.caserunner.CaseRunner[source]

Bases: object

测试用例执行器

load_resource(file_name: str, username: str)[source]

加载测试资源

Parameters:
  • file_name (str) – 资源文件路径

  • username (str) – 资源拥有者

Returns:

Return type:

load_test(test_name: str)[source]

实例化测试用例

Parameters:

test_name (str) – 测试名称

Returns:

Return type:

print_module_info()[source]
property resource_ready[source]

资源是否已准备好

Returns:

Return type:

run_case_lcm(test: testbot.case.base.TestCaseBase, node: testbot.result.testreporter.CaseEntry)[source]

执行测试用例生命周期管理 这个方法应该在子线程被运行

set_test_list(test_list: testbot.testengine.testlist.TestList)[source]

#装载测试列表

start()[source]

测试引擎开始执行

property test_list_ready[source]

测试用例列表是否已准备好

Returns:

Return type:

wait_for_test_done()[source]

等待测试完成

Returns:

Return type:

执行测试

下面命令时执行一次测试任务,参数-t指定了要执行的测试用例列表,参数-r指定了测试资源配置文件,参数-u指定了该测试资源只允许哪个用户使用。

python -m testbot.runner.start -t .\src\testbot\example\TCList.json -r .\src\testbot\example\ResourcePool.json -u dechen

执行结果如下:

  1[2024-12-04 14:25:09,585][INFO][CaseRunner][tatf.testengine.caserunner.__init__  :+78][pid|tid:48832|34832]:执行器装载完毕
  2[2024-12-04 14:25:09,587][INFO][Resource  ][tatf.resource.pool.load      :+140][pid|tid:48832|34832]:Entering ResourcePool.load...
  3[2024-12-04 14:25:09,589][INFO][Resource  ][tatf.resource.resource.__init__  :+167][pid|tid:48832|34832]:Initialize Device...
  4[2024-12-04 14:25:09,590][INFO][Resource  ][tatf.resource.resource.__init__  :+167][pid|tid:48832|34832]:Initialize Device...
  5[2024-12-04 14:25:09,590][INFO][Resource  ][tatf.resource.pool.load      :+174][pid|tid:48832|34832]:Exiting ResourcePool.load...
  6[2024-12-04 14:25:09,590][INFO][CaseRunner][tatf.testengine.caserunner.load_resource:+113][pid|tid:48832|34832]:测试资源装载完毕
  7[2024-12-04 14:25:09,592][INFO][CaseRunner][tatf.testengine.caserunner.load_test :+148][pid|tid:48832|34832]:正在加载用例模块: tatf.example.TCDemo...
  8[2024-12-04 14:25:09,592][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+158][pid|tid:48832|34832]:################################################################################
  9[2024-12-04 14:25:09,605][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf模块 【Version】:2024.49.2.dev19,【概要】:TATF测试框架,分支名称:,提交ID:,【安装路径】:tatf 2024.49.2.dev19 ##############
 10C:\Python38\lib\site-packages\pkginfo\installed.py:62: UserWarning: No PKG-INFO found for package: tatf_aw
 11  warnings.warn('No PKG-INFO found for package: %s' % self.package_name)
 12C:\Python38\lib\site-packages\pkginfo\distribution.py:178: UnknownMetadataVersion: Unknown metadata version: None
 13  warnings.warn(UnknownMetadataVersion(self.metadata_version))
 14[2024-12-04 14:25:10,019][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf_aw模块 【Version】:None,【概要】:None,【安装路径】:None ##############
 15C:\Python38\lib\site-packages\pkginfo\installed.py:62: UserWarning: No PKG-INFO found for package: tatf_scripts
 16  warnings.warn('No PKG-INFO found for package: %s' % self.package_name)
 17[2024-12-04 14:25:10,432][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf_scripts模块 【Version】:None,【概要】:None,【安装路径】:None ##############
 18C:\Python38\lib\site-packages\pkginfo\installed.py:62: UserWarning: No PKG-INFO found for package: tatf_tools
 19  warnings.warn('No PKG-INFO found for package: %s' % self.package_name)
 20[2024-12-04 14:25:10,845][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf_tools模块 【Version】:None,【概要】:None,【安装路径】:None ##############
 21[2024-12-04 14:25:10,845][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+174][pid|tid:48832|34832]:################################################################################
 22[2024-12-04 14:25:10,859][INFO][CaseRunner][tatf.testengine.caserunner.set_test_list:+186][pid|tid:48832|34832]:测试列表装载完毕
 23[2024-12-04 14:25:10,868][INFO][TCDemo    ][tatf.case.precondition.is_meet   :+37][pid|tid:48832|45808]:测试用例的类型必须是COMMON_TEST
 24[2024-12-04 14:25:10,868][INFO][CaseRunner][tatf.testengine.caserunner.__run_case:+319][pid|tid:48832|45808]:self.resource_pool={'M70JP90W': <tatf.resource.resource.Device object at 0x0000027F023B7940>, '5C0AD0760BB0C50AD': <tatf.resource.resource.Device object at 0x0000027F023887F0>}
 25[2024-12-04 14:25:10,872][INFO][CaseRunner][tatf.example.TCDemo.setup     :+60][pid|tid:48832|45808]:case_setting1=setting1, case_setting2=10, TIMEOUT=60
 26[2024-12-04 14:25:10,874][INFO][CaseRunner][tatf.testengine.caserunner.__run_case:+349][pid|tid:48832|45808]:执行次数:3
 27[2024-12-04 14:25:10,878][INFO][Resource  ][tatf.resource.modules.device_module.power_off :+53][pid|tid:48832|45808]:给设备断电
 28[2024-12-04 14:25:10,879][INFO][Resource  ][tatf.resource.modules.device_module.power_on  :+43][pid|tid:48832|45808]:给设备上电
 29[2024-12-04 14:25:10,885][INFO][Resource  ][tatf.resource.modules.device_module.power_off :+53][pid|tid:48832|45808]:给设备断电
 30[2024-12-04 14:25:10,886][INFO][Resource  ][tatf.resource.modules.device_module.power_on  :+43][pid|tid:48832|45808]:给设备上电
 31[2024-12-04 14:25:10,892][INFO][Resource  ][tatf.resource.modules.device_module.power_off :+53][pid|tid:48832|45808]:给设备断电
 32[2024-12-04 14:25:10,896][INFO][Resource  ][tatf.resource.modules.device_module.power_on  :+43][pid|tid:48832|45808]:给设备上电
 33<测试节点> 【步骤】:Root,【失败描述】:<测试节点> 【步骤】:测试套件,【失败描述】:        <测试用例> 【步骤】:TCDemo,【失败描述】:------------------------------------------------------------------PASSED
 34<测试节点> 【步骤】:执行测试,【失败描述】:        <测试用例> 【步骤】:执行测试,【失败描述】:--------------------------------------------------------------------PASSED
 35            <测试步骤-1> 【步骤】:执行用例,【失败描述】:INFO: TCDemo--------------------------------------------------PASSED
 36                <筛选资源-1> 【步骤】:收集测试资源,【失败描述】:--------------------------------------------------------PASSED
 37                    <测试步骤-1> 【步骤】:筛选设备,【失败描述】:------------------------------------------------------PASSED
 38                        <测试步骤-1> 【步骤】:筛选PC设备,【失败描述】:筛选PC设备成功----------------------------------------PASSED
 39                        <测试步骤-2> 【步骤】:筛选TV设备,【失败描述】:筛选TV设备成功----------------------------------------PASSED
 40                <前提条件-2> 【步骤】:初始化前置条件,【失败描述】:-------------------------------------------------------PASSED
 41                    <测试步骤-1> 【步骤】:,【失败描述】:设置STR为ON--------------------------------------------------PASSED
 42                    <测试步骤-2> 【步骤】:,【失败描述】:设置STR为ON--------------------------------------------------PASSED
 43                    <测试步骤-3> 【步骤】:,【失败描述】:设置待机时长----------------------------------------------------PASSED
 44                    <测试步骤-4> 【步骤】:,【失败描述】:INFO: 安装WIFI apk------------------------------------------PASSED
 45                    <测试步骤-5> 【步骤】:,【失败描述】:断开有线连接断开有线连接----------------------------------------------PASSED
 46                    <测试步骤-6> 【步骤】:,【失败描述】:连接并检查WIFI热点-----------------------------------------------PASSED
 47                <测试主体-3> 【步骤】:执行测试主体,【失败描述】:--------------------------------------------------------PASSED
 48                    <测试步骤-1> 【步骤】:执行测试主体第0次,【失败描述】:-------------------------------------------------PASSED
 49                        <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频---------------------------------------PASSED
 50                        <测试步骤-2> 【步骤】:,【失败描述】:按power键进入待机状态-----------------------------------------PASSED
 51                        <测试步骤-3> 【步骤】:,【失败描述】:等待5秒后,按power键唤醒电视-------------------------------------PASSED
 52                        <测试步骤-4> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 53                        <测试步骤-5> 【步骤】:,【失败描述】:开机后进入在线视频---------------------------------------------PASSED
 54                        <测试步骤-6> 【步骤】:,【失败描述】:给电视断电-------------------------------------------------PASSED
 55                        <测试步骤-7> 【步骤】:,【失败描述】:给电视上电-------------------------------------------------PASSED
 56                        <测试步骤-8> 【步骤】:,【失败描述】:等待30秒后,按power键唤醒电视------------------------------------PASSED
 57                        <测试步骤-9> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 58                        <测试步骤-10> 【步骤】:,【失败描述】:开机后进入Launcher页面--------------------------------------PASSED
 59                            <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频-----------------------------------PASSED
 60                    <测试步骤-2> 【步骤】:执行测试主体第1次,【失败描述】:-------------------------------------------------PASSED
 61                        <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频---------------------------------------PASSED
 62                        <测试步骤-2> 【步骤】:,【失败描述】:按power键进入待机状态-----------------------------------------PASSED
 63                        <测试步骤-3> 【步骤】:,【失败描述】:等待5秒后,按power键唤醒电视-------------------------------------PASSED
 64                        <测试步骤-4> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 65                        <测试步骤-5> 【步骤】:,【失败描述】:开机后进入在线视频---------------------------------------------PASSED
 66                        <测试步骤-6> 【步骤】:,【失败描述】:给电视断电-------------------------------------------------PASSED
 67                        <测试步骤-7> 【步骤】:,【失败描述】:给电视上电-------------------------------------------------PASSED
 68                        <测试步骤-8> 【步骤】:,【失败描述】:等待30秒后,按power键唤醒电视------------------------------------PASSED
 69                        <测试步骤-9> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 70                        <测试步骤-10> 【步骤】:,【失败描述】:开机后进入Launcher页面--------------------------------------PASSED
 71                            <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频-----------------------------------PASSED
 72                    <测试步骤-3> 【步骤】:执行测试主体第2次,【失败描述】:-------------------------------------------------PASSED
 73                        <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频---------------------------------------PASSED
 74                        <测试步骤-2> 【步骤】:,【失败描述】:按power键进入待机状态-----------------------------------------PASSED
 75                        <测试步骤-3> 【步骤】:,【失败描述】:等待5秒后,按power键唤醒电视-------------------------------------PASSED
 76                        <测试步骤-4> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 77                        <测试步骤-5> 【步骤】:,【失败描述】:开机后进入在线视频---------------------------------------------PASSED
 78                        <测试步骤-6> 【步骤】:,【失败描述】:给电视断电-------------------------------------------------PASSED
 79                        <测试步骤-7> 【步骤】:,【失败描述】:给电视上电-------------------------------------------------PASSED
 80                        <测试步骤-8> 【步骤】:,【失败描述】:等待30秒后,按power键唤醒电视------------------------------------PASSED
 81                        <测试步骤-9> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 82                        <测试步骤-10> 【步骤】:,【失败描述】:开机后进入Launcher页面--------------------------------------PASSED
 83                            <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频-----------------------------------PASSED
 84                <后置清理-4> 【步骤】:清理后置条件,【失败描述】:--------------------------------------------------------PASSED
 85                    <测试步骤-1> 【步骤】:,【失败描述】:断开WIFI热点--------------------------------------------------PASSED
 86                    <测试步骤-2> 【步骤】:,【失败描述】:关闭WIFI开关--------------------------------------------------PASSED
 87
 88{"headline": "Root", "message": "", "timestamp": "2024-12-04 14:25:09", "children": [{"headline": "\u6d4b\u8bd5\u5957\u4ef6", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "TCDemo", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed"}]}, {"headline":
 89 "\u6267\u884c\u6d4b\u8bd5", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u6267\u884c\u6d4b\u8bd5", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u6267\u884c\u7528\u4f8b", "message": "INFO: TCDemo", "timestamp": "2024-12-04 14:25:10", "children": [
 90{"headline": "\u6536\u96c6\u6d4b\u8bd5\u8d44\u6e90", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u7b5b\u9009\u8bbe\u5907", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u7b5b\u9009PC\u8bbe\u5907", "message": "\u7b5b\u9009PC\u8bbe\u5907\u6210\u529f
 91", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "1-"}, {"headline": "\u7b5b\u9009TV\u8bbe\u5907", "message": "\u7b5b\u9009TV\u8bbe\u5907\u6210\u529f", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "1-"}], "result": "Passed", "prefix": ""}], "
 92result": "Passed", "prefix": "COLLECT_RESOURCE"}, {"headline": "\u521d\u59cb\u5316\u524d\u7f6e\u6761\u4ef6", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u8bbe\u7f6eSTR\u4e3aON", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""},
 93{"headline": "", "message": "\u8bbe\u7f6eSTR\u4e3aON", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "message": "\u8bbe\u7f6e\u5f85\u673a\u65f6\u957f", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "
 94message": "INFO: \u5b89\u88c5WIFI apk", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "message": "\u65ad\u5f00\u6709\u7ebf\u8fde\u63a5\u65ad\u5f00\u6709\u7ebf\u8fde\u63a5", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""
 95}, {"headline": "", "message": "\u8fde\u63a5\u5e76\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}], "result": "Passed", "prefix": "SETUP"}, {"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53", "message": "", "timestamp": "2024-12-04 14:25:10", "c
 96hildren": [{"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53\u7b2c0\u6b21", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST
 97-01-"}, {"headline": "", "message": "\u6309power\u952e\u8fdb\u5165\u5f85\u673a\u72b6\u6001", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7b49\u5f855\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-0
 984 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165\u5728\u7eb
 99f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u65ad\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6
100\u4e0a\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7b49\u5f8530\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"hea
101dline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165Launcher\u9875\u9762", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "",
102 "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-10-"}], "result": "Passed", "prefix": "TEST-01-"}], "result": "Passed", "prefix": "TEST-0"}, {"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53\u7b2c1\u6
103b21", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u6309power\u952e\u8fdb\u5165\u5f8
1045\u673a\u72b6\u6001", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7b49\u5f855\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"},
105 {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165\u5728\u7ebf\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "re
106sult": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u65ad\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u4e0a\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "res
107ult": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7b49\u5f8530\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9"
108, "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165Launcher\u9875\u9762", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891",
109"timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-10-"}], "result": "Passed", "prefix": "TEST-12-"}], "result": "Passed", "prefix": "TEST-1"}, {"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53\u7b2c2\u6b21", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{
110"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u6309power\u952e\u8fdb\u5165\u5f85\u673a\u72b6\u6001", "timestamp": "2024-12-04 14:25:10", "children": [
111], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u7b49\u5f855\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\
112u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165\u5728\u7ebf\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u
1137ed9\u7535\u89c6\u65ad\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u4e0a\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u7
114b49\u5f8530\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed
115", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165Launcher\u9875\u9762", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed",
116 "prefix": "TEST-23-10-"}], "result": "Passed", "prefix": "TEST-23-"}], "result": "Passed", "prefix": "TEST-2"}], "result": "Passed", "prefix": "TEST"}, {"headline": "\u6e05\u7406\u540e\u7f6e\u6761\u4ef6", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u65ad\u5f00WIFI
117\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "message": "\u5173\u95edWIFI\u5f00\u5173", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}], "result": "Passed", "prefix": "CLEANUP"}], "result": "Passed", "p
118refix": "RUNCASE"}], "result": "Passed"}]}]}

结果模块

日志管理器类LoggerManager

class testbot.result.logger.LoggerManager[source]

Bases: object

日志管理器,可注册多个日志对象,支持模块日志和用例日志分离。

get_logger(logger_name: str)[source]

获取日志对象 :param logger_name: 日志名称 :type logger_name: str :return: 日志对象 :rtype: logging.Logger

register(logger_name: str, filename: str = None, console: bool = True, default_level: str = logging.INFO, **kwargs)[source]

注册logger。 for_test参数默认False,开启则支持模块日志;is_test参数默认False,开启则支持用例日志。

Parameters:
  • logger_name (str) – 日志名称

  • filename (str) – 文件名称

  • console (bool) – 是否控制台输出

  • default_level (str) – 默认日志级别

  • kwargs

Returns:

创建或已注册的日志Logger对象

Return type:

logging.Logger

unregister(logger_name: str)[source]

删除注册的logger,同时将需要打包的logger文件打包

Parameters:

logger_name (str) – 日志名称

Returns:

Return type:

创建日志类对象

模块tbot.result.logger对外共享一个日志管理器对象logger_manager,方便各个模块和用例使用它来注册各自的日志对象。

下面是一个例子,介绍了如何创建一个Resource模块和用例的日志对象,用于各自的日志输出:

 1#!/usr/bin/env python
 2# -*- coding: utf-8 -*-
 3
 4__copyright__ = "Copyright (c) 2024 Nuanguang Gu(Sunny) Reserved"
 5__author__ = "Nuanguang Gu(Sunny)"
 6__email__ = "nuanguang.gu@aliyun.com"
 7
 8import os
 9from pathlib import Path
10from tbot.result.logger import logger_manager
11
12
13if __name__ == "__main__":
14    RESOURCE_LOGGER_FILENAME = os.path.join(str(Path.home()), "TBOT", "logs", "Resource.log")
15    TC_LOGGER_FILENAME = os.path.join(str(Path.home()), "TBOT", "logs", "TestCase.log")
16
17    # 注册Resource模块日志对象
18    resource_module_logger = logger_manager.register(logger_name="Resource", filename=RESOURCE_LOGGER_FILENAME, for_test=True)
19    # 注册用例对象
20    tc_logger = logger_manager.register(logger_name="TestCase", filename=TC_LOGGER_FILENAME, is_test=True)
21
22    # Resource模块日志打印信息
23    resource_module_logger.info("这是Resource模块日志")
24    # 用例日志打印信息
25    tc_logger.info("这是用例日志")
26
27    # 在用例执行结束后,去注册用例日志
28    logger_manager.unregister("TestCase")
29

日志目录和日志内容如下。您会发现,模块Resource日志对象的日志信息,除了保存到模块日志文件Resource.log,还保存到用例日志文件TestCase.log。

_images/logger_info.png

日志文件目录

默认情况下,模块配置文件将会保存到目录~/TESTBOT/logs。

C:\USERS\NUANGUANG.GU\TESTBOT
├───configs
│       CaseRunnerSetting.json
│       ModuleSetting.json
│       ResourcePool.json
│       ResourceSetting.json
│
└───logs
    ├───cases
    │   └───20240905180219
    │       └───A Demo Test List
    │               TCDemo.log
    │
    ├───modules
    │       Resource.log
    │
    └───runner
            CaseRunner.log

结构化步骤信息

  1[2024-12-04 14:25:09,585][INFO][CaseRunner][tatf.testengine.caserunner.__init__  :+78][pid|tid:48832|34832]:执行器装载完毕
  2[2024-12-04 14:25:09,587][INFO][Resource  ][tatf.resource.pool.load      :+140][pid|tid:48832|34832]:Entering ResourcePool.load...
  3[2024-12-04 14:25:09,589][INFO][Resource  ][tatf.resource.resource.__init__  :+167][pid|tid:48832|34832]:Initialize Device...
  4[2024-12-04 14:25:09,590][INFO][Resource  ][tatf.resource.resource.__init__  :+167][pid|tid:48832|34832]:Initialize Device...
  5[2024-12-04 14:25:09,590][INFO][Resource  ][tatf.resource.pool.load      :+174][pid|tid:48832|34832]:Exiting ResourcePool.load...
  6[2024-12-04 14:25:09,590][INFO][CaseRunner][tatf.testengine.caserunner.load_resource:+113][pid|tid:48832|34832]:测试资源装载完毕
  7[2024-12-04 14:25:09,592][INFO][CaseRunner][tatf.testengine.caserunner.load_test :+148][pid|tid:48832|34832]:正在加载用例模块: tatf.example.TCDemo...
  8[2024-12-04 14:25:09,592][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+158][pid|tid:48832|34832]:################################################################################
  9[2024-12-04 14:25:09,605][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf模块 【Version】:2024.49.2.dev19,【概要】:TATF测试框架,分支名称:,提交ID:,【安装路径】:tatf 2024.49.2.dev19 ##############
 10C:\Python38\lib\site-packages\pkginfo\installed.py:62: UserWarning: No PKG-INFO found for package: tatf_aw
 11  warnings.warn('No PKG-INFO found for package: %s' % self.package_name)
 12C:\Python38\lib\site-packages\pkginfo\distribution.py:178: UnknownMetadataVersion: Unknown metadata version: None
 13  warnings.warn(UnknownMetadataVersion(self.metadata_version))
 14[2024-12-04 14:25:10,019][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf_aw模块 【Version】:None,【概要】:None,【安装路径】:None ##############
 15C:\Python38\lib\site-packages\pkginfo\installed.py:62: UserWarning: No PKG-INFO found for package: tatf_scripts
 16  warnings.warn('No PKG-INFO found for package: %s' % self.package_name)
 17[2024-12-04 14:25:10,432][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf_scripts模块 【Version】:None,【概要】:None,【安装路径】:None ##############
 18C:\Python38\lib\site-packages\pkginfo\installed.py:62: UserWarning: No PKG-INFO found for package: tatf_tools
 19  warnings.warn('No PKG-INFO found for package: %s' % self.package_name)
 20[2024-12-04 14:25:10,845][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+173][pid|tid:48832|34832]:############## tatf_tools模块 【Version】:None,【概要】:None,【安装路径】:None ##############
 21[2024-12-04 14:25:10,845][INFO][CaseRunner][tatf.testengine.caserunner.print_module_info:+174][pid|tid:48832|34832]:################################################################################
 22[2024-12-04 14:25:10,859][INFO][CaseRunner][tatf.testengine.caserunner.set_test_list:+186][pid|tid:48832|34832]:测试列表装载完毕
 23[2024-12-04 14:25:10,868][INFO][TCDemo    ][tatf.case.precondition.is_meet   :+37][pid|tid:48832|45808]:测试用例的类型必须是COMMON_TEST
 24[2024-12-04 14:25:10,868][INFO][CaseRunner][tatf.testengine.caserunner.__run_case:+319][pid|tid:48832|45808]:self.resource_pool={'M70JP90W': <tatf.resource.resource.Device object at 0x0000027F023B7940>, '5C0AD0760BB0C50AD': <tatf.resource.resource.Device object at 0x0000027F023887F0>}
 25[2024-12-04 14:25:10,872][INFO][CaseRunner][tatf.example.TCDemo.setup     :+60][pid|tid:48832|45808]:case_setting1=setting1, case_setting2=10, TIMEOUT=60
 26[2024-12-04 14:25:10,874][INFO][CaseRunner][tatf.testengine.caserunner.__run_case:+349][pid|tid:48832|45808]:执行次数:3
 27[2024-12-04 14:25:10,878][INFO][Resource  ][tatf.resource.modules.device_module.power_off :+53][pid|tid:48832|45808]:给设备断电
 28[2024-12-04 14:25:10,879][INFO][Resource  ][tatf.resource.modules.device_module.power_on  :+43][pid|tid:48832|45808]:给设备上电
 29[2024-12-04 14:25:10,885][INFO][Resource  ][tatf.resource.modules.device_module.power_off :+53][pid|tid:48832|45808]:给设备断电
 30[2024-12-04 14:25:10,886][INFO][Resource  ][tatf.resource.modules.device_module.power_on  :+43][pid|tid:48832|45808]:给设备上电
 31[2024-12-04 14:25:10,892][INFO][Resource  ][tatf.resource.modules.device_module.power_off :+53][pid|tid:48832|45808]:给设备断电
 32[2024-12-04 14:25:10,896][INFO][Resource  ][tatf.resource.modules.device_module.power_on  :+43][pid|tid:48832|45808]:给设备上电
 33<测试节点> 【步骤】:Root,【失败描述】:<测试节点> 【步骤】:测试套件,【失败描述】:        <测试用例> 【步骤】:TCDemo,【失败描述】:------------------------------------------------------------------PASSED
 34<测试节点> 【步骤】:执行测试,【失败描述】:        <测试用例> 【步骤】:执行测试,【失败描述】:--------------------------------------------------------------------PASSED
 35            <测试步骤-1> 【步骤】:执行用例,【失败描述】:INFO: TCDemo--------------------------------------------------PASSED
 36                <筛选资源-1> 【步骤】:收集测试资源,【失败描述】:--------------------------------------------------------PASSED
 37                    <测试步骤-1> 【步骤】:筛选设备,【失败描述】:------------------------------------------------------PASSED
 38                        <测试步骤-1> 【步骤】:筛选PC设备,【失败描述】:筛选PC设备成功----------------------------------------PASSED
 39                        <测试步骤-2> 【步骤】:筛选TV设备,【失败描述】:筛选TV设备成功----------------------------------------PASSED
 40                <前提条件-2> 【步骤】:初始化前置条件,【失败描述】:-------------------------------------------------------PASSED
 41                    <测试步骤-1> 【步骤】:,【失败描述】:设置STR为ON--------------------------------------------------PASSED
 42                    <测试步骤-2> 【步骤】:,【失败描述】:设置STR为ON--------------------------------------------------PASSED
 43                    <测试步骤-3> 【步骤】:,【失败描述】:设置待机时长----------------------------------------------------PASSED
 44                    <测试步骤-4> 【步骤】:,【失败描述】:INFO: 安装WIFI apk------------------------------------------PASSED
 45                    <测试步骤-5> 【步骤】:,【失败描述】:断开有线连接断开有线连接----------------------------------------------PASSED
 46                    <测试步骤-6> 【步骤】:,【失败描述】:连接并检查WIFI热点-----------------------------------------------PASSED
 47                <测试主体-3> 【步骤】:执行测试主体,【失败描述】:--------------------------------------------------------PASSED
 48                    <测试步骤-1> 【步骤】:执行测试主体第0次,【失败描述】:-------------------------------------------------PASSED
 49                        <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频---------------------------------------PASSED
 50                        <测试步骤-2> 【步骤】:,【失败描述】:按power键进入待机状态-----------------------------------------PASSED
 51                        <测试步骤-3> 【步骤】:,【失败描述】:等待5秒后,按power键唤醒电视-------------------------------------PASSED
 52                        <测试步骤-4> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 53                        <测试步骤-5> 【步骤】:,【失败描述】:开机后进入在线视频---------------------------------------------PASSED
 54                        <测试步骤-6> 【步骤】:,【失败描述】:给电视断电-------------------------------------------------PASSED
 55                        <测试步骤-7> 【步骤】:,【失败描述】:给电视上电-------------------------------------------------PASSED
 56                        <测试步骤-8> 【步骤】:,【失败描述】:等待30秒后,按power键唤醒电视------------------------------------PASSED
 57                        <测试步骤-9> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 58                        <测试步骤-10> 【步骤】:,【失败描述】:开机后进入Launcher页面--------------------------------------PASSED
 59                            <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频-----------------------------------PASSED
 60                    <测试步骤-2> 【步骤】:执行测试主体第1次,【失败描述】:-------------------------------------------------PASSED
 61                        <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频---------------------------------------PASSED
 62                        <测试步骤-2> 【步骤】:,【失败描述】:按power键进入待机状态-----------------------------------------PASSED
 63                        <测试步骤-3> 【步骤】:,【失败描述】:等待5秒后,按power键唤醒电视-------------------------------------PASSED
 64                        <测试步骤-4> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 65                        <测试步骤-5> 【步骤】:,【失败描述】:开机后进入在线视频---------------------------------------------PASSED
 66                        <测试步骤-6> 【步骤】:,【失败描述】:给电视断电-------------------------------------------------PASSED
 67                        <测试步骤-7> 【步骤】:,【失败描述】:给电视上电-------------------------------------------------PASSED
 68                        <测试步骤-8> 【步骤】:,【失败描述】:等待30秒后,按power键唤醒电视------------------------------------PASSED
 69                        <测试步骤-9> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 70                        <测试步骤-10> 【步骤】:,【失败描述】:开机后进入Launcher页面--------------------------------------PASSED
 71                            <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频-----------------------------------PASSED
 72                    <测试步骤-3> 【步骤】:执行测试主体第2次,【失败描述】:-------------------------------------------------PASSED
 73                        <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频---------------------------------------PASSED
 74                        <测试步骤-2> 【步骤】:,【失败描述】:按power键进入待机状态-----------------------------------------PASSED
 75                        <测试步骤-3> 【步骤】:,【失败描述】:等待5秒后,按power键唤醒电视-------------------------------------PASSED
 76                        <测试步骤-4> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 77                        <测试步骤-5> 【步骤】:,【失败描述】:开机后进入在线视频---------------------------------------------PASSED
 78                        <测试步骤-6> 【步骤】:,【失败描述】:给电视断电-------------------------------------------------PASSED
 79                        <测试步骤-7> 【步骤】:,【失败描述】:给电视上电-------------------------------------------------PASSED
 80                        <测试步骤-8> 【步骤】:,【失败描述】:等待30秒后,按power键唤醒电视------------------------------------PASSED
 81                        <测试步骤-9> 【步骤】:,【失败描述】:开机后检查WIFI热点-------------------------------------------PASSED
 82                        <测试步骤-10> 【步骤】:,【失败描述】:开机后进入Launcher页面--------------------------------------PASSED
 83                            <测试步骤-1> 【步骤】:,【失败描述】:打开Youtube播放任意视频-----------------------------------PASSED
 84                <后置清理-4> 【步骤】:清理后置条件,【失败描述】:--------------------------------------------------------PASSED
 85                    <测试步骤-1> 【步骤】:,【失败描述】:断开WIFI热点--------------------------------------------------PASSED
 86                    <测试步骤-2> 【步骤】:,【失败描述】:关闭WIFI开关--------------------------------------------------PASSED
 87
 88{"headline": "Root", "message": "", "timestamp": "2024-12-04 14:25:09", "children": [{"headline": "\u6d4b\u8bd5\u5957\u4ef6", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "TCDemo", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed"}]}, {"headline":
 89 "\u6267\u884c\u6d4b\u8bd5", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u6267\u884c\u6d4b\u8bd5", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u6267\u884c\u7528\u4f8b", "message": "INFO: TCDemo", "timestamp": "2024-12-04 14:25:10", "children": [
 90{"headline": "\u6536\u96c6\u6d4b\u8bd5\u8d44\u6e90", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u7b5b\u9009\u8bbe\u5907", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "\u7b5b\u9009PC\u8bbe\u5907", "message": "\u7b5b\u9009PC\u8bbe\u5907\u6210\u529f
 91", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "1-"}, {"headline": "\u7b5b\u9009TV\u8bbe\u5907", "message": "\u7b5b\u9009TV\u8bbe\u5907\u6210\u529f", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "1-"}], "result": "Passed", "prefix": ""}], "
 92result": "Passed", "prefix": "COLLECT_RESOURCE"}, {"headline": "\u521d\u59cb\u5316\u524d\u7f6e\u6761\u4ef6", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u8bbe\u7f6eSTR\u4e3aON", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""},
 93{"headline": "", "message": "\u8bbe\u7f6eSTR\u4e3aON", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "message": "\u8bbe\u7f6e\u5f85\u673a\u65f6\u957f", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "
 94message": "INFO: \u5b89\u88c5WIFI apk", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "message": "\u65ad\u5f00\u6709\u7ebf\u8fde\u63a5\u65ad\u5f00\u6709\u7ebf\u8fde\u63a5", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""
 95}, {"headline": "", "message": "\u8fde\u63a5\u5e76\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}], "result": "Passed", "prefix": "SETUP"}, {"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53", "message": "", "timestamp": "2024-12-04 14:25:10", "c
 96hildren": [{"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53\u7b2c0\u6b21", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST
 97-01-"}, {"headline": "", "message": "\u6309power\u952e\u8fdb\u5165\u5f85\u673a\u72b6\u6001", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7b49\u5f855\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-0
 984 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165\u5728\u7eb
 99f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u65ad\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6
100\u4e0a\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u7b49\u5f8530\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"hea
101dline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165Launcher\u9875\u9762", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "",
102 "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-01-10-"}], "result": "Passed", "prefix": "TEST-01-"}], "result": "Passed", "prefix": "TEST-0"}, {"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53\u7b2c1\u6
103b21", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u6309power\u952e\u8fdb\u5165\u5f8
1045\u673a\u72b6\u6001", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7b49\u5f855\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"},
105 {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165\u5728\u7ebf\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "re
106sult": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u65ad\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u4e0a\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "res
107ult": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u7b49\u5f8530\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9"
108, "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165Launcher\u9875\u9762", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891",
109"timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-12-10-"}], "result": "Passed", "prefix": "TEST-12-"}], "result": "Passed", "prefix": "TEST-1"}, {"headline": "\u6267\u884c\u6d4b\u8bd5\u4e3b\u4f53\u7b2c2\u6b21", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{
110"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u6309power\u952e\u8fdb\u5165\u5f85\u673a\u72b6\u6001", "timestamp": "2024-12-04 14:25:10", "children": [
111], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u7b49\u5f855\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\
112u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165\u5728\u7ebf\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u
1137ed9\u7535\u89c6\u65ad\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u7ed9\u7535\u89c6\u4e0a\u7535", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u7
114b49\u5f8530\u79d2\u540e\uff0c\u6309power\u952e\u5524\u9192\u7535\u89c6", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u68c0\u67e5WIFI\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed
115", "prefix": "TEST-23-"}, {"headline": "", "message": "\u5f00\u673a\u540e\u8fdb\u5165Launcher\u9875\u9762", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u6253\u5f00Youtube\u64ad\u653e\u4efb\u610f\u89c6\u9891", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed",
116 "prefix": "TEST-23-10-"}], "result": "Passed", "prefix": "TEST-23-"}], "result": "Passed", "prefix": "TEST-2"}], "result": "Passed", "prefix": "TEST"}, {"headline": "\u6e05\u7406\u540e\u7f6e\u6761\u4ef6", "message": "", "timestamp": "2024-12-04 14:25:10", "children": [{"headline": "", "message": "\u65ad\u5f00WIFI
117\u70ed\u70b9", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}, {"headline": "", "message": "\u5173\u95edWIFI\u5f00\u5173", "timestamp": "2024-12-04 14:25:10", "children": [], "result": "Passed", "prefix": ""}], "result": "Passed", "prefix": "CLEANUP"}], "result": "Passed", "p
118refix": "RUNCASE"}], "result": "Passed"}]}]}