编写 Tradefed 测试运行程序

本页介绍如何在 Tradefed 中编写新的测试运行程序。

背景

如果您想知道 Tradefed 架构中测试运行程序的位置,请参阅测试运行程序的结构

这不是编写新测试运行程序的先决条件;可以单独编写测试运行程序。

最低要求:实现接口

若要成为 Tradefed 测试运行程序,需满足的最低要求是实现 IRemoteTest 接口,更具体地说,也就是 run(TestInformation testInfo, ITestInvocationListener listener) 方法。

这是使用测试运行程序时自动化测试框架所调用的方法,类似于 Java Runnable。

该方法的每一部分都被视为测试运行程序执行的一部分。

报告测试运行程序的结果

通过基接口中的 run 方法可以访问 ITestInvocationListener 类型的监听器对象。此对象是将测试运行程序的结构化结果报告给自动化测试框架的关键。

通过报告结构化结果,测试运行程序具有以下属性:

  • 报告运行的所有测试(给出正确的列表)、它们花费了多长时间,以及它们分别是通过、失败,还是处于其他某种状态。
  • 报告与测试关联的指标(如果适用),例如安装时间指标。
  • 适合大多数基础架构工具,例如显示结果和指标等。
  • 通常更容易调试,因为有更精细的执行跟踪记录。

不过,报告结构化结果是可选操作;测试运行程序可能只是想将整个运行的状态评估为 PASSED 或 FAILED,而不需要关于实际执行的任何细节。

可以对监听器调用以下事件,以通知自动化测试框架当前的执行进度:

  • testRunStarted:通知自动化测试框架联系在一起的一组测试用例已开始。
    • testStarted:通知自动化测试框架起始测试用例已开始。
    • testFailed/testIgnored:通知自动化测试框架正在执行的测试用例的状态发生了变化。如果某个测试用例的状态未发生任何变化,则视为通过。
    • testEnded:通知自动化测试框架相应测试用例已结束。
  • testRunFailed:通知自动化测试框架执行相应的一组测试用例的总体状态为失败。测试运行的状态可以是通过,也可以是失败,与测试用例结果无关,具体取决于预期的执行结果。例如,运行多个测试用例的二进制文件可以报告所有通过的测试用例,但有一个错误退出代码(出于任何原因:泄露文件等)。
  • testRunEnded:通知自动化测试框架相应的一组测试用例已结束。

维护和确保回调的正确顺序由测试运行程序实现者负责,例如确保在出现异常时使用 finally 子句来调用 testRunEnded

测试用例回调(testStartedtestEnded 等)是可选的。测试运行可能会在没有任何测试用例的情况下发生。

您可能会注意到,这种事件结构的灵感源自典型的 JUnit 结构。这样做是为了让相关内容接近开发者通常所了解的一些基本内容。

报告测试运行程序的日志

如果您要编写自己的 Tradefed 测试类或运行程序,那么应实现 IRemoteTest 并通过 run() 方法获取 ITestInvocationListener。此监听器可用于记录文件,如下所示:

    listener.testLog(String dataName, LogDataType type_of_data, InputStreamSource data);

使用一部设备进行测试

上面的最小接口允许运行非常简单的测试(这些测试是孤立的,且不需要任何特定资源),例如 Java 单元测试。

想要进入下一步(即设备测试)的测试编写者需要实现以下接口:

  • IDeviceTest - 允许接收代表被测设备的 ITestDevice 对象,并提供用来与之交互的 API。
  • IBuildReceiver - 允许测试获取在 build 提供程序步骤中创建的 IBuildInfo 对象,该对象包含与测试设置相关的所有信息和工件。

测试运行程序通常对这些接口感兴趣,以获取与执行相关的工件(例如额外文件),并获取将在执行期间作为目标的被测设备。

使用多部设备进行测试

Tradefed 支持同时在多部设备上运行测试。这在测试需要外部交互的组件(如手机与手表配对)时非常有用。

为了编写可以使用多部设备的测试运行程序,您需要实现 IMultiDeviceTest,该接口将允许接收 ITestDeviceIBuildInfo(其中包含设备表示方式及其关联 build 信息的完整列表)的映射。

该接口的 setter 始终在 run 方法之前调用,因此几乎可以断定,在调用 run 时结构可用。

知道自身设置的测试

某些测试运行程序实现可能需要有关整体设置的信息才能正常工作,例如有关调用的一些元数据或之前运行的 target_preparer 等。

为了做到这一点,测试运行程序可以访问它所属的同时也是它执行时所在的 IConfiguration 对象。如需了解更多详情,请参阅配置对象说明。

对于测试运行程序实现,您需要实现 IConfigurationReceiver 来接收 IConfiguration 对象。

灵活的测试运行程序

如果测试运行程序对测试进行精细控制,那么它们可以提供一种灵活的方式来运行这些测试。例如,JUnit 测试运行程序可以单独运行每个单元测试。

这样一来,更大的自动化测试框架和基础架构便可利用这种精细控制,用户也能通过过滤来部分地运行测试运行程序。

ITestFilterReceiver 接口中介绍了对过滤的支持,该接口允许接收多组 include 过滤条件和 exclude 过滤条件,用来过滤应运行或不应运行的测试。

我们的惯例是,当且仅当测试与一个或多个包含过滤器匹配且与任何排除过滤器都不匹配时,才会运行该测试。如果没有给出包含过滤器,那么应运行所有测试,只要它们与任何排除过滤器都不匹配。