本页介绍如何在 Tradefed 中编写新的测试运行程序。
背景
如果您对 Tradefed 架构中测试运行器的位置感到好奇,请参阅测试运行器的结构。
这不是编写新测试运行器的先决条件;测试运行器可以单独编写。
最低限度:实现接口
成为 Tradefed 测试运行程序的最低要求是实现IRemoteTest 接口,更具体地说是实现run(TestInformation testInfo, ITestInvocationListener listener)
方法。
此方法是在使用测试运行器时由工具调用的方法,类似于 Java Runnable。
该方法的每个部分都被视为测试运行程序执行的一部分。
从测试运行器报告结果
基本接口中的run
方法可以访问ITestInvocationListener
类型的侦听器对象。该对象是将结构化结果从测试运行器报告给工具的关键。
通过报告结构化结果,测试运行器具有以下属性:
- 报告所有运行的测试的正确列表,它们花费了多长时间以及它们是否单独通过、失败或其他一些状态。
- 报告与测试相关的指标(如果适用),例如安装时间指标。
- 适合大多数基础设施工具,例如显示结果和指标等。
- 通常更容易调试,因为有更精细的执行跟踪。
也就是说,报告结构化结果是可选的;测试运行者可能只是想将整个运行的状态评估为 PASSED 或 FAILED,而不需要任何实际执行的细节。
注意:实现遵循事件顺序的运行器更加困难,但鉴于上面列出的好处,我们建议您这样做。
可以在侦听器上调用以下事件来通知工具当前执行进度:
- testRunStarted:通知一组相关联的测试用例的开始。
- testStarted:通知一个测试用例开始的开始。
- testFailed/testIgnored:通知正在进行的测试用例的状态变化。没有任何状态变化的测试用例被认为是通过的。
- testEnded:通知测试用例结束。
- testRunFailed:通知该组测试用例执行的整体状态为失败。测试运行可以是通过或失败,独立于测试用例结果,具体取决于执行的预期。例如,运行多个测试用例的二进制文件可能会报告所有通过测试用例但带有错误退出代码(出于任何原因:文件泄露等)。
- testRunEnded:通知测试用例组结束。
维护和确保回调的正确顺序是测试运行器实现者的责任,例如确保使用finally
子句在异常情况下调用testRunEnded
。
测试用例回调( testStarted
、 testEnded
等)是可选的。可能会在没有任何测试用例的情况下进行测试运行。
您可能会注意到这种事件结构的灵感来自典型的 JUnit 结构。这是为了使事情接近开发人员通常了解的基本知识。
来自测试运行器的报告日志
如果您正在编写自己的 Tradefed 测试类或运行程序,您将实现IRemoteTest并通过run()
方法获取ITestInvocationListener
。此侦听器可用于记录文件,如下所示:
listener.testLog(String dataName, LogDataType type_of_data, InputStreamSource data);
使用设备进行测试
上面的最小接口允许运行非常简单的独立测试,不需要任何特定资源,例如 Java 单元测试。
想要进行下一步设备测试的测试编写者将需要以下接口:
- IDeviceTest允许接收代表被测设备的
ITestDevice
对象并提供与之交互的 API。 - IBuildReceiver允许测试获取在构建提供程序步骤创建的
IBuildInfo
对象,其中包含与测试设置相关的所有信息和工件。
测试运行者通常对这些接口感兴趣,以便获取与执行相关的工件,例如额外的文件,并获取将在执行期间作为目标的被测设备。
使用多个设备进行测试
Tradefed 支持同时在多个设备上运行测试。这在测试需要外部交互的组件时非常有用,例如手机和手表配对。
为了编写可以使用多个设备的测试运行器,您需要实现IMultiDeviceTest ,这将允许接收ITestDevice
到IBuildInfo
的映射,其中包含设备表示的完整列表及其相关的构建信息。
接口中的 setter 总是在run
方法之前被调用,因此可以安全地假设该结构在调用run
时可用。
测试知道他们的设置
注意:这不是一个非常常见的用例。为了完整起见,它已记录在案,但您通常不需要它。
一些测试运行器实现可能需要有关整体设置的信息才能正常工作,例如有关调用的一些元数据,或者之前运行的target_preparer
等。
为了实现这一点,测试运行程序可以访问它所属的IConfiguration
对象,并在其中执行它。有关更多详细信息,请参阅配置对象描述。
对于测试运行器实现,您需要实现IConfigurationReceiver以接收IConfiguration
对象。
灵活的测试运行器
如果测试运行程序对它们有精细的控制,他们可以提供一种灵活的方式来运行他们的测试,例如,JUnit 测试运行程序可以单独运行每个单元测试。
这允许更大的工具和基础设施利用这种精细控制,并且用户可以通过过滤部分运行测试运行器。
ITestFilterReceiver 接口中描述了过滤支持,它允许接收应该或不应该运行的测试的include
和exclude
过滤器集。
我们的约定是,如果它匹配一个或多个包含过滤器并且不匹配任何排除过滤器,则将运行测试。如果没有给出包含过滤器,那么只要它们不匹配任何排除过滤器,就应该运行所有测试。
注意:我们鼓励以支持此过滤的方式编写测试运行程序,因为它在更大的基础架构中提供了巨大的附加值。但我们知道,在某些情况下,这是不可能的。