测试百科全书

<ph type="x-smartling-placeholder"></ph> 报告问题 <ph type="x-smartling-placeholder"></ph> 查看来源 每晚 · 7.2 条 · 7.1敬上 · 7.0 · 6.5 · 6.4

测试执行环境的详尽规范。

背景

Bazel BUILD 语言中包含可用于定义自动化 测试程序。

使用 bazel test 运行测试。

用户也可以直接执行测试二进制文件。我们允许这种做法,但不表示认可 因此此类调用将不遵循下述授权。

测试应该是封闭的:也就是说,测试应该只访问这些资源 它们已声明了依赖项如果测试未正确封闭 则它们不会给出可重现的历史结果。这可能是 找出导致罪魁祸首的重大问题(确定哪些更改破坏了测试)、 发布工程可审核性,以及测试的资源隔离(自动化 测试框架不应对服务器进行 DDOS,因为有些测试正好需要与 )。

目标

本页的目标是正式为 Cloud Storage 和 Cloud Storage 的 Bazel 测试的预期行为还会对测试施加要求 运行程序和构建系统

测试环境规范可帮助测试作者避免依赖 从而赋予测试基础设施更大的自由 实施更改。该规范增加了一些漏洞, 目前允许许多测试通过,尽管测试没有适当的封闭, 确定性和可重入性。

本页内容具有规范性和权威性。如果 与测试运行程序的实现行为不一致, 优先级。

建议的规范

关键字“必须”“不得”“必需”“会”“不会”“应” “不应该”“建议”“可以”和“可选”将被解释为 (如 IETF RFC 2119 中所述)。

测试目的

Bazel 测试的目的是确认源文件的某个属性 签入代码库(在本页中,“源文件”包括测试数据, 黄金输出,以及保持版本控制的其他内容。)一位用户写入 以断言预期会得到维护的不变量。其他用户 稍后执行测试以检查不变量是否已损坏。如果 测试依赖于除源文件(非封闭)之外的任何变量,其值 因为之后的用户无法确定他们的更改是否有误 当测试停止通过时触发。

因此,测试的结果必须仅取决于:

  • 测试已声明其依赖项的源文件
  • 已声明测试依赖的构建系统的产品
  • 行为由测试运行程序保证保持不变的资源

目前,未强制执行此类行为。不过,测试运行程序会保留 拥有权利。

构建系统的角色

测试规则类似于二进制规则,每个规则都必须生成一个可执行文件 计划。对于某些语言,这是一个存根程序,用于将 测试代码。测试规则必须生成 输出内容。除了主测试可执行文件之外,测试运行程序 将需要一个 runfiles 的清单,这些输入文件应该可供使用 在运行时进行测试,可能需要关于类型、大小和 代码。

构建系统可以使用 runfile 传递代码和数据。( 可以作为优化措施, 文件。)构建系统 应确保生成的可执行文件通过 runfile 测试运行程序提供的图像,而不是对绝对 在源树或输出树中的位置。

测试运行程序的角色

从测试运行程序的角度来看,每个测试都是一个程序, 使用 execve() 调用。可以通过其他方式进行测试;例如 IDE 可能允许在进程中执行 Java 测试。不过,结果 必须被视为权威性测试。如果 测试进程运行至完成并正常终止,并显示退出代码 零,则表示测试已通过。任何其他结果均被视为测试失败。在 具体来说,如果将任何字符串 PASSFAIL 写入 stdout, 对测试运行程序的重要性。

如果测试的执行时间过长、超出某些资源限制,或者 其他运行程序检测到禁止的行为,则可能会选择终止测试并 系统会将运行视为失败。运行程序之后不得将测试报告为通过 向测试进程或其任何子级发送信号。

为整个测试目标(而非单个方法或测试)指定有限的 运行完毕所需的时间测试的时间限制取决于 timeout 属性 如下表所示:

超时 时间限制(秒)
短片 60
适中 300
long 900
永恒 3600

未明确指定超时的测试会根据 测试的 size,如下所示:

大小 隐含的超时标签
短片
medium 适中
long
超大 永恒

“大型”对于没有显式超时设置的测试,将分配 900 秒。“媒介”测试超时情况为“short”将分配到 60 。

timeout 不同,size 还决定了 在本地运行测试时访问的其他资源(例如 RAM)中,具体说明请参阅 常见定义

sizetimeout 标签的所有组合都是合法的,因此“特大”测试 可以声明超时为“short”。它应该能 很快会发生可怕的事情

无论超时多久,测试都可能会以任意快的速度返回。测试不会受到处罚 设置超时值,虽然系统可能会发出警告: 通常,应尽可能将超时设置得很紧,不易出现任何不稳定的情况。

