PHP 官方 自动化 测试 方法 简述 以下介绍以 PHP 最新 官方 版本 5.2.8 的源码在 LINUX 系统平台上的分析为例展开。首先来看一下 PHP 的 自动化 测试 脚本 PHPT 脚本。 自动化 测试 脚本 PHPT 示例 PHP 的 测试 脚本是以“ .phpt ”为后缀,包含 TEST,FILE
以下介绍以 PHP 最新官方版本 5.2.8 的源码在 LINUX 系统平台上的分析为例展开。首先来看一下 PHP 的自动化测试脚本 PHPT 脚本。
PHP 的测试脚本是以“ .phpt ”为后缀,包含 TEST,FILE,EXPECT 等多个段落的文件,简称 PHPT 。在各个段落中,TEST,FILE,EXPECT 是基本的段落,每个测试脚本都必须至少包括这三个段落。其中,TEST 段可以用来填写测试用例的名字; FILE 段是一个 PHP 脚本实现的测试用例; EXPECT 段则是测试用例的期待值。测试用例的运行中,PHP 将用被测试的 PHP 可执行对象去运行 FILE 段中的测试用例,用实际的结果去比对测试用例中 EXPECT 段所列的期待值;如果实际结果和期待值一致,则测试通过;如果不一致,则测试失败。
表 1 列出的是常用的段落名和其相应的填充内容说明。
段落名 | 填充内容 | 备注 |
---|---|---|
TEST | 测试用例名称 | 必填段落 |
ARGS | FILE 段的输入参数 | 选填段落 |
SKIPIF | 跳过这个测试的条件 | 选填段落 |
POST | 传入测试脚本的 POST 变量 | 选填段落。如果使用 POST 段,建议配合使用 SKIPIF 段,如: --SKIPIF-- |
GET | 传入测试脚本的 GET 变量 | 选填段落。如果使用 POST 段,建议配合使用 SKIPIF 段,如: --SKIPIF-- |
INI | 应用于测试脚本的 ini 设置 | 选填段落。例如 foo=bar 。其值可通过函数 ini_get(string name_entry) 获得。 |
FILE | 测试脚本语句 | 必填段落。应用 PHP 语言书写的脚本语句。其执行的结果将与 EXPECT* 段的期待值做对比。 |
EXPECT | 测试脚本的期待值 | 必填段落 |
EXPECTF | 测试脚本的期待值,可用函数 sscanf() 中的格式表达期待值 | EXPECT 段的变体 |
EXPECTREGEX | 测试脚本的期待值,可用正则式表达期待值 | EXPECT 段的变体 |
以官方包里自带的测试脚本 “ 001.phpt ” 为例(见清单 1),从 TEST 段的内容看来这是一个对 PHP 版本进行验证的测试用例。 SKIPIF 段的内容写在了 “ skipip.inc ” 文件里。在 FILE 段里,测试用例将环境变量 TEST_PHP_EXECUTABLE 里设置的那个 PHP 的版本打印出来,这个结果将和 EXPECTF 中的字串进行格式匹对。
--TEST-- version string --SKIPIF-- <?php include "skipif.inc"; ?> --FILE-- <?php $php = getenv('TEST_PHP_EXECUTABLE'); var_dump(`$php -n -v`); echo "Done\n"; ?> --EXPECTF-- string(%d) "PHP %s (cli) (built: %s)%s Copyright (c) 1997-20%d The PHP Group Zend Engine v%s, Copyright (c) 1998-20%d Zend Technologies " Done
在运行测试脚步前,首先要将被测试的 PHP 源码编译为可执行对象。
然后要导入若干环境变量。表 2 中介绍了主要的几个环境变量如何设置。
环境变量名 | 环境变量值 | 例子 |
---|---|---|
TEST_PHP_EXECUTABLE | 设定被测试对象 PHP,或者 “ auto ” 。当设置 “ auto ” 时,如果是 CGI 模式,即为 “ ./sapi/cgi/php-cgi ” ;如果是 CLI 模式,即为 “ ./sapi/cli/php ” 。 | TEST_PHP_EXECUTABLE= $HOME/php-5.2.8/sapi/cli/php |
TEST_PHP_DETAILED | 设定是否需要详细的日志输出。设置值为 1 或者 0 。 | TEST_PHP_DETAILED=1 |
TEST_PHP_USER | 设定是否需要特制的用户目录。 | TEST_PHP_DETAILED= “ /usr/test1 ” |
TEST_PHP_LOG_FORMAT |
设定日志的格式。设置值为 “ LEOD ” 子串的子集。其中 L 代表测试后需要生成 “ .log ” 文件,E 代表 “ .exp ” ,O 代表 “ .out ” ,D 代表 “ .diff ” 。 | TEST_PHP_LOG_FORMAT="LD" |
在本例中,在 Bash 环境中设置环境变量如下:
export HOME=/home/user_dir/ export TEST_PHP_EXECUTABLE=$HOME/php-5.2.8/sapi/cli/php export TEST_PHP_DETAILED=1 export TEST_PHP_LOG_FORMAT="LEOD"
经过这样设置后,被测试的 PHP 可执行对象就是放在目录 “ $HOME/php-5.2.8/sapi/cli/ ” 下编译好的那个 “ php ” 可执行文件。
执行测试前,还需将测试脚本 PHPT 编辑好,存为 “ .phpt ” 文件。这里以官方包里自带的测试脚本 “ 001.phpt ” 为例,运行如下:
bash-2.03$ cd $HOME/php-5.2.8/ bash-2.03$ $HOME/php-5.2.8/sapi/cli/php run-tests.php \ $HOME/php-5.2.8/sapi/cli/tests/001.phpt
如果该测试用例的实际输出与期待值一致,则在屏幕上输出测试结果如下:
===================================================================== CWD : /home/user_dir/php-5.2.8/sapi/cli/php PHP : /home/user_dir/php-5.2.8/sapi/cli/php PHP_SAPI : cli PHP_VERSION : 5.2.8 ZEND_VERSION: 2.1.0 PHP_OS : Linux rhas05 2.6.9-55.ELhugemem #1 SMP Fri Apr 20 17:20:11 EDT 2007 i686 i686 i386 GNU/Linux INI actual : More .INIs : Extra dirs : ===================================================================== Running selected tests. PASS Test version string [001.phpt] ===================================================================== Number of tests : 1 1 Tests skipped : 0 ( 0.0%) -------- Tests warned : 0 ( 0.0%) ( 0.0%) Tests failed : 0 ( 0.0%) ( 0.0%) Tests passed : 1 (100.0%) (100.0%) --------------------------------------------------------------------- Time taken : 0 seconds =====================================================================
如果该测试失败了,则除了屏幕输出失败结果外,当前运行目录下还会生成若干文件,以供用户分析测试失败的原因。生成的日志文件的种类是由环境变量 TEST_PHP_LOG_FORMAT 设定的,详见表 2 。如果设定的是 “ LEOD ” 则生成日志文件包括表 3 中列出的五种文件。
日志文件名 | 日志文件内容 | 对应的TEST_PHP_LOG_FORMAT里的设置 |
---|---|---|
001.out | 运行测试语句后得到的实际输出结果。 | O |
001.exp | 脚本中的期待结果,即测试脚本中 EXPECT* 段的内容。 | E |
001.log | 实际运行的输出结果和脚本中的期待结果,即 “ .exp ” 和 “ .out ” 的合集。 | L |
001.diff | 实际运行的输出结果和脚本中的期待结果通过 diff 命令得到比对后的结果。 | D |
001.php | 实际执行的 PHP 测试语句,在测试中解析测试脚本的 FILE 段得到。 | 总会生成 |
上面的例子是一次只运行一个脚本。 PHP 也支持多测试脚本一起运行。表 4 列出了三种 PHP 支持的测试方式。
测试方式 | 参数 | 举例 |
---|---|---|
只执行单个测试用例 | 测试脚本名 | 001.phpt 002.phpt |
执行某个目录下的测试用例 | 测试用例的目录名 | test_dir/ |
执行某个文件中列出的测试用例 | -r 加列举测试用例的文件名 | -r record_file |
回页首
在清单 3中的运行示例中,实际的执行语句是 “ $HOME/php-5.2.8/sapi/cli/php run-tests.php $HOME/php-5.2.8/sapi/cli/tests/001.phpt ” 。其中,“ 001.phpt ” 是测试脚本;“ run-tests.php ” 为 PHP 测试的驱动脚本,是官方脚本;而 “ $HOME/php-5.2.8/sapi/cli/php ” 是运行驱动脚本的 PHP 可执行对象。这里需要指出的一点是,环境变量 TEST_PHP_EXECUTABLE 中设置的 PHP 可执行对象和这里运行测试脚本中的 “ $HOME/php-5.2.8/sapi/cli/php ” 虽然指向的是同一个可执行对象,但其意义是不一样的。环境变量 TEST_PHP_EXECUTABLE 中设置的 PHP 是被测试对象,而运行测试中使用的 “ $HOME/php-5.2.8/sapi/cli/php ” 只是为了用来驱动测试脚本运行。
在图 1 中可以具体的看出 PHP 测试过程中两个 PHP 可执行对象及两个 PHP 脚本的关系。在测试的过程中,首先是由 “ $HOME/php-5.2.8/sapi/cli/php ” 去运行脚本 “ run-tests.php ” (第 1 步)。 在 “ run-tests.php ” 脚本中,将解析环境变量的值 “ TEST_PHP_EXECUTABLE =$HOME/php-5.2.8/sapi/cli/php ” (第 2 步)。这里 PHP 可执行对象是被测试的 PHP 。“ run-tests.php ” 脚本中还将把测试脚本 “ 001.phpt ” 中的 FILE 段解析为 PHP 脚本 “ 001.php ” (第 3 步), 用 “ TEST_PHP_EXECUTABLE ” 设置的那个 PHP 可执行对象去执行 “ 001.php ” (第 4 步)并得到实际输出结果,在比对实际输出结果和 EXPECT 段的期待结果后,输出测试结果(第 5 步)。以上运行过程可以从对 “ run-tests.php ” 脚本的分析中得出。
通过以上实例分析可以看出,PHP 官方测试的自动化主要依赖于 “ run-tests.php ” 脚本和测试用例脚本 PHPT 。而 “ run-tests.php ” 脚本正是 PHP 测试自动化框架的搭建者。从代码清单 5 中,可以略微看出 PHP 自动化测试框架的主要工作。
$test_cnt = count($test_files); if ($test_cnt) { putenv('NO_INTERACTION=1'); verify_config(); write_information($html_output); usort($test_files, "test_sort"); $start_time = time(); if (!$html_output) { echo "Running selected tests.\n"; } else { show_start($start_time); } $test_idx = 0; run_all_tests($test_files, $environment); $end_time = time(); if ($html_output) { show_end($end_time); } if ($failed_tests_file) { fclose($failed_tests_file); } if (count($test_files) || count($test_results)) { compute_summary(); if ($html_output) { fwrite($html_file, "<hr>\n" . get_summary(false, true)); } echo "================================================="; echo get_summary(false, false); } if ($html_output) { fclose($html_file); } if ($output_file != '' && $just_save_results) { save_or_mail_results(); } if (getenv('REPORT_EXIT_STATUS') == 1 and preg_match('/FAILED(?: |$)/', \ implode(' ', $test_results))) { exit(1); }
在测试前,这个自动化测试的框架按照用户指定的有效测试文件数目来决定具体将有多少个测试用例,并写入 test_cnt 变量中以备计数使用。函数 verify_config() 分别用来验证和准备各种环境变量的设置及 ini 设置。函数 write_information() 将输出本次测试环境的各种信息,包括被测试 PHP 的版本号,使用的扩展( Extention ),ZEND 版本,INI 设置,测试所在的系统版本信息,以及测试时间记录。
测试用例的运行发生在函数 run_all_tests() 中调用的函数 run_test() 中。 run_test() 将具体解析测试脚本中各个段落的含义,清除所以上次测试的记录与设置将干净的测试环境准备完毕,并把各种中间文件和日志文件准备好,然后用环境变量 TEST_PHP_EXECUTABLE 指定的 PHP 可执行对象运行实际的测试语句。最后将运行后的结果和测试脚本中期待值进行比对,如果比对失败,则将结果信息一一记录到用户设置的日志文件中。
在所有的测试都运行结束后,变量 end_time 将记录测试的结束时间,并用函数 compute_summary() 计算成功的、失败的、跳过的等各种情况的测试数目,并将结果输出。
由此可以总结出,这个自动化测试的框架主要包括如下几个部分:
回页首
了解了 PHP 官方自动化测试的运作方法后,用户可以创建自己的 PHPT 测试脚本以帮助 PHP 进行函数黑盒测试。然而,应用 PHP 官方自动化测试的思想和框架搭建方法,用户还可以构建自己的自动化测试工具,以应用于其他程序开发测试中。在定制自动化测试框架时,需要注意的一些问题,而这些问题在 PHP 官方自动化测试框架中就得到了很好的解决。比如:
然而,在 PHP 官方自动化测试框架中也存在一些对于用户来说不完美的地方,比如:在测试异常的情况下,不能输出完整的测试总结报告。如果测试人员需要完成一个长达十个小时的测试,而测试在第九小时发生了异常,但测试却无法给出所有跑过的测试的测试报告,这将是很恼人的。所以在自动化测试框架的实现中要考虑好测试异常情况下的处理。
回页首
PHP 官方自动化测试方法给黑盒测试人员提供了一个很好的自动化测试框架的范例。测试人员不仅可以利用 PHPT 测试脚本完善对 PHP 的测试,更可以通过学习这个范例构建自己的自动化测试框架和工具,让测试的自动化更好地服务于测试工作。