查看源代码 使用 Common Test 进行大规模测试
概述
大规模自动化测试需要并行运行多个独立的测试会话。这通过在一个或多个主机上运行一些 Common Test
节点,测试不同的目标系统来实现。独立配置、启动和控制测试节点可能是一个繁琐的操作。为了帮助进行这种自动化的大规模测试,Common Test
提供了一个主测试节点组件,Common Test
Master,它在分布式 Common Test
节点系统中处理中心配置和控制。
Common Test
Master 服务器在一个专用的 Erlang 节点上运行,并使用分布式 Erlang 与任意数量的 Common Test
测试节点通信,每个节点都托管一个常规的 Common Test
服务器。测试规范用作输入,以指定在哪个测试节点上使用什么配置测试什么内容。
Common Test
Master 服务器以类似于常规 Common Test
服务器的方式将进度信息写入 HTML 日志文件。日志包含测试统计信息以及指向每个独立 Common Test
服务器写入的日志文件的链接。
Common Test
Master API 由模块 ct_master
导出。
使用
Common Test
Master 要求所有测试节点位于同一网络上并共享一个公共文件系统。Common Test
Master 不能自动启动测试节点。必须预先启动节点,Common Test
Master 才能在其上启动测试会话。
通过调用 ct_master:run(TestSpecs)
或 ct_master:run(TestSpecs, InclNodes, ExclNodes)
来启动测试。
TestSpecs
可以是测试规范文件名(字符串)或测试规范列表。如果它是一个列表,则按顺序处理规范(并执行相应的测试)。 TestSpecs
列表中的元素也可以是测试规范列表。在执行测试之前,此类列表中的规范会合并为一个组合规范。
示例
ct_master:run(["ts1","ts2",["ts3","ts4"]])
在这里,首先运行“ts1”指定的测试,然后运行“ts2”指定的测试,最后运行“ts3”和“ts4”指定的测试。
run/3
的 InclNodes
参数是节点名称列表。函数 run/3
像 run/1
一样运行 TestSpecs
中的测试,但也接受 TestSpecs
中的任何测试,该测试没有显式标记特定的节点名称,并在 InclNodes
中列出的节点上执行它。通过以这种方式使用 run/3
,任何测试规范都可以用于大规模测试环境,无论是否包含节点信息。
ExclNodes
是要从测试中排除的节点列表。也就是说,如果某个节点在运行时列在 ExclNodes
中,则不会执行测试规范中指定在该特定节点上运行的测试。
如果 Common Test
Master 最初未能连接到测试规范或 InclNodes
列表中指定的任何测试节点,则会提示操作员选择重新开始(在手动检查相关节点的状态后)、在没有丢失节点的情况下运行或中止操作。
当测试开始时,Common Test
Master 会向控制台显示有关所涉及节点的信息。Common Test
Master 还会报告测试何时完成,无论成功还是不成功。如果与某个节点的连接丢失,则该节点上的测试将被视为已完成。Common Test
Master 不会尝试重新建立与故障节点的联系。
随时,要获取测试节点的当前状态,请调用函数 ct_master:progress()
。
要停止一个或多个测试,请使用函数 ct_master:abort()
(停止所有)或 ct_master:abort(Nodes)
。
有关 Common Test
Master API 的详细信息,请参阅模块 ct_master
。
测试规范
用作 Common Test
Master 输入的测试规范与用作常规 Common Test
服务器输入的规范完全兼容。语法在运行测试和分析结果部分中的 测试规范 部分中进行了描述。
所有测试规范术语都可以有一个 NodeRefs
元素。此元素指定在哪个或哪些节点上执行配置操作或测试。NodeRefs
定义如下:
NodeRefs = all_nodes | [NodeRef] | NodeRef
NodeRef = NodeAlias | node() | master
NodeAlias
(atom/0
) 在测试规范中用作节点名称的引用(因此节点名称只需要声明一次,也可以使用常量来实现)。别名使用 node
术语声明如下:
{node, NodeAlias, NodeName}
如果 NodeRefs
的值为 all_nodes
,则在所有指定的测试节点上执行操作或测试。(声明一个没有 NodeRefs
元素的术语具有相同的效果)。如果 NodeRefs
的值为 master
,则操作仅在 Common Test
Master 节点上执行(即设置日志目录或安装事件处理程序)。
考虑运行测试和分析结果部分中的 测试规范 部分中的示例,现在使用节点信息进行扩展,并打算由 Common Test
Master 执行
{define, 'Top', "/home/test"}.
{define, 'T1', "'Top'/t1"}.
{define, 'T2', "'Top'/t2"}.
{define, 'T3', "'Top'/t3"}.
{define, 'CfgFile', "config.cfg"}.
{define, 'Node', ct_node}.
{node, node1, 'Node@host_x'}.
{node, node2, 'Node@host_y'}.
{logdir, master, "'Top'/master_logs"}.
{logdir, "'Top'/logs"}.
{config, node1, "'T1'/'CfgFile'"}.
{config, node2, "'T2'/'CfgFile'"}.
{config, "'T3'/'CfgFile'"}.
{suites, node1, 'T1', all}.
{skip_suites, node1, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
{skip_cases, node1, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
{skip_cases, node1, 'T1', t1C_SUITE, [test1], "Ignore"}.
{suites, node2, 'T2', [t2B_SUITE,t2C_SUITE]}.
{cases, node2, 'T2', t2A_SUITE, [test4,test1,test7]}.
{skip_suites, 'T3', all, "Not implemented"}.
此示例指定与原始示例相同的测试。但是,如果现在通过调用 ct_master:run(TestSpecName)
启动,则测试 t1
在节点 ct_node@host_x
(node1
) 上执行,测试 t2
在 ct_node@host_y
(node2
) 上执行,测试 t3
在 node1
和 node2
上执行。配置文件 t1
仅在 node1
上读取,配置文件 t2
仅在 node2
上读取,而配置文件 t3
在 node1
和 node2
上都读取。两个测试节点都将日志文件写入同一目录。(但是,Common Test
Master 节点使用与测试节点不同的日志目录。)
如果测试会话改为通过调用 ct_master:run(TestSpecName, [ct_node@host_z], [ct_node@host_x])
启动,则结果是测试 t1
不在 ct_node@host_x
(或任何其他节点)上运行,而测试 t3
在 ct_node@host_y
和 ct_node@host_z
上运行。
一个很好的特性是,包含节点信息的测试规范仍然可以用作常规 Common Test
服务器的输入(如 测试规范 部分中所述)。结果是,在与相关 Common Test
节点同名的节点上(如果使用 ct_run
程序启动,通常为 ct@somehost
)运行的任何测试都将执行。当然,没有明确节点关联的测试也始终执行。
自动启动测试目标节点
可以使用测试规范术语 init
在测试目标节点上自动启动和执行初始操作。
支持两个子术语:node_start
和 eval
。
示例
{node, node1, node1@host1}.
{node, node2, node1@host2}.
{node, node3, node2@host2}.
{node, node4, node1@host3}.
{init, node1, [{node_start, [{callback_module, my_slave_callback}]}]}.
{init, [node2, node3], {node_start, [{username, "ct_user"}, {password, "ct_password"}]}}.
{init, node4, {eval, {module, function, []}}}.
此测试规范声明 node1@host1
将使用用户回调函数 callback_module:my_slave_callback/0
启动,而节点 node1@host2
和 node2@host2
将使用默认回调模块 ct_slave
启动。指定的用户名和密码用于登录远程主机 host2
。此外,在 node1@host3
上评估函数 module:function/0
,并且此调用的结果将打印到日志中。
默认回调模块 ct_slave
具有以下功能
- 在本地或远程主机上启动 Erlang 目标节点(应用程序
SSH
用于通信)。 - 能够使用更多标志启动 Erlang 模拟器(支持
erl
支持的任何标志)。 - 使用内部回调函数来监视正在启动的节点。用于防止挂起的节点。(可配置。)
- 从属节点监视主节点。如果主节点终止,则可以停止从属节点。(可配置。)
- 在从节点启动后执行用户函数。函数可以指定为
{模块, 函数, 参数}
元组的列表。
注意
可以为节点指定一个
eval
项,以及在node_start
选项列表中的startup_functions
。在这种情况下,节点首先启动,然后执行startup_functions
,最后调用使用eval
指定的函数。