在以下情况下,可以使用 --test_timeout bazel 标志替换测试超时: 在已知慢速条件下手动运行。通过 --test_timeout 值以秒为单位。例如:--test_timeout=120 将测试超时设置为两分钟。

此外,还有一个建议的测试超时下限,如下所示:

超时 最短时间(秒)
短片 0
适中 30
long 300
永恒 900

例如,如果“中等”测试在 5.5 秒内完成,请考虑设置 timeout = "short"size = "small"。使用 bazel --test_verbose_timeout_warnings 命令行选项会显示指定大小过大的测试。

测试大小和超时在 BUILD 文件中根据 此处查看规范。如果 未指定,测试大小将默认为“medium”。

如果测试的主进程退出,但其部分子级进程仍在运行, 测试运行程序应认为运行已完成并将其计为成功,或者 根据从主进程观察到的退出代码判断是否失败。测试运行程序 可能会终止任何散乱进程测试不应以这种方式泄露进程。

测试分片

您可以通过测试分片并行运行测试。请参阅 --test_sharding_strategyshard_count至 启用测试分片。启用分片后,测试运行程序将启动一次 每个分片环境变量 TEST_TOTAL_SHARDS 是碎片数,而 TEST_SHARD_INDEX 是 分片索引,从 0 开始。运行程序会使用这些信息来选择哪些测试 运行 - 例如,使用轮循策略。并非所有测试运行程序都支持 。如果运行程序支持分片,则必须创建或更新最后一个 指定的文件的修改日期 TEST_SHARD_STATUS_FILE。否则,如果 --incompatible_check_sharding_support 启用后,如果 Bazel 被分片,测试将无法通过。

初始条件

在执行测试时,测试运行程序必须建立特定的初始 条件。

测试运行程序必须使用测试可执行文件的路径来调用每个测试。 argv[0]。此路径必须是相对路径,并且位于测试的当前目录下 (位于 runfiles 树,请参阅下文)。测试运行程序不应通过任何 为测试添加其他参数,除非用户明确要求。

初始环境块应按如下方式组成:

