测试模板

AOSP 包含用于非 VTS 运行程序 BaseTest 的主机端 Python 子类的测试模块的测试模板。

图 1. 测试模板架构。

开发者可以使用这些模板来最大限度地减少集成此类测试所需的工作量。本部分介绍了如何配置和使用测试模板(位于 VTS testcases/template 目录中),并提供了常用模板的示例。

BinaryTest 模板

使用 BinaryTest 模板可在 VTS 中集成在目标设备上执行的测试。目标端测试包括

  • C++ 基础测试(已编译并推送到设备)
  • 目标端 Python 测试(已编译为二进制文件)
  • Shell 脚本(可在设备上执行)

这些测试可以集成到 VTS 中,无论是否使用 BinaryTest 模板。

使用 BinaryTest 模板集成目标端测试

BinaryTest 模板旨在帮助开发者轻松集成目标端测试。在大多数情况下,您可以在 AndroidTest.xml 中添加几行简单的配置。以下是 VtsDeviceTreeEarlyMountTest 中的配置示例

<configuration description="Config for VTS VtsDeviceTreeEarlyMountTest.">
  ...
<test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
<option name="test-module-name" value="VtsDeviceTreeEarlyMountTest"/>
<option name="binary-test-source" value="_32bit::DATA/nativetest/dt_early_mount_test/dt_early_mount_test" />
<option name="binary-test-source" value="_64bit::DATA/nativetest64/dt_early_mount_test/dt_early_mount_test" />
<option name="test-timeout" value="5m"/>
</test>
</configuration>

在此配置中:

  • binary-test-sourcebinary-test-type 是模板专用的。
  • 指定测试二进制文件源的相对主机路径可让模板处理准备、文件推送、测试执行、结果解析和清理。
  • 该模板包含与测试用例创建相关的方法,供子类替换。
  • 该模板假定每个测试二进制文件模块一个测试用例,并且默认情况下使用二进制源文件名作为测试用例名称。

配置选项

BinaryTest 模板支持以下配置选项:

选项名称 值类型 说明
binary-test-source 字符串 二进制测试源路径(相对于主机上的 vts 测试用例目录)。
示例:DATA/nativetest/test
binary-test-working-directory 字符串 工作目录(设备端路径)。
示例:/data/local/tmp/testing/
binary-test-envp 字符串 二进制文件的环境变量。
示例:PATH=/new:$PATH
binary-test-args 字符串 测试参数或标记。
示例:--gtest_filter=test1
binary-test-ld-library-path 字符串 LD_LIBRARY_PATH 环境变量。
示例:/data/local/tmp/lib
binary-test-disable-framework 布尔值 运行 adb stop 以在测试前关闭 Android 框架。示例:true
binary-test-stop-native-servers 布尔值 在测试期间停止所有正确配置的原生服务器。示例:true
binary-test-type 字符串 模板类型。其他模板类型从此模板扩展而来,但您不必为此模板指定此选项,因为您已指定 binary-test-source

对于值类型为 strings 的选项,您可以通过在配置中重复选项来添加多个值。例如,将 binary-test-source 设置两次(如 VtsDeviceTreeEarlyMountTest 示例中所示)。

测试标记

您可以通过在选项前添加测试标记(值类型为 strings),并使用 :: 作为分隔符来添加测试标记。当包含名称相同但位深或父目录不同的二进制源时,测试标记尤其有用。例如,为了避免名称相同但源目录不同的源的文件推送或结果名称冲突,您可以为这些源指定不同的标记。

VtsDeviceTreeEarlyMountTest 示例中所示,其中包含两个 dt_early_mount_test 源,测试标记是 binary-test-source 上的 _32bit::_64bit:: 前缀。以 32bit64bit 结尾的标记会自动将测试标记为可用于一个 ABI 位深;即,标记为 _32bit 的测试不会在 64 位 ABI 上执行。不指定标记等同于使用空字符串的标记。

具有相同标签的选项被分组并与其他标签隔离。例如,带有 _32bit 标签的 binary-test-args 仅应用于带有相同标签的 binary-test-source,并在带有相同标签的 binary-test-working-directory 中执行。binary-test-working-directory 选项对于二进制测试是可选的,允许您为标签指定单个工作目录。如果未指定 binary-test-working-directory 选项,则为每个标签使用默认目录。

标签名称直接附加到结果报告中的测试用例名称。例如,带有 _32bit 标签的测试用例 testcase1 在结果报告中显示为 testcase1_32bit

集成不使用 BinaryTest 模板的目标侧测试

在 VTS 中,默认测试格式是从 VTS runner 中的 BaseTest 扩展的主机侧 Python 测试。要集成目标侧测试,您必须首先将测试文件推送到设备,使用 shell 命令执行测试,然后使用主机侧 Python 脚本解析结果。

推送测试二进制文件

我们建议使用 VtsFilePusher 目标准备器推送文件。例如

<target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
        <option name="push" value="DATA/test->/data/local/tmp/test"/>
    </target_preparer>

VtsFilePusher 执行以下操作

  1. 检查设备连接。
  2. 确定绝对源文件路径。
  3. 使用 adb push 命令推送文件。
  4. 测试完成后删除文件。

或者,您可以手动推送文件,方法是使用遵循类似过程的主机侧 Python 测试脚本。

运行测试

