测试模板

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 test-case 目录相对的二进制测试源文件路径。
示例: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 值的选项的前缀,并使用 :: 作为分隔符。在包含具有相同名称但具有不同位数或父目录的二进制源文件时,测试标记尤其有用。例如,为了避免名称相同但源文件目录不同的源文件发生推送或结果名称冲突,您可以为这些源文件指定不同的标记。

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

具有相同标记的选项将组合到一起并与其他标记隔开来。例如,带有 _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 运行器中的 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 测试二进制文件,每个文件通常包含多个测试用例。该模板通过替换设置、测试用例创建和结果解析方法来扩展 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、错误报告、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 安全性 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 repo 中的模板具有以下扩展功能:

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

我们鼓励开发者扩展任何现有的模板以满足任何特定的测试要求。扩展模板的常见原因包括:

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

为了简化现有模板扩展过程,模板包含专用于每个功能的方法。如果您已经改进了现有模板的设计,我们建议您为 VTS 代码库做出贡献。