变量 状态
HOME $TEST_TMPDIR 的值 推荐
LANG unset 必填
LANGUAGE unset 必填
LC_ALL unset 必填
LC_COLLATE unset 必填
LC_CTYPE unset 必填
LC_MESSAGES unset 必填
LC_MONETARY unset 必填
LC_NUMERIC unset 必填
LC_TIME unset 必填
LD_LIBRARY_PATH 以冒号分隔的包含共享库的目录列表 可选
JAVA_RUNFILES $TEST_SRCDIR 的值 已弃用
LOGNAME $USER 的值 必填
PATH /usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:. 推荐
PWD $TEST_SRCDIR/workspace-name 推荐
SHLVL 2 推荐
TEST_INFRASTRUCTURE_FAILURE_FILE 可写目录中某个私有文件的绝对路径(此文件 只能用于报告 而非作为报告不稳定故障的一般机制 测试。在这种情况下,测试基础设施就是系统 或并非特定于测试但可能会导致测试失败的库 出现故障。第一行是测试基础架构的名称 第二个组件是人类可读的 失败的说明。其他行会被忽略)。 可选
TEST_LOGSPLITTER_OUTPUT_FILE 可写目录中私有文件的绝对路径(用于写入 Logsplitter 协议缓冲区日志) 可选
TEST_PREMATURE_EXIT_FILE 可写目录中私有文件的绝对路径(用于 捕获对 exit() 的调用) 可选
TEST_RANDOM_SEED 如果使用 --runs_per_test 选项, TEST_RANDOM_SEED 设置为 run number (从 1 开始)。 可选
TEST_RUN_NUMBER 如果使用 --runs_per_test 选项, TEST_RUN_NUMBER 设置为 run number (从 1 开始)。 可选
TEST_TARGET 要测试的目标的名称 可选
TEST_SIZE 测试 size 可选
TEST_TIMEOUT 测试 timeout(以秒为单位) 可选
TEST_SHARD_INDEX 分片索引(如果使用了 sharding 可选
TEST_SHARD_STATUS_FILE 要触摸的文件路径,用于表示支持 sharding 可选
TEST_SRCDIR runfiles 树基底的绝对路径 必填
TEST_TOTAL_SHARDS 总计 shard count, 如果使用 sharding 可选
TEST_TMPDIR 私有可写目录的绝对路径 必填
TEST_WORKSPACE 本地代码库的工作区名称 可选
TEST_UNDECLARED_OUTPUTS_DIR 私有可写目录的绝对路径(用于写入未声明的 测试输出)。任何写入到 TEST_UNDECLARED_OUTPUTS_DIR 目录将被压缩, 添加到outputs.zip文件内的 bazel-testlogs 可选
TEST_UNDECLARED_OUTPUTS_ANNOTATIONS_DIR 私有可写目录的绝对路径(用于写入未声明的 测试输出注释 .part.pb 文件)。 可选
TEST_WARNINGS_OUTPUT_FILE 可写目录中私有文件的绝对路径(用于写入 测试目标警告) 可选
TESTBRIDGE_TEST_ONLY --test_filter, (如果指定) 可选
TZ UTC 必填
USER getpwuid(getuid())->pw_name 的值 必填
XML_OUTPUT_FILE 测试操作应将测试结果 XML 输出文件写入到的位置。 否则,Bazel 会生成封装测试日志的默认 XML 输出文件 作为测试操作的一部分。XML 架构基于 JUnit 测试结果架构 可选
BAZEL_TEST 表示测试可执行文件由 bazel test 驱动 必填

环境可能包含其他条目。测试不应依赖于 上面未列出的任何环境变量的存在、缺失或值。

初始工作目录应为 $TEST_SRCDIR/$TEST_WORKSPACE

当前的进程 ID、进程组 ID、会话 ID 和父级进程 ID 为 未指定。该进程不一定是进程组领导者或会话 。该进程不一定有控制终端。该过程可能会 具有零个或零个或多个正在运行或未回收的子进程。该过程不应 当测试代码获得控制权时,有多个线程。

文件描述符 0 (stdin) 应处于开放状态以供读取,但它被附加到 未指定参数。测试不得从中读取数据。文件描述符 1 (stdout) 和 2 (stderr) 应开放写入,但附加的内容为 未指定。它可以是终端、管道、常规文件 可以写出哪些字符。他们可能会共享打开文件表中的条目 (这意味着它们不能独立寻找)。测试不应继承任何 其他打开的文件描述符

初始 umask 应为 022027

不应有闹铃或间隔计时器。

被屏蔽信号的初始掩码应为空。所有信号均应设置为 执行默认操作。

初始资源限制(包括软资源限制和硬资源限制)应按如下方式设置:

资源 限制
RLIMIT_AS 无限制
RLIMIT_CORE 未指定
RLIMIT_CPU 无限制
RLIMIT_DATA 无限制
RLIMIT_FSIZE 无限制
RLIMIT_LOCKS 无限制
RLIMIT_MEMLOCK 无限制
RLIMIT_MSGQUEUE 未指定
RLIMIT_NICE 未指定
RLIMIT_NOFILE 至少 1024
RLIMIT_NPROC 未指定
RLIMIT_RSS 无限制
RLIMIT_RTPRIO 未指定
RLIMIT_SIGPENDING 未指定
RLIMIT_STACK 无限制,或 2044KB <= rlim <= 8192KB

初始进程时间(由 times() 返回)和资源利用率 (由 getrusage() 返回)。

未指定初始调度政策和优先级。

主机系统的角色

除了测试直接控制的用户情境的各个方面之外, 运行程序,执行测试的操作系统必须满足 属性。

文件系统

测试观察到的根目录不一定是真实的根目录。

应装载 /proc

所有构建工具都应位于/usr 本地安装

/home 开头的路径可能不可用。测试不应访问任何 此类路径

/tmp 应可写入,但测试应避免使用这些路径。

测试不得假设任何常量路径可用于其专有 。

测试不得假设已为任何已装载的文件系统启用 atime。

用户和组

users root、nobody 和 unittest 必须存在。群组 root、nobody 和 eng 必须存在。

测试必须以非根用户的身份执行。真实有效的用户 ID 必须 相等;同样地,也适用于群组 ID。除此之外,当前的用户 ID、群组 ID、 用户名和群组名称均未指定补充的群组 ID 集合为 未指定。

当前的用户 ID 和组 ID 必须有相应的名称, 使用 getpwuid()getgrgid() 进行检索。对于 补充的群组 ID。

当前用户必须有一个主目录。可能无法写入。测试必须 请勿尝试对其执行写入操作。

网络

未指定主机名。它不一定包含点。解决 主机名必须提供当前主机的 IP 地址。解决主机名剪切的问题 第一个点之后的结果也必须有效。localhost 必须解析主机名。

其他资源

测试至少被授予一个 CPU 核心。其他可能可用,但不可用 。未指定此核心的其他性能方面。您可以 通过添加标记将预留增加到更多 CPU 核心数 &quot;cpu:n&quot;(其中 n 为正数)。如果机器的 CPU 核心总数超过请求的 CPU 核心数,则 Bazel 仍会运行测试。如果测试使用 sharding 表示,每个分片都会预留一些 CPU 核心机器类型

测试可以创建子进程,但不能处理组或会话。

测试可使用的输入文件数量是有限制的。此限制为 可能会有变化,但目前在数万个输入范围内。

时间和日期

未指定当前时间和日期。未指定系统时区。

X Windows 可能可用,也可能不可用。需要 X 服务器的测试应启动 Xvfb。

测试与文件系统的交互

测试环境变量中指定的所有文件路径均指向 本地文件系统(除非另有说明)。

测试应仅在 $TEST_TMPDIR$TEST_UNDECLARED_OUTPUTS_DIR(如果已设置)。

这些目录最初为空。

测试不得尝试移除、chmod 或以其他方式更改这些目录。

这些目录可能是符号链接。

$TEST_TMPDIR/. 的文件系统类型仍然未指定。

测试还可以将 .part 文件写入 $TEST_UNDECLARED_OUTPUTS_ANNOTATIONS_DIR,用于为未声明的输出文件添加注释。

在极少数情况下,测试可能会强制在 /tmp 中创建文件。例如: Unix 网域套接字的路径长度限制 通常需要在 /tmp 下创建套接字。Bazel 将无法 跟踪此类文件;测试本身必须要注意封闭 避免与其他(同时运行测试和非测试)发生冲突的路径 进程,以及清理它在 /tmp 中创建的文件。

一些常用的测试框架,例如 JUnit4 TemporaryFolderGo TempDir, 用自己的方式在 /tmp 下创建临时目录。这些测试 框架包含清理 /tmp 中的文件的功能,因此您可以使用 即使他们在 TEST_TMPDIR 之外创建文件,也是如此。

测试必须通过 runfiles 机制或其他部分 执行环境, 可用。

测试不得在从以下推断出的路径中访问构建系统的其他输出: 自己的可执行文件的位置

不指定 runfiles 树是否包含符号 链接或两者的组合。runfiles 树可能包含指向目录的符号链接。 测试应避免在 runfile 中使用包含 .. 组成部分的路径 树。

runfiles 树中没有任何目录、文件或符号链接(包括 遍历符号链接)。(因此,最初的工作是 目录。)测试不得假定 runfiles 可写,或归当前用户所有(例如,chmodchgrp 可能 失败)。

Runfiles 树(包括遍历符号链接的路径)不得更改 。不得更改父级目录和文件系统装载 以任何方式影响运行文件中某个路径的解析结果 树。

为了捕获提前退出,测试可能会在由 在启动时调用 TEST_PREMATURE_EXIT_FILE,并在退出时将其移除。如果 Bazel 文件,则会认为测试过早退出, 将其标记为已失败

代码规范

测试规则中的某些代码具有特殊含义。另请参阅 tags 属性的 Bazel 构建百科全书

标记 含义
exclusive 不同时运行其他测试
external 测试具有外部依赖项;停用测试缓存
large test_suite 惯例;大型测试套件
manual * 请勿在通配符目标格式中包含测试目标,例如 :...:*:all
medium test_suite 惯例;中型测试套件
small test_suite 惯例;一套小型测试
smoke test_suite 惯例;意味着它应该在 将代码更改提交到版本控制系统

Runfile

在下例中,假设有一条 *_binary() 规则, //foo/bar:unittest,运行时依赖于标记为 //deps/server:server

位置

目标 //foo/bar:unittest 的 runfiles 目录 $(WORKSPACE)/$(BINDIR)/foo/bar/unittest.runfiles。该路径称为 runfiles_dir

依赖项

将 runfiles 目录声明为 *_binary() 规则。runfiles 目录本身依赖于 BUILD 文件集 影响 *_binary() 规则或其任何编译时或运行时的文件 依赖项修改源文件不会影响 runfiles 目录,因此不会触发任何重新构建。

目录

runfiles 目录包含以下内容:

  • 指向运行时依赖项的符号链接:*_binary() 规则的运行时依赖项,由 runfiles 目录符号链接的名称为 $(WORKSPACE)/package_name/rule_name。例如,服务器的符号链接 将命名为 $(WORKSPACE)/deps/server/server,而完整路径将为 $(WORKSPACE)/foo/bar/unittest.runfiles/$(WORKSPACE)/deps/server/server。 符号链接的目标是 OutputFile 或 CommandRule,表示为绝对路径。因此, 符号链接可能是 $(WORKSPACE)/linux-dbg/deps/server/42/server
  • 子运行时的符号链接:针对运行时的每个 *_binary() Z *_binary() C 的依赖项,则 runfile 中还有第二个链接 复制到 Z 的 runfile 中。符号链接的名称为 $(WORKSPACE)/package_name/rule_name.runfiles。符号链接的目标为 runfiles 目录例如,所有子程序共享一个 目录。