8. Running Tests and Analyzing Results
8运行测试及分析结果
8.1使用通用测试框架
该Common Test
框架提供了用于测试的高级操作员界面,提供以下功能:
- 自动编译测试套件(和帮助模块)
- 创建额外的HTML页面以改进概览。
- 运行所有可用测试的单命令接口
- 处理指定与被测系统(SUT)相关的数据的配置文件(以及任何其他可变数据)
- 与中央控制和配置并行运行多个独立测试会话的模式
8.2测试套件和帮助模块的自动编译
当Common Test
启动时,它会自动尝试编译包括在指定任何测试套件。如果指定了特定的套件,则仅编译这些套件。如果指定了特定的测试对象目录(意味着此目录中的所有套件都将成为测试的一部分),则Common Test
运行make:all/1
目录中的运行以编译套件。
如果一个或多个套件的编译失败,编译错误将打印到tty,并询问操作员测试运行是否要在没有缺失套件的情况下继续执行,或者被中止。如果操作员选择继续,则在HTML日志中记录具有缺失套件的测试。如果Common Test
编译失败后无法提示用户(如果Common Test
无法控制stdin
),则测试运行自动进行,不会丢失套件。但是,该行为可以通过ct_run
标志-abort_if_missing_suites
或ct:run_test/1
选项进行修改{abort_if_missing_suites,TrueOrFalse}
。如果abort_if_missing_suites
设置为true
,则某些套件无法编译时,测试运行会立即停止。
任何与作为测试一部分的套件位于相同测试对象目录中的帮助模块(即,名称不以“_SUITE”结尾的常规Erlang模块)也会自动编译。帮助模块不会被误认为测试套件(除非它具有“_SUITE”名称)。无论目录中的所有或唯一特定套件是否为测试的一部分,都会编译特定测试对象目录中的所有帮助模块。
如果测试套件或帮助模块包含存储在除测试目录之外的其他位置的头文件,则可以通过使用-include
带有标志ct_run
或include
带有选项的指定来包含这些目录ct:run_test/1
。另外,可以使用OS环境变量指定包含路径CT_INCLUDE_PATH
。
示例 (bash):
$ export CT_INCLUDE_PATH=~testuser/common_suite_files/include:~testuser/common_lib_files/include
Common Test
将所有包含目录(使用标志/选项include
或变量CT_INCLUDE_PATH
或两者指定)传递给编译器。
包含目录也可以在测试规范中指定,请参阅Test Specifications
。
如果用户想通过仅指定顶级目录(例如,使用开始标志/选项dir
)来运行测试对象(或OTP应用程序)的所有测试套件,则Common Test
主要在名为的子目录中查找测试套件模块test
。如果此子目录不存在,则指定的顶层目录将被视为测试目录,并从中读取测试套件。
要禁用自动编译功能,请使用flag -no_auto_compile
with ct_run
或option {auto_compile,false}
with ct:run_test/1
。在禁用自动编译的情况下,用户负责在测试运行之前编译测试套件模块(以及任何帮助模块)。如果启动期间无法从本地文件系统Common Test
加载模块,则用户必须在开始测试之前预加载模块。Common Test
仅验证指定的测试套件是否存在(即,它们是否可以加载)。例如,如果测试套件通过RPC从远程节点传输并加载为二进制文件,则这很有用。
8.3从操作系统命令行运行测试
例如,ct_run
程序可用于从OS命令行运行测试,如下所示:
- ct_run -config <configfilenames> -dir <dirs>
- ct_run -config <configfilenames> -suite <suiteswithfullpath>
- ct_run -userconfig <callbackmodulename> <configfilenames> -suite <suiteswithfullpath>
- ct_run -config <configfilenames> -suite <suitewithfullpath> -group <groups> -case <casenames>
例子:
$ ct_run -config $CFGS/sys1.cfg $CFGS/sys2.cfg -dir $SYS1_TEST $SYS2_TEST
$ ct_run -userconfig ct_config_xml $CFGS/sys1.xml $CFGS/sys2.xml -dir $SYS1_TEST $SYS2_TEST
$ ct_run -suite $SYS1_TEST/setup_SUITE $SYS2_TEST/config_SUITE
$ ct_run -suite $SYS1_TEST/setup_SUITE -case start stop
$ ct_run -suite $SYS1_TEST/setup_SUITE -group installation -case start stop
标志dir
,suite
和group/case
可以组合。例如,要运行x_SUITE
并y_SUITE
在目录中testdir
,如下所示:
$ ct_run -dir ./testdir -suite x_SUITE y_SUITE
这样做的效果如下:
$ ct_run -suite ./testdir/x_SUITE ./testdir/y_SUITE
有关详情,请参阅Test Case Group Execution
。
下面的标志也可以与ct_run
*
-help
列出所有可用的开始标志。
-logdir <dir>
指定要写入HTML日志文件的位置。
-label <name_of_test_run>
将测试运行与在概述HTML日志文件中打印的名称关联。
-refresh_logs
刷新顶级HTML索引文件。
-vts
启动基于web的GUI,稍后将介绍。
-shell
启动交互式shell模式(稍后介绍)。
-step [step_opts]
使用Erlang调试器测试案例(稍后介绍)。
-spec <testspecs>
使用测试规范作为输入(稍后介绍)。
-allow_user_terms
在测试规范中允许用户特定的条款(稍后介绍)。
-silent_connections [conn_types]
,告诉Common Test
抑制指定连接的打印输出(稍后介绍)。
-stylesheet <css_file>
指出用户HTML样式表(稍后介绍)。
-cover <cover_cfg_file>
执行代码覆盖率测试(请参阅Code Coverage Analysis
)。
-cover_stop <bool>
指定cover
测试完成后是否要停止工具(请参阅Code Coverage Analysis
)。
-event_handler <event_handlers>
要安装event handlers
。
-event_handler_init <event_handlers>
安装event handlers
包括开始争论。
-ct_hooks <ct_hooks>
安装Common Test Hooks
包括开始争论。
-enable_builtin_hooks <bool>
启用或禁用Built-in Common Test Hooks
。默认是true
。
-include
指定包含目录(如前所述)。
-no_auto_compile
禁用自动测试套件编译功能(如前所述)。
-abort_if_missing_suites
如果一个或多个套件无法编译(如前所述),则中止测试运行。
-multiply_timetraps <n>
扩展timetrap time-out
价值。
-scale_timetraps <bool>
启用自动timetrap time-out
缩放。
-repeat <n>
告诉Common Test
重复测试n
时间(稍后介绍)。
-duration <time>
告诉Common Test
重复测试持续时间(稍后介绍)。
-until <stop_time>
告诉Common Test
重复测试,直到stop_time
(稍后描述)。
-force_stop [skip_rest]
超时后,测试运行在当前测试作业完成时中止。如果skip_rest
提供,则跳过当前测试作业中的其余测试用例(稍后介绍)。
-decrypt_key <key>
提供解密密钥encrypted configuration files
。
-decrypt_file <key_file>
指出一个包含解密密钥的文件encrypted configuration files
。
-basic_html
关闭可能与旧版浏览器不兼容的HTML增强功能。
-logopts <opts>
启用修改记录行为,请参阅Log options
。
-verbosity <levels>
设置verbosity levels for printouts
。
-no_esc_chars
禁止自动转义特殊的HTML字符。看到了Logging chapter
。
注
传递给的目录Common Test
可以具有相对路径或绝对路径。
注
Erlang运行时系统(应用程序ERTS)的任何开始标志也可以作为参数传递给ct_run
。例如,能够将目录传递到带有标志-pa
或标志的Erlang代码服务器搜索路径中非常有用-pz
。如果测试套件(单独编译)有共同的帮助或库模块,并存储在测试套件目录以外的其他目录中,则这些help/lib
目录最好以这种方式添加到代码路径中。
例子:
$ ct_run -dir ./chat_server -logdir ./chat_server/testlogs -pa $PWD/chat_server/ebin
目录的绝对路径在chat_server/ebin
这里传递给代码服务器。这是非常重要的,因为代码服务器将相对路径存储为相对路径,并Common Test
在测试运行期间更改ERTS的当前工作目录。
ct_run
程序在关机前设置退出状态。定义了以下值:
0
表示成功的testrun,即没有失败或自动跳过的测试用例。
1
表示一个或多个测试用例失败或已被自动跳过。
2
表示由于例如编译错误或来自信息功能的非法返回值而导致测试执行失败。
如果自动跳过的测试用例不影响退出状态。默认行为可以使用开始标志进行更改:
-exit_status ignore_config
注
ct_run
不用开始标志执行就等于命令:ct_run -dir ./
有关该ct_run
程序的更多信息,请参阅模块ct_run
和章节Installation
。
8.4从Erlang Shell或Erlang程序运行测试
Common Test
为运行测试提供了一个Erlang API。用于指定和执行测试的主要(也是最灵活的)功能是ct:run_test/1
。它采用与启动参数相同ct_run
的标志,但标志在键值元组列表中被指定为选项。例如,用ct_run
以下指定的测试:
$ ct_run -suite ./my_SUITE -logdir ./results
与ct:run_test/1
指定为:
1> ct:run_test([{suite,"./my_SUITE"},{logdir,"./results"}]).
该函数返回由元组表示的测试结果{Ok,Failed,{UserSkipped,AutoSkipped}}
,其中每个元素是一个整数。如果测试执行失败,则该函数将返回元组{error,Reason}
,该术语Reason
解释失败。
{dir,Cwd}
如果使用空的选项列表调用该函数,则使用默认启动选项(以运行当前工作目录中的所有套件)。
发布Erlang Shell
在开始执行测试期间ct:run_test/1
,控制Erlang shell进程stdin
仍然是进程Common Test
系统的顶级进程。因此,在测试运行期间,Erlang shell不可用于交互。例如,如果这是不可取的,例如,因为调试目的或在测试执行期间与SUT交互需要shell,请将start选项设置release_shell
为true
(在调用ct:run_test/1
或使用相应的测试规范术语,稍后介绍)。这使得Common Test
在测试套件编译阶段之后立即释放shell。为了达到这个目的,一个测试运行器进程被产生以控制测试执行。效果是这样的ct:run_test/1
返回此进程的pid而不是测试结果,而测试结果将在测试运行结束时打印到tty。
注
要使用的功能ct:break/1,2
和ct:continue/0,1
,release_shell
必须
设置为true
。
有关详细信息,请参见ct:run_test/1
手册页。
8.5测试用例组执行
通过ct_run
标志或ct:run_test/1
选项group
,可以指定一个或多个测试用例组,可选地结合特定的测试用例。在命令行上指定组的语法如下所示:
$ ct_run -group <group_names_or_paths> [-case <cases>]
Erlang shell中的语法如下:
1> ct:run_test([{group,GroupsNamesOrPaths}, {case,Cases}]).
参数group_names_or_paths
指定一个或多个组名和/或一个或多个组路径。在启动时,Common Test
搜索组定义树中的匹配组(即,返回的列表Suite:groups/0
;有关详细信息,请参见部分Test Case Groups
。
给定一个组名,比如g
,Common Test
搜索导致所有路径g
。按路径指的是一系列嵌套组,必须遵循才能从顶层组获取g
。要在组中执行测试用例g
,Common Test
必须调用init_per_group/2
路径中每个组的函数,然后调用g
所有相应的end_per_group/2
函数。这是因为g
(和它的Config
输入数据)中的测试用例的配置依赖于init_per_testcase(TestCase, Config)
它的返回值,而这个返回值又取决于init_per_group(g, Config)
返回值,而返回值又取决于init_per_group/2
上面的组g
,依此类推直到顶层组。
这意味着如果在一个路径中有多种方法来定位组(及其测试用例),则组搜索操作的结果是一系列测试,所有这些测试都将被执行。Common Test
解释由单一名称组成的组规范,如下所示:
“搜索并查找组定义树中导向指定组的所有路径,并为每个路径创建一个按以下顺序执行以下操作的测试:
- 执行指定组路径中的所有配置函数。
- 在这个组中执行所有或全部匹配的测试用例。
- 在组的所有子组中执行所有或所有匹配的测试用例。“
用户可以使用参数指定特定的组路径group_names_or_paths
。通过这种类型的规范执行不需要的组(在其他匹配路径中),和/或可以避免子组的执行。组路径的命令行语法是路径中的组名列表,例如:
$ ct_run -suite "./x_SUITE" -group [g1,g3,g4] -case tc1 tc5
Erlang shell中的语法如下(在组列表中需要一个列表):
1> ct:run_test([{suite,"./x_SUITE"}, {group,[[g1,g3,g4]]}, {testcase,[tc1,tc5]}]).
指定路径中的最后一个组是测试中的终止组,也就是说,该组后面的任何子组都不会被执行。在前面的例子中,g4
是终止组。因此,Common Test
执行一个测试,调用init
路径中的所有配置函数g4
,也就是说g1..g3..g4
。然后,它调用测试用例tc1
和tc5
中g4
,最后全部end
以配置功能g4..g3..g1
。
注
组路径规范不一定必须包括终止组路径中的所有
组。Common Test
如果指定了不完整的组路径,则搜索所有
匹配的路径。
注
组名和组路径可以与参数组合group_names_or_paths
。每个元素与参数一起被视为单独的规格cases
。以下示例说明了这一点。
例子:
-module(x_SUITE).
...
%% The group definitions:
groups() ->
[{top1,[],[tc11,tc12,
{sub11,[],[tc12,tc13]},
{sub12,[],[tc14,tc15,
{sub121,[],[tc12,tc16]}]}]},
{top2,[],[{group,sub21},{group,sub22}]},
{sub21,[],[tc21,{group,sub2X2}]},
{sub22,[],[{group,sub221},tc21,tc22,{group,sub2X2}]},
{sub221,[],[tc21,tc23]},
{sub2X2,[],[tc21,tc24]}].
下面执行两项测试,一个适用于所有情况下的所有子组top1
,以及一个对所有下top2
:
$ ct_run -suite "x_SUITE" -group all
1> ct:run_test([{suite,"x_SUITE"}, {group,all}]).
使用-group top1 top2
或{group,[top1,top2]}
给出相同的结果。
以下为所有案例和小组执行一项测试top1
:
$ ct_run -suite "x_SUITE" -group top1
1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}]).
下面运行tc12
在可以找到(和)的位置top1
下的任何子组中执行的测试:top1sub11sub121
$ ct_run -suite "x_SUITE" -group top1 -case tc12
1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc12]}]).
以下内容tc12
仅
在组中执行top1
:
$ ct_run -suite "x_SUITE" -group [top1] -case tc12
1> ct:run_test([{suite,"x_SUITE"}, {group,[[top1]]}, {testcase,[tc12]}]).
以下搜索top1
及其所有子组tc16
导致此测试用例在组中执行sub121
:
$ ct_run -suite "x_SUITE" -group top1 -case tc16
1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc16]}]).
在此示例中使用特定路径-group [sub121]
或{group,[[sub121]]}
给出相同的结果。
下面执行两个测试,其中一个包括所有案例和子组sub12
,另一个只
包含测试案例sub12
:
$ ct_run -suite "x_SUITE" -group sub12 [sub12]
1> ct:run_test([{suite,"x_SUITE"}, {group,[sub12,[sub12]]}]).
在以下示例中,Common Test
查找并执行两个测试,一个用于从路径top2
到sub2X2
通过sub21
,一个来自top2
于sub2X2
通过sub22
:
$ ct_run -suite "x_SUITE" -group sub2X2
1> ct:run_test([{suite,"x_SUITE"}, {group,[sub2X2]}]).
在以下示例中,通过指定唯一路径top2 -> sub21 -> sub2X2,仅执行一个测试。第二个可能的路径,从top2到sub2X2(从以前的例子)被丢弃:
$ ct_run -suite "x_SUITE" -group [sub21,sub2X2]
1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub21,sub2X2]]}]).
sub22
与组定义相比,以下内容仅执行测试用例并按相反顺序执行:
$ ct_run -suite "x_SUITE" -group [sub22] -case tc22 tc21
1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub22]]}, {testcase,[tc22,tc21]}]).
如果属于一个组的测试用例(根据组定义)在没有组规范的情况下执行,也就是简单地通过(使用命令行):
$ ct_run -suite "my_SUITE" -case my_tc
或者(使用Erlang shell):
1> ct:run_test([{suite,"my_SUITE"}, {testcase,my_tc}]).
然后Common Test
忽略组定义并仅在测试套件的范围内执行测试用例(不调用组配置功能)。
本节介绍的组规格功能也可以用于Test Specifications
(添加了一些额外的功能)。
8.6运行交互式Shell模式
您可以Common Test
在没有执行自动测试的交互式shell模式下启动。相反,Common Test
启动它的实用程序进程,安装配置数据(如果有的话),并等待用户从Erlang shell调用函数(通常是测试用例支持函数)。
例如,shell模式对调试测试套件,在“模拟”测试用例执行过程中分析和调试SUT以及在测试套件开发期间尝试各种操作很有用。
要启动交互式shell模式,请手动启动Erlang shell并调用ct:install/1
以安装您可能需要的任何配置数据([]
否则使用参数作为参数)。然后打电话ct:start_interactive/0
开始Common Test
。
如果你使用这个ct_run
程序,你可以启动Erlang shell,Common Test
然后通过使用标志-shell
和可选的标志-config
和/或来选择-userconfig
。
例子:
ct_run -shell
ct_run -shell -config cfg/db.cfg
ct_run -shell -userconfig db_login testuser x523qZ
如果没有使用命令指定配置文件ct_run
,则会显示警告。如果之前Common Test
已经从同一个目录运行,则会再次使用相同的配置文件。如果Common Test
之前没有从此目录运行,则没有配置文件可用。
如果任何使用“所需配置数据”的函数(例如,函数ct_telnet
或ct_ftp
)将从Erlang shell中调用,则首先需要使用配置数据ct:require/1,2
。这相当于require
在Test Suite Information Function
或中的陈述Test Case Information Function
。
例子:
1> ct:require(unix_telnet, unix).
ok
2> ct_telnet:open(unix_telnet).
{ok,<0.105.0>}
4> ct_telnet:cmd(unix_telnet, "ls .").
{ok,["ls .","file1 ...",...]}
Common Test通常在测试用例日志中打印的所有内容都以交互模式写入到ctlog.html目录中指定的日志中ct_run.<timestamp>。该文件的链接last_interactive.html位于您执行的目录中的文件中ct_run。不支持指定不同于当前工作目录的日志的根目录。
如果您希望退出交互模式(例如,启动自动化测试运行ct:run_test/1
),请调用函数ct:stop_interactive/0
。这会关闭正在运行的ct
应用程序。配置名称与创建的数据之间的关联require
因此被删除。函数ct:start_interactive/0
使您回到交互模式,但之前的状态不会恢复。
8.7使用Erlang调试器逐步执行测试用例
使用ct_run -step [opts]
,或者通过传递选项{step,Opts}
到ct:run_test/1
,以下是可能的:
- 自动启动Erlang调试器。
- 使用其图形界面来调查当前测试用例的状态。
- 逐步执行测试用例和/或设置执行断点。
如果没有用标志/选项指定额外的选项step
,则断点将自动设置在要执行的测试用例上Common Test
,而这些功能只能用于执行。如果步骤选项config
指定,断点也最初设置在套件中的配置功能,即,init_per_suite/1
,end_per_suite/1
,init_per_group/2
,end_per_group/2
,init_per_testcase/2
和end_per_testcase/2
。
Common Test
启用调试器自动附加功能,这意味着对于每个新开始执行的解释测试用例函数,都会自动弹出一个新的跟踪窗口(每个测试用例在专用的Erlang进程上执行)。每当新的测试用例开始时,就Common Test
尝试关闭先前测试用例的不活动跟踪窗口。但是,如果您希望Common Test
保留不活动的跟踪窗口,请使用选项keep_inactive
。
步骤功能可以与标志/选项suite
和suite
+ case/testcase
一起使用,但不能与之一起使用dir
。
8.8测试规范
一般描述
指定要测试什么的最灵活的方法是使用测试规范,这是一系列Erlang术语。这些术语通常在一个或多个文本文件中声明(请参阅参考资料ct:run_test/1
),但也可以通过Common Test
列表的形式传递(参见参考资料ct:run_testspec/1
)。有两种常用术语:配置术语和测试规范术语。
通过配置术语,例如可以执行以下操作:
- 标记测试运行(类似于
ct_run -label
)。
- 在开始测试之前评估任何表达式。
- 导入配置数据(类似于
ct_run -config/-userconfig
)。
- 指定顶级HTML日志目录(类似于
ct_run -logdir
)。
- 启用代码覆盖率分析(类似于
ct_run -cover
)。
- 安装
Common Test Hooks
(类似于ct_run -ch_hooks
)。
- 安装
event_handler
插件(类似于ct_run -event_handler
)。
- 指定要传递给编译器以进行自动编译的include目录(类似于
ct_run -include
)。
- 禁用自动编译功能(类似于
ct_run -no_auto_compile
)。
- 设置详细级别(类似于
ct_run -verbosity
)。
配置术语可以与ct_run
开始标志或ct:run_test/1
选项结合使用。对于某些标志/选项和术语,结果是合并值(例如,配置文件,包括目录,详细级别和无提示连接)以及其他启动标志/选项覆盖测试规范术语(用于例如,日志目录,标签,样式表和自动编译)。
使用测试规范术语,可以准确地说明要运行哪些测试以及以何种顺序。测试术语指定一个或多个套件,一个或多个测试用例组(可能嵌套)或一个或多个组(或多个组)或套件中的一个或多个测试用例。
可以按顺序声明任意数量的测试术语。Common Test
默认情况下将术语编译成一个或多个测试,以在一次最终测试运行中执行。用于指定一组测试用例的术语“吞噬”仅指定这些用例的子集的术语。例如,合并一个指定要执行S套件中的所有案例的术语的结果与另一个术语仅指定S中的测试案例X和Y的结果是对S中的所有案例的测试。但是,如果术语指定测试S中的情况X和Y与在S中指定情况Z的术语合并,结果是S中的X,Y和Z的测试。为了禁止这种行为,即取而代之地在“脚本样”的方式,设定术语merge_tests
以false
在测试规范。
测试术语还可以指定要跳过的一个或多个测试套件,组或测试用例。跳过的套件,组和案例不会执行,并会显示在HTML日志文件中SKIPPED
。
使用多个测试规范文件
如果在启动时指定了多个测试规范文件(使用ct_run -spec file1 file2 ...
or ct:run_test([{spec, [File1,File2,...]}])
),则Common Test
可以对每个规范文件执行一次测试运行,或者在单次测试运行中加入文件并执行所有测试。第一种行为是默认行为。后者要求提供开始标记/选项join_specs
,例如run_test -spec ./my_tests1.ts ./my_tests2.ts -join_specs
。
加入多个规范,或单独运行它们,也可以通过(并且可以结合)测试规范文件包含来完成。
测试规格文件包含
有了这个术语specs
,测试规范可以包含其他规范。包含的规范可以与源规范结合使用,也可以用于生成单独的测试运行(与join_specs
上面的启动标志/选项一样)。
例子:
%% In specification file "a.spec"
{specs, join, ["b.spec", "c.spec"]}.
{specs, separate, ["d.spec", "e.spec"]}.
%% Config and test terms follow
...
在这个例子中,文件“b.spec”和“c.spec”中定义的测试术语与源规范“a.spec”中的术语(如果有的话)联合使用。包含规格“d.spec”和“e.spec”会产生两个独立的,独立的测试运行(每个包含的规范都有一个测试运行)。
选项join
并不意味着测试术语是合并的,只是所有测试都在一次测试中执行。
加入的规范共享通用配置设置,例如config
文件或include
目录列表。对于不能组合的配置(例如logdir
or的设置)verbosity
,由用户确定在连接测试规格时不会发生冲突。包含在选项中的规范separate
不会与源规范共享配置设置。例如,如果包含的规范中存在冲突的配置设置,这使得它们无法加入,这很有用。
如果{merge_tests,true}
在源规范(这是默认设置)中设置,则在连接的规范中的术语与源规范中的术语合并(根据merge_tests
前面的描述)。
注意,它始终是merge_tests
源规范中与其他规范结合使用的设置。举例来说,举例说,一个具有测试TA1和TA2的源规范A已经{merge_tests,false}
设置,并且它包括另一个规范B,其具有已经{merge_tests,true}
设置的测试TB1和TB2 。结果是测试系列TA1,TA2,merge(TB1,TB2)
被执行。相反的merge_tests
设置会导致测试系列merge(merge(TA1,TA2),TB1,TB2)
。
这个术语specs
可以用来嵌套规范,也就是说,一个规范包含其他规范,而其他规范又包含其他规范,因此不包含其他规范
测试用例组
当指定测试用例组时,结果测试执行功能init_per_group
,然后执行所有测试用例和子组(包括它们的配置功能),最后执行功能end_per_group
。此外,如果指定了组中的特定测试用例,init_per_group
并且end_per_group
针对该组讨论,则会被调用。如果指定了(作为Suite:group/0
)另一个组的子组的组(作为另一个组的子组),(或者如果子组的特定测试用例是),则Common Test
调用顶级组和所讨论的子组的配置函数(使得可以通过配置数据init_per_suite
一直到子组中的测试用例)。
测试规范使用相同的机制通过名称和路径指定测试用例组,如部分中Test Case Group Execution
所述,添加了元素GroupSpec
。
元素GroupSpec
可以指定重写组定义(即,in groups/0
)中的组的执行属性。子组的执行属性也可能被覆盖。此功能可以在执行时更改组的属性,而无需编辑测试套件。列表中的group
元素具有相同的功能Suite:all/0
。有关详细信息和示例,请参见部分Test Case Groups
。
测试规范语法
测试规范可用于在单个测试主机环境和分布式Common Test
环境(大规模测试)中运行测试。术语init
中的节点参数仅与后者有关(请参见Test Specifications
大规模测试中的部分)。有关各种术语的详细信息,请参阅“用户指南”中的相应部分,例如:
- 所述
ct_runprogram
可用的开始标志的概述(大多数标志具有相应的配置术语)
Logging
(对于术语verbosity
,stylesheet
,basic_html
和esc_chars
)
External Configuration Data
(用于条款config
和userconfig
)
Event Handling
(为event_handler
期限)
Common Test Hooks
(期限ct_hooks
)
配置条款:
{merge_tests, Bool}.
{define, Constant, Value}.
{specs, InclSpecsOption, TestSpecs}.
{node, NodeAlias, Node}.
{init, InitOptions}.
{init, [NodeAlias], InitOptions}.
{label, Label}.
{label, NodeRefs, Label}.
{verbosity, VerbosityLevels}.
{verbosity, NodeRefs, VerbosityLevels}.
{stylesheet, CSSFile}.
{stylesheet, NodeRefs, CSSFile}.
{silent_connections, ConnTypes}.
{silent_connections, NodeRefs, ConnTypes}.
{multiply_timetraps, N}.
{multiply_timetraps, NodeRefs, N}.
{scale_timetraps, Bool}.
{scale_timetraps, NodeRefs, Bool}.
{cover, CoverSpecFile}.
{cover, NodeRefs, CoverSpecFile}.
{cover_stop, Bool}.
{cover_stop, NodeRefs, Bool}.
{include, IncludeDirs}.
{include, NodeRefs, IncludeDirs}.
{auto_compile, Bool},
{auto_compile, NodeRefs, Bool},
{abort_if_missing_suites, Bool},
{abort_if_missing_suites, NodeRefs, Bool},
{config, ConfigFiles}.
{config, ConfigDir, ConfigBaseNames}.
{config, NodeRefs, ConfigFiles}.
{config, NodeRefs, ConfigDir, ConfigBaseNames}.
{userconfig, {CallbackModule, ConfigStrings}}.
{userconfig, NodeRefs, {CallbackModule, ConfigStrings}}.
{logdir, LogDir}.
{logdir, NodeRefs, LogDir}.
{logopts, LogOpts}.
{logopts, NodeRefs, LogOpts}.
{create_priv_dir, PrivDirOption}.
{create_priv_dir, NodeRefs, PrivDirOption}.
{event_handler, EventHandlers}.
{event_handler, NodeRefs, EventHandlers}.
{event_handler, EventHandlers, InitArgs}.
{event_handler, NodeRefs, EventHandlers, InitArgs}.
{ct_hooks, CTHModules}.
{ct_hooks, NodeRefs, CTHModules}.
{enable_builtin_hooks, Bool}.
{basic_html, Bool}.
{basic_html, NodeRefs, Bool}.
{esc_chars, Bool}.
{esc_chars, NodeRefs, Bool}.
{release_shell, Bool}.
测试术语:
{suites, Dir, Suites}.
{suites, NodeRefs, Dir, Suites}.
{groups, Dir, Suite, Groups}.
{groups, NodeRefs, Dir, Suite, Groups}.
{groups, Dir, Suite, Groups, {cases,Cases}}.
{groups, NodeRefs, Dir, Suite, Groups, {cases,Cases}}.
{cases, Dir, Suite, Cases}.
{cases, NodeRefs, Dir, Suite, Cases}.
{skip_suites, Dir, Suites, Comment}.
{skip_suites, NodeRefs, Dir, Suites, Comment}.
{skip_groups, Dir, Suite, GroupNames, Comment}.
{skip_groups, NodeRefs, Dir, Suite, GroupNames, Comment}.
{skip_cases, Dir, Suite, Cases, Comment}.
{skip_cases, NodeRefs, Dir, Suite, Cases, Comment}.
类型:
Bool = true | false
Constant = atom()
Value = term()
InclSpecsOption = join | separate
TestSpecs = string() | [string()]
NodeAlias = atom()
Node = node()
NodeRef = NodeAlias | Node | master
NodeRefs = all_nodes | [NodeRef] | NodeRef
InitOptions = term()
Label = atom() | string()
VerbosityLevels = integer() | [{Category,integer()}]
Category = atom()
CSSFile = string()
ConnTypes = all | [atom()]
N = integer()
CoverSpecFile = string()
IncludeDirs = string() | [string()]
ConfigFiles = string() | [string()]
ConfigDir = string()
ConfigBaseNames = string() | [string()]
CallbackModule = atom()
ConfigStrings = string() | [string()]
LogDir = string()
LogOpts = [term()]
PrivDirOption = auto_per_run | auto_per_tc | manual_per_tc
EventHandlers = atom() | [atom()]
InitArgs = [term()]
CTHModules = [CTHModule |
{CTHModule, CTHInitArgs} |
{CTHModule, CTHInitArgs, CTHPriority}]
CTHModule = atom()
CTHInitArgs = term()
Dir = string()
Suites = atom() | [atom()] | all
Suite = atom()
Groups = GroupPath | [GroupPath] | GroupSpec | [GroupSpec] | all
GroupPath = [GroupName]
GroupSpec = GroupName | {GroupName,Properties} | {GroupName,Properties,GroupSpec}
GroupName = atom()
GroupNames = GroupName | [GroupName]
Cases = atom() | [atom()] | all
Comment = string() | ""
config
上面的术语之间的区别在于ConfigDir
,ConfigBaseNames
是基本名称的列表,即没有目录路径。ConfigFiles
必须是全名,包括路径。例如,以下两个术语具有相同的含义:
{config, ["/home/testuser/tests/config/nodeA.cfg",
"/home/testuser/tests/config/nodeB.cfg"]}.
{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.
注
在测试规范中指定的任何相对路径相对于包含测试规范文件的目录(如果ct_run -spec TestSpecFile ...
或ct:run:test([{spec,TestSpecFile},...])
执行测试)。
如果ct:run:testspec(TestSpec)
执行测试,则路径相对于顶级日志目录。
常数
术语define
引入了用于替换名称的恒定Constant
带Value
,无论它在测试规范中找到。这个替换发生在通过测试规范的初始迭代期间。常量可以在测试规范中的任何地方使用,例如,在任何列表和元组中,甚至在字符串中以及在其他常量定义的值部分内。常量也可以是节点名称的一部分,但这是常量可以成为原子的一部分的唯一位置。
注
出于可读性起见,常量的名称必须始终以大写字母,或开始$
,?
或_
。这意味着它必须始终单引号(因为常数名称是原子,而不是文本)。
常量的主要好处是它们可以用来减小长字符串的大小(并避免重复),比如文件路径。
例子:
%% 1a. no constant
{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, "/home/testuser/tests/suites", all}.
%% 1b. with constant
{define, 'TESTDIR', "/home/testuser/tests"}.
{config, "'TESTDIR'/config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, "'TESTDIR'/suites", all}.
%% 2a. no constants
{config, [testnode@host1, testnode@host2], "../config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, [testnode@host1, testnode@host2], "../suites", [x_SUITE, y_SUITE]}.
%% 2b. with constants
{define, 'NODE', testnode}.
{define, 'NODES', ['NODE'@host1, 'NODE'@host2]}.
{config, 'NODES', "../config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, 'NODES', "../suites", [x_SUITE, y_SUITE]}.
常量使测试规范术语alias
在以前的版本中是Common Test
冗余的。该术语已被弃用,但在即将Common Test
发布的版本中仍然受支持。尽管如此alias
,define
强烈推荐替换术语。这种替换的例子如下:
%% using the old alias term
{config, "/home/testuser/tests/config/nodeA.cfg"}.
{alias, suite_dir, "/home/testuser/tests/suites"}.
{groups, suite_dir, x_SUITE, group1}.
%% replacing with constants
{define, 'TestDir', "/home/testuser/tests"}.
{define, 'CfgDir', "'TestDir'/config"}.
{define, 'SuiteDir', "'TestDir'/suites"}.
{config, 'CfgDir', "nodeA.cfg"}.
{groups, 'SuiteDir', x_SUITE, group1}.
常数也可以很好地代替术语node
,但这仍然具有声明性值,主要与NodeRefs == all_nodes
(见Types
)结合使用。
例
这里有一个简单的测试规范示例:
{define, 'Top', "/home/test"}.
{define, 'T1', "'Top'/t1"}.
{define, 'T2', "'Top'/t2"}.
{define, 'T3', "'Top'/t3"}.
{define, 'CfgFile', "config.cfg"}.
{logdir, "'Top'/logs"}.
{config, ["'T1'/'CfgFile'", "'T2'/'CfgFile'", "'T3'/'CfgFile'"]}.
{suites, 'T1', all}.
{skip_suites, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
{skip_cases, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
{skip_cases, 'T1', t1C_SUITE, [test1], "Ignore"}.
{suites, 'T2', [t2B_SUITE,t2C_SUITE]}.
{cases, 'T2', t2A_SUITE, [test4,test1,test7]}.
{skip_suites, 'T3', all, "Not implemented"}.
该示例指定以下内容:
- 指定的
logdir
目录用于存储HTML日志文件(在标有节点名称,日期和时间的子目录中)。
- 为测试导入指定测试系统配置文件中的变量。
- 第一次运行测试包括系统的所有套件
t1
。套房,t1B
并被t1D
排除在测试之外。测试用例test3
以及test4
int1A
和test1
case在t1C
也被排除在测试之外。
- 第二个测试是为了系统
t2
。包括的套房是t2B
和t2C
。测试用例test4
,test1
以及test7
在浴室t2A
也包括在内。测试用例按照指定的顺序执行。
- 最后一次运行的测试是针对系统
t3
。在这里,所有套件都会被跳过,这在日志文件中有明确的说明。
原语
使用术语init
,可以为测试规范中定义的节点指定初始化选项。可以选择启动节点并评估节点上的任何功能。有关详细信息,请参见Automatic Startup of Test Target Nodes
使用通用测试进行大规模测试。
用户专用术语
用户可以提供包括(用于Common Test
)无法识别的术语的测试规范。如果需要,使用标志-allow_user_terms
开始测试ct_run
。这迫使Common Test
忽略无法识别的条款。在此模式下,Common Test
无法像扫描仪以默认模式运行一样有效地检查错误规格。如果ct:run_test/1
用于启动测试,轻松扫描仪模式由元组启用{allow_user_terms,true}
。
阅读试验规范术语
可以查看当前测试规范中的术语(即,用于配置和运行当前测试的规范)。该函数get_testspec_terms()
返回所有测试规范术语(配置术语和测试术语)get_testspec_terms(Tags)
的列表,并返回匹配标签(或多个标签)的术语(或术语列表)Tags
。
例如,在测试规范中:
...
{label, my_server_smoke_test}.
{config, "../../my_server_setup.cfg"}.
{config, "../../my_server_interface.cfg"}.
...
例如,在测试套件或Common Test Hook
职能:
...
[{label,[{_Node,TestType}]}, {config,CfgFiles}] =
ct:get_testspec_terms([label,config]),
[verify_my_server_cfg(TestType, CfgFile) || {Node,CfgFile} <- CfgFiles,
Node == node()];
...
8.9从基于Web的GUI运行测试
基于Web的GUI,虚拟测试服务器(VTS),随ct_run
程序启动。在GUI中,您可以加载配置文件并选择要运行的目录,套件和案例。您还可以在启动基于Web的GUI时在命令行上声明配置文件,目录,套件和案例。
例子:
ct_run -vts
- ct_run -vts -config <configfilename>
- ct_run -vts -config <configfilename> -suite <suitewithfullpath> -case <casename>
在GUI中,您可以运行测试并查看结果和日志。
ct_run -vts
尝试Common Test
在现有的Web浏览器窗口中打开起始页面,或者在浏览器未运行时启动浏览器。可以使用浏览器启动命令选项指定要启动的浏览器:
ct_run -vts -browser <browser_start_cmd>
例子:
$ ct_run -vts -browser 'firefox&'
注
浏览器必须作为单独的OS进程运行,否则VTS挂起。
如果未指定特定的浏览器启动命令,则Firefox是Unix平台上的默认浏览器,Windows上是Internet Explorer。如果Common Test
未能自动启动浏览器,或者none
指定为-browser
(即-browser none
)的值,请手动启动您最喜爱的浏览器,然后键入Common Test
显示在shell中的URL 。
8.10日志文件
随着测试套件的执行继续进行,以下面四种不同方式记录事件:
- 给操作员控制台的文本。
- 与套件相关的信息被发送到主日志文件。
- 与案例相关的信息被发送到次要日志文件。
- HTML概述日志文件将根据测试结果更新。
- 从指定目录执行的所有运行的链接写入名为日志,
all_runs.html
并将直接链接到所有测试(最新结果)写入顶层index.html
。
通常情况下,运营商可能运行数百或数千个测试用例,但不希望在控制台中填写特定测试用例的详细信息或打印输出。默认情况下,操作员只能看到以下内容:
- 测试已经开始的确认信息以及总共执行多少测试用例的信息。
- 关于每个失败的测试用例的小记录。
- 所有运行测试用例的摘要。
- 测试运行完成时的确认。
- 一些特殊信息,例如错误报告,进度报告,以及写入
erlang:display/1
或io:format/3
专门写入接收方以外的standard_io
(例如默认组领导进程user
)的打印输出。
要深入了解一般结果或特定测试用例的结果,操作员可以通过遵循HTML演示文稿中的链接并阅读主要或次要日志文件来完成此操作。“all_runs.html”页面是一个很好的起点。它位于logdir
每个测试运行并包含一个链接,包括快速概览(包含日期和时间,节点名称,测试次数,测试名称和测试结果总数)。
为每次测试运行编写一个“index.html”页面(即,存储在ct_run
标有节点名称,日期和时间的目录中)。该文件提供了在同一测试运行中执行的所有单个测试的概述。测试名称遵循以下约定:
TopLevelDir.TestDir
(所有套件都在TestDir
执行中)
TopLevelDir.TestDir:suites
(执行特定套件)
TopLevelDir.TestDir.Suite
(所有案件在Suite
执行中)
TopLevelDir.TestDir.Suite:cases
(执行特定的测试用例)
TopLevelDir.TestDir.Suite.Case
(只Case
执行)
“测试运行索引”页面包含指向Common Test
框架日志文件的链接,其中写入了有关导入的配置数据和一般测试进度的信息。此日志文件对于在执行期间获取有关测试运行的快照信息非常有用。分析测试结果或调试测试套件时也很有帮助。
“测试运行索引”页面指示测试是否缺少套件(即Common Test
未能编译的套件)。缺失的套件的名称可以在Common Test
框架日志文件中找到。
主要的日志文件显示测试运行的详细报告。它包括测试套件和测试用例名称,执行时间,失败的确切原因等等。这些信息在文本文件和HTML表示文件中均可用。HTML文件显示了一个总结,可以很好地概述测试运行。它还具有指向每个单独测试用例日志文件的链接,以便使用HTML浏览器进行快速查看。
次要日志文件包含每个测试用例的完整详细信息,每个测试用例都在单独的文件中。这样,即使测试用例集发生更改,也可以直接比较最近的测试结果和以前的测试结果。如果应用程序SASL正在运行,则它的日志也会被打印到当前次要日志文件cth_log_redirect built-in hook
。
在执行测试用例时,可以读取次要日志文件的全名(即包含绝对目录路径的文件的名称)。它作为在元组值{tc_logfile,LogFileName}
的Config
列表(这意味着它也可以由一个前或后读Common Test Hook
功能)。另外,在测试用例开始时,这些数据将与事件一起发送到任何已安装的事件处理程序。有关详情,请参阅部分Event Handling
。
日志文件在测试运行期间连续写入,链接总是在测试开始时最初创建。因此,只需刷新HTML浏览器中的页面,就可以跟踪测试进度。统计总数在测试完成后才会显示。
日志选项
使用启动标志logopts
选项可以指定日志行为的某些方面。以下选项可用:
no_src
测试套件源代码的HTML版本在测试运行期间不会生成(因此在日志文件系统中不可用)。
no_nl
Common Test
不会将一个换行符添加(\n)
到它从一个调用接收到的输出字符串的末尾,例如io:format/2
,并将其打印到测试用例日志中。
例如,如果测试开始时:
$ ct_run -suite my_SUITE -logopts no_src
然后在测试期间通过连续调用进行的打印输出在io:format("x")
测试用例日志中显示为:
xxx
而不是每个x
打印在新行上,这是默认行为。
HTML表格列的排序
通过单击任何表的列标题中的名称(例如,“Ok”,“Case”,“Time”等),表格行按照对于类型值有意义的顺序进行排序(例如,“Ok”或“Time”的数字,“Case”的字母数字)。排序通过JavaScript代码执行,并自动插入到HTML日志文件中。为此实现Common Test
使用jQuery
库和tablesorter
插件,以及定制的排序功能。
意外的I/O日志
测试套件概述页面包含指向意外I / O日志的链接。在此日志中,Common Test
保存使用ct:log/1,2,3,4,5
和进行的打印输出ct:pal/1,2,3,4,5
,以及捕获的系统错误和进度报告,这些报告不能与特定测试用例相关联,因此无法写入单个测试用例日志文件。例如,如果日志打印输出是由外部进程(而不是测试用例进程)完成的,或者
如果出现错误或
进度报告,则在短时间间隔Common Test
内未执行测试用例或
配置功能时,或
同时Common Test
当前正在执行一个并行测试病例组。
测试前后I/O测井
该Common Test
框架日志页面包含指向前和测试后I / O日志。在此日志中,Common Test
保存使用ct:log/1,2,3,4,5
和执行的打印输出ct:pal/1,2,3,4,5
,以及捕获在测试运行之前和之后发生的系统错误和进度报告。这样的例子是来自CT钩子初始化或终止函数的打印输出,或者当从CT钩子初始化函数启动OTP应用程序时生成的进度报告。另一个例子是当外部应用程序从CT挂钩终止函数中停止时,由于失败而生成的错误报告。这些示例中的所有信息都以“前后测试I / O日志”结尾。有关如何使测试运行与外部用户应用程序同步的更多信息,请参阅Synchronizing
常见测试挂钩部分。
注
记录到文件ct:log/1,2,3,4,5
或ct:pal/1,2,3,4,5
仅在Common Test
运行时运行。ct:pal/1,2,3,4,5
然而,打印输出总是显示在屏幕上。
删除旧日志
Common Test可以自动删除旧日志。这是用keep_logs选项指定的。此选项的默认值是all,这意味着没有日志被删除。如果该值设置为整数N,则Common Test删除ct_run.<timestamp>除N最新之外的所有目录。
8.11 HTML样式表
Common Test
使用HTML样式表(CSS文件)来控制测试运行期间生成的HTML日志文件的外观。如果日志文件没有在您选择的浏览器中正确显示,或者您更喜欢Common Test
日志的更原始(“ v1.6”)外观,请使用开始标志/选项:
basic_html
这将禁止使用样式表和JavaScript(请参阅参考资料Sorting HTML Table Columns
)。
Common Test
包括一个可选
功能,允许用户自定义打印输出的HTML样式表。这个函数在ct
打印到测试用例HTML日志文件(log/3,4,5
和pal/3,4,5
)时被接受Category
为第一个参数。使用此参数可以指定一个类别,该类别可以映射到div
CSS规则集中的命名选择器。这很有用,特别是根据打印输出的类型(或原因)对文本进行不同的着色。假设您需要测试系统配置信息的一种特定背景颜色,测试系统状态信息不同的背景颜色,以及测试用例功能检测到的错误。相应的样式表可以如下所示:
div.sys_config { background:blue }
div.sys_state { background:yellow }
div.error { background:red }
通用测试打印嵌套在指定元素下的元素内部ct:log/3,4,5
或ct:pal/3,4,5
内部的文本。由于选择器对于属性具有预定义的CSS规则(在文件中),并且如果用户想要更改任何预定义的属性设置,则必须将新规则添加到用户样式表中。例:predivprect_default.csscolorfont-familyfont-sizepre
div.error pre { color:white }
在这里,使用白色文本代替div.error
打印输出的默认黑色(并且不会影响其他属性设置pre
)。
要安装CSS文件(Common Test
将定义内联在HTML代码中),可以在执行时提供文件名ct_run
。
例子:
$ ct_run -dir $TEST/prog -stylesheet $TEST/styles/test_categories.css
使用标志安装的CSS文件中的类别在-stylesheet
全局测试级别上,因为它们可以在测试运行的任何套件中使用。
样式表也可以安装在每个套件和每个测试用例基础上。
例子:
-module(my_SUITE).
...
suite() -> [..., {stylesheet,"suite_categories.css"}, ...].
...
my_testcase(_) ->
...
ct:log(sys_config, "Test node version: ~p", [VersionInfo]),
...
ct:log(sys_state, "Connections: ~p", [ConnectionInfo]),
...
ct:pal(error, "Error ~p detected! Info: ~p", [SomeFault,ErrorInfo]),
ct:fail(SomeFault).
如果样式表按照本例安装,则类别对于所讨论的套件是私有的。它们可以被套件中的所有测试用例使用,但不能被其他套件使用。套件私人样式表(如果指定)用于全局样式表(使用标志指定-stylesheet
)。样式表元组(suite/0
如上所述)也可以从测试用例信息函数返回。在这种情况下,样式表中指定的类别只能用于特定的测试用例。测试用例私人样式表用于套件或全局级样式表。
例如,在元组中{stylesheet,CSSFile}
,如果CSSFile
使用路径指定,"$TEST/styles/categories.css"
则使用该全名来查找文件。但是,例如,如果只指定文件名,categories.css
则假定CSS文件位于data_dir
套件的数据目录中。推荐使用后者,因为与套件中的硬编码路径名相比,它是便携式的。
Category
上例中的参数可以具有值(原子)sys_config
(蓝色背景),sys_state
(黄色背景)或error
(红色背景上的白色文本)。
8.12重复测试
您可以命令Common Test
重复您指定的测试。您可以选择多次重复测试,重复测试一段时间,或重复测试,直到达到特定的停止时间。如果重复受时间控制,Common Test
则可以指定超时时间。无论是Common Test
执行当前运行所有测试前停止,或者当前的测试作业完成时停止。重复可以通过ct_run
启动标志或ct:run:test/1
选项列表参数中的元组来激活。标志(括号中的选项)如下所示:
-repeat N {repeat,N}),
其中N是
一个正整数
-duration DurTime {duration,DurTime}),
当DurTime持
续时间
-until StopTime {until,StopTime}),
当StopTime为
结束时间
-force_stop {force_stop,true})
-force_stop skip_rest {force_stop,skip_rest})
DurTime
持续时间被指定为HHMMSS
,例如-duration 012030
或{duration,"012030"}
,这意味着测试被执行并且(如果时间允许的话)重复,直到1小时20分钟和30秒之后发生超时。 StopTime
结束时间可以被指定为HHMMSS
,然后被解释为今天(或可能明天)的时间,但也可以被指定YYMoMoDDHHMMSS
为例如-until 071001120000
或{until,"071001120000"}
。这意味着测试将在2007年10月1日12点之前重复执行(如果时间允许)。
发生超时时,Common Test
不要中止正在进行的测试用例,因为这会使SUT处于未定义的状态(可能是坏的状态)。相反Common Test
,默认情况下,在停止之前完成当前的测试运行。如果force_stop
指定了标志,则Common Test
在当前测试作业完成时停止。如果force_stop
指定了标志skip_rest
,Common Test
则只完成当前测试用例并跳过测试作业中剩余的测试。
注
由于Common Test
总是至少完成当前的测试用例,所以使用duration
or 指定的时间until
永远不会确定。
每次重复测试运行的日志文件都以正常Common Test
方式保存(如前所述)。
Common Test
稍后可能会支持一个可选功能,以仅存储重复测试运行的最后一组(也可能是第一组)日志,但是现在用户必须注意,如果长时间重复测试,请不要用尽磁盘空间。
对于作为重复会话一部分的每个测试运行,关于特定测试运行的信息都将打印在Common Test
框架日志中。信息包括重复次数,剩余时间等。
例1:
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -duration 001000 -force_stop
这里,测试目录中的套件to1
,随后是套件to2
,在一次测试运行中执行。10分钟后发生超时事件。只要还有时间,Common Test
重复测试运行(即从测试开始to1
)。超时后,Common Test
停止当前工作完成(由于国旗force_stop
)。因此,指定的测试运行可以在测试之后to1
和测试之前中止to2
。
例2:
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -duration 001000 -forces_stop skip_rest
这里,运行与例1相同的测试,但标志force_stop
设置为skip_rest
。如果在执行目录中的测试时发生超时to1
,to1
则跳过其余的测试用例,并且在to2
另一次不运行测试时中止测试。如果在目录中执行测试时发生超时to2
,to2
则跳过其余的测试用例,并中止测试。
例3:
$ date
Fri Sep 28 15:00:00 MEST 2007
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -until 160000
在此,执行与前面示例中相同的测试运行(并且可能重复)。然而,当超时发生时,1小时后,Common Test
完成整个测试运行停止之前(即,两者to1
并to2
总是在相同的测试运行中执行)。
例4:
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -repeat 5
在这里,测试运行(包括测试to1
和to2
重复测试)重复五次。
注
不要将此功能与repeat
测试用例组的属性混淆。这里描述的选项用于重复执行整个测试运行,而repeat
测试用例组的属性使得可以在一个套件中重复执行一组测试用例。有关后者的更多信息,请参见Test Case Groups
编写测试套件一节。
8.13无声连接
在协议处理过程Common Test
,通过实现ct_telnet
,ct_ssh
,ct_ftp
,等等,做详细的印刷测试用例日志。这可以通过标志关闭-silent_connections
:
ct_run -silent_connections [conn_types]
这里conn_types
指定SSH,Telnet,FTP,RPC和/或SNMP。
例1:
ct_run ... -silent_connections ssh telnet
这会关闭SSH和Telnet连接的日志记录。
例2:
ct_run ... -silent_connections
这将关闭所有连接类型的日志记录。
即使已针对相关连接类型禁止记录,仍会始终打印致命通信错误和重新连接尝试。但是,发送和接收数据等操作是静默执行的。
silent_connections
也可以在测试套件中指定。这是通过{silent_connections,ConnTypes}
在suite/0
测试用例信息列表中返回一个元组来完成的。如果ConnTypes
是原子列表(SSH,Telnet,FTP,RPC和/或SNMP),则禁止任何相应连接的输出。默认情况下,对于未指定类型的任何连接启用完全日志记录ConnTypes
。因此,如果ConnTypes
是空列表,则为所有连接启用日志记录。
例3:
-module(my_SUITE).
suite() -> [..., {silent_connections,[telnet,ssh]}, ...].
...
my_testcase1() ->
[{silent_connections,[ssh]}].
my_testcase1(_) ->
...
my_testcase2(_) ->
...
在这个例子中,suite/0
告诉Common Test
抑制来自Telnet和SSH连接的打印输出。这对所有测试用例都有效。但是,my_testcase1/0
指定对于此测试用例,仅SSH将保持沉默。结果是my_testcase1
得到Telnet信息(如果有)打印在日志中,但不是SSH信息。my_testcase2
没有从任何连接打印信息。
silent_connections
也可以用测试规范中的术语指定(请参阅Test Specifications
运行测试和分析结果一节中的部分)。与开始标志/选项silent_connections
一起提供的连接与测试规范中列出的任何连接合并。
开始标志/选项silent_connections
和测试规范术语覆盖测试套件中信息功能所做的任何设置。
注
在当前Common Test
版本中,该silent_connections
功能仅适用于Telnet和SSH连接。未来Common Test
版本可以添加对其他连接类型的支持。