在线文档教程

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_suitesct:run_test/1选项进行修改{abort_if_missing_suites,TrueOrFalse}。如果abort_if_missing_suites设置为true,则某些套件无法编译时,测试运行会立即停止。

任何与作为测试一部分的套件位于相同测试对象目录中的帮助模块(即,名称不以“_SUITE”结尾的常规Erlang模块)也会自动编译。帮助模块不会被误认为测试套件(除非它具有“_SUITE”名称)。无论目录中的所有或唯一特定套件是否为测试的一部分,都会编译特定测试对象目录中的所有帮助模块。

如果测试套件或帮助模块包含存储在除测试目录之外的其他位置的头文件,则可以通过使用-include带有标志ct_runinclude带有选项的指定来包含这些目录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_compilewith 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

标志dirsuitegroup/case可以组合。例如,要运行x_SUITEy_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_shelltrue(在调用ct:run_test/1或使用相应的测试规范术语,稍后介绍)。这使得Common Test在测试套件编译阶段之后立即释放shell。为了达到这个目的,一个测试运行器进程被产生以控制测试执行。效果是这样的ct:run_test/1 返回此进程的pid而不是测试结果,而测试结果将在测试运行结束时打印到tty。

要使用的功能ct:break/1,2ct:continue/0,1release_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

给定一个组名,比如gCommon Test搜索导致所有路径g。按路径指的是一系列嵌套组,必须遵循才能从顶层组获取g。要在组中执行测试用例gCommon 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。然后,它调用测试用例tc1tc5g4,最后全部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查找并执行两个测试,一个用于从路径top2sub2X2通过sub21,一个来自top2sub2X2通过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_telnetct_ftp)将从Erlang shell中调用,则首先需要使用配置数据ct:require/1,2。这相当于requireTest 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/1end_per_suite/1init_per_group/2end_per_group/2init_per_testcase/2end_per_testcase/2

Common Test启用调试器自动附加功能,这意味着对于每个新开始执行的解释测试用例函数,都会自动弹出一个新的跟踪窗口(每个测试用例在专用的Erlang进程上执行)。每当新的测试用例开始时,就Common Test尝试关闭先前测试用例的不活动跟踪窗口。但是,如果您希望Common Test保留不活动的跟踪窗口,请使用选项keep_inactive

步骤功能可以与标志/选项suitesuite+ 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_testsfalse在测试规范。

测试术语还可以指定要跳过的一个或多个测试套件,组或测试用例。跳过的套件,组和案例不会执行,并会显示在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目录列表。对于不能组合的配置(例如logdiror的设置)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(对于术语verbositystylesheetbasic_htmlesc_chars

  • External Configuration Data(用于条款configuserconfig

  • 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上面的术语之间的区别在于ConfigDirConfigBaseNames是基本名称的列表,即没有目录路径。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引入了用于替换名称的恒定ConstantValue,无论它在测试规范中找到。这个替换发生在通过测试规范的初始迭代期间。常量可以在测试规范中的任何地方使用,例如,在任何列表和元组中,甚至在字符串中以及在其他常量定义的值部分内。常量也可以是节点名称的一部分,但这是常量可以成为原子的一部分的唯一位置。

出于可读性起见,常量的名称必须始终以大写字母,或开始$?_。这意味着它必须始终单引号(因为常数名称是原子,而不是文本)。

常量的主要好处是它们可以用来减小长字符串的大小(并避免重复),比如文件路径。

例子:

%% 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发布的版本中仍然受支持。尽管如此aliasdefine强烈推荐替换术语。这种替换的例子如下:

%% 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以及test4in t1Atest1case在 t1C也被排除在测试之外。

  • 第二个测试是为了系统t2。包括的套房是t2Bt2C。测试用例test4test1以及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/1io: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,5ct: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,5pal/3,4,5)时被接受Category为第一个参数。使用此参数可以指定一个类别,该类别可以映射到divCSS规则集中的命名选择器。这很有用,特别是根据打印输出的类型(或原因)对文本进行不同的着色。假设您需要测试系统配置信息的一种特定背景颜色,测试系统状态信息不同的背景颜色,以及测试用例功能检测到的错误。相应的样式表可以如下所示:

div.sys_config { background:blue } div.sys_state { background:yellow } div.error { background:red }

通用测试打印嵌套在指定元素下的元素内部ct:log/3,4,5ct: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_restCommon Test则只完成当前测试用例并跳过测试作业中剩余的测试。

由于Common Test总是至少完成当前的测试用例,所以使用durationor 指定的时间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。如果在执行目录中的测试时发生超时to1to1则跳过其余的测试用例,并且在to2另一次不运行测试时中止测试。如果在目录中执行测试时发生超时to2to2则跳过其余的测试用例,并中止测试。

例3:

$ date Fri Sep 28 15:00:00 MEST 2007 $ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -until 160000

在此,执行与前面示例中相同的测试运行(并且可能重复)。然而,当超时发生时,1小时后,Common Test完成整个测试运行停止之前(即,两者to1to2总是在相同的测试运行中执行)。

例4:

$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -repeat 5

在这里,测试运行(包括测试to1to2重复测试)重复五次。

不要将此功能与repeat测试用例组的属性混淆。这里描述的选项用于重复执行整个测试运行,而repeat测试用例组的属性使得可以在一个套件中重复执行一组测试用例。有关后者的更多信息,请参见Test Case Groups编写测试套件一节。

8.13无声连接

在协议处理过程Common Test,通过实现ct_telnetct_sshct_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版本可以添加对其他连接类型的支持。