将文件推送到设备后,在主机侧 Python 测试脚本中使用 shell 命令运行测试。例如

device = self.android_devices[0]
res = device.shell.Execute(["chmod a+x /data/local/tmp/test", "/data/local/tmp/test"])
asserts.AssertFalse(any(res[return_codes]))

GtestBinaryTest 模板

GtestBinaryTest 模板 托管 GTest 测试二进制文件,每个文件通常包含多个测试用例。此模板通过覆盖 setup、测试用例创建和结果解析方法来扩展 BinaryTest 模板,因此继承了所有 BinaryTest 配置。

GtestBinaryTest 添加了选项 gtest-batch-mode

选项名称 值类型 说明
binary-test-type 字符串 模板类型。使用值 gtest
gtest-batch-mode 布尔值 以批处理模式运行 Gtest 二进制文件。示例:true

通常,将 gtest-batch-mode 设置为 true 会提高性能,但会略微降低可靠性。在 VTS 合规性测试中,许多模块使用批处理模式来提高性能。但是,为了可靠性,如果未指定模式,则默认为非批处理。

非批处理模式

非批处理模式为每个测试用例单独调用 GTest 二进制文件。例如,如果 GTest 二进制文件包含 10 个测试用例(在按主机侧配置过滤后),则二进制文件将在设备 shell 上调用 10 次,每次使用不同的测试过滤器。对于每个测试用例,模板都会生成和解析唯一的 GTest 结果输出 XML。

图 2. 非批处理模式。

使用非批处理模式的优点包括

  • 测试用例隔离。一个测试用例中的崩溃或挂起不会影响其他测试用例。
  • 粒度。更容易获得每个测试用例的性能分析/覆盖率测量、systrace、bugreport、logcat 等。测试结果和日志在每个测试用例完成后立即检索。

使用非批处理模式的缺点包括

  • 冗余加载。每次调用 GTest 二进制文件时,它都会加载相关库并执行初始类设置。
  • 通信开销。测试完成后,主机和目标设备会进行通信以进行结果解析和下一个命令(未来可能进行优化)。

批处理模式

在 GTest 批处理模式下,测试二进制文件仅被调用一次,并使用包含所有按主机侧配置过滤的测试用例的长测试过滤器值(这避免了非批处理模式下的冗余加载问题)。您可以使用 output.xml 或终端输出解析 GTest 的测试结果。

当使用 output.xml 时(默认)

图 3. 批处理模式,output.xml。

与非批处理模式一样,测试结果通过 GTest 输出 xml 文件解析。但是,由于输出 xml 是在所有测试完成后生成的,因此如果测试用例使二进制文件或设备崩溃,则不会生成结果 xml 文件。

当使用终端输出时

图 4. 批处理模式,终端输出。

当 GTest 运行时,它会将测试日志和进度以一种格式打印到终端,该格式可以被框架解析以获取测试状态、结果和日志。

使用批处理模式的优点包括

  • 测试用例隔离。如果框架在崩溃后使用缩减的测试过滤器(排除已完成和崩溃的测试用例)重新启动二进制文件/设备,则提供与非批处理模式相同级别的测试用例隔离。
  • 粒度。提供与非批处理模式相同的测试用例粒度。

使用批处理模式的缺点包括

  • 维护成本。如果 GTest 日志记录格式更改,则所有测试都将中断。
  • 混淆。测试用例可以打印类似于 GTest 进度格式的内容,这可能会混淆格式。

由于这些缺点,我们暂时删除了使用命令行输出的选项。我们将在未来重新审视此选项,以提高此功能的可靠性。

HostBinaryTest 模板

HostBinaryTest 模板包括主机侧可执行文件,这些文件在其他目录或 Python 脚本中不存在。这些测试包括

  • 在主机上可执行的已编译测试二进制文件
  • shell、Python 或其他语言的可执行脚本

一个示例是 VTS Security SELinux 策略主机侧测试

<configuration description="Config for VTS  Security SELinux policy host-side test cases">
    ...
    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
        <option name="test-module-name" value="VtsSecuritySelinuxPolicyHost"/>
        <option name="binary-test-source" value="out/host/linux-x86/bin/VtsSecuritySelinuxPolicyHostTest" />
        <option name="binary-test-type" value="host_binary_test"/>
    </test>
</configuration>

HostBinaryTest 不扩展 BinaryTest 模板,但确实使用类似的测试配置。在上面的示例中,binary-test-source 选项指定测试可执行文件的主机侧相对路径,binary-test-typehost_binary_test。与 BinaryTest 模板类似,默认情况下,二进制文件名用作测试用例名称。

扩展现有模板

您可以直接在测试配置中使用模板来包含非 Python 测试,或在子类中扩展它们以处理特定的测试要求。VTS 仓库中的模板具有以下扩展

图 5. 在 VTS 仓库中扩展现有模板。

鼓励开发人员针对任何特定的测试要求扩展任何现有模板。扩展模板的常见原因包括

  • 特殊的测试设置程序,例如使用特殊命令准备设备。
  • 生成不同的测试用例和测试名称。
  • 通过读取命令输出或使用其他条件来解析结果。

为了更容易扩展现有模板,模板包含针对每个功能专门设计的方法。如果您对现有模板有改进的设计,我们鼓励您为 VTS 代码库做出贡献。