PHP TestFest UK 2010和测试PHP

今年的英国PHP TestFest于9月11日在曼彻斯特的MadLab举行。我是12位一起学习测试PHP语言的人之一。因此,我认为我将整理本届会议期间遇到的一些事情。

在创建测试之前,需要设置测试环境,您可以通过转到TestFest网站并执行有关设置系统以测试PHP的教程来完成此操作。完成测试环境的设置后,您将有一个包含三个文件夹的文件夹,分别是php52,php53和php-trunk,它们是可以测试的PHP的不同版本,尽管我们将重点介绍php53版本。本文将相同的做法用于其他中继。

设置测试环境时,您要做的最后一件事是设置一个名为TEST_PHP_EXECUTABLE的全局变量。这将指向您要测试的PHP可执行文件,并允许您在同一台计算机上运行PHP服务器并测试PHP。

export TEST_PHP_EXECUTABLE=php53/sapi/cli/php

您可以像现在一样运行PHP测试,但是最好的办法是使用代码覆盖率重新编译PHP,以便每次添加测试时,我们都可以看到我们正在测试的内容以及它在PHP源代码中的运行方式。要在启用代码覆盖率的情况下重新编译PHP,请运行带有enable-gcov标志的configure命令。

./configure --enable-gcov

与其每次都编译和测试所有内容,不如禁用所有内容并仅启用代码覆盖范围,可能会更容易。可以通过使用以下选项来完成。

./configure --disable-all --enable-gcov

一旦配置了PHP实例,就需要再次创建它。由于缺少LTP软件包,我们中的许多人在使PHP无法使用--enable-gcov开关进行编译时遇到了麻烦。如果发生此错误,我们发现可以通过使用sudo apt-get install lcov命令安装lcov库来轻松修复它。当时我正在使用Ubuntu,因此我可以在Synaptic软件包管理器中找到所需的软件包。

编译完PHP后,就可以停止。无需运行make install命令,因为我们将在本地处理PHP可执行文件。

在PHP的每个版本目录中,您都可以找到一个名为run-tests.php的文件。该脚本将允许您运行所有可用的PHP测试,您需要使用刚刚编译的PHP客户端来运行它,如下所示:

sapi/cli/php run-tests.php

这将测试整个代码库,并为整个代码库生成一个代码覆盖率报告。我应该警告您,此操作可能需要花费相当长的时间,因为根据您要查找的版本目录,可以进行7-9,000多个测试。运行测试时,最好一次只运行一个或几个测试,而不是数百个,因为这将帮助您确保测试已经编写完毕。

要仅测试PHP代码的一小部分,您可以运行脚本并传入要测试的目录(甚至文件)的参数。例如,要仅测试sql扩展中可用的测试,您可以执行此操作。

sapi/cli/php run-tests.php ext/spl

Ben Longden非常友好,可以共享一个使用run-tests.php来测试版本目录的脚本,但是随后它还继续生成我们在启用gcov的情况下重新编译PHP时想要创建的代码覆盖率报告。

ROOT='/home/bl/Development/php/php-src/branches/'
BRANCH='PHP_5_2'
BASE_DIR="$ROOT/$BRANCH"
TEST_PHP_EXECUTABLE="$BASE_DIR/sapi/cli/php"
TESTS='ext/spl'
 
$TEST_PHP_EXECUTABLE $BASE_DIR/run-tests.php $BASE_DIR/$TESTS
lcov -directory $BASE_DIR/$TESTS -c -o tests.info
genhtmltests.info-o coverage
firefox coverage/index.html

您可以将其保存为所需的任何内容,但是要运行此脚本,您首先需要进行测试。为此,您需要能够读取一点C代码,这是在调用PHP函数时运行的。查看GCOV网站上有关DNS功能的LCOV报告。您会注意到,每一行代码都以两种方式之一着色。蓝线表示代码已由测试执行,红线表示该行尚未由测试执行。未进行颜色编码的行将不会在常规代码执行期间运行,这些注释和语句之类的东西。

我们在PHP测试中运行的实际代码是PHP,因此我们需要以某种方式解密大量的红色和蓝色代码行,并将其转换为可以测试的PHP函数。您需要寻找的是PHP函数包装器,这些将C代码映射到PHP函数调用。以gethostname()DNS函数中的PHP函数为例。

通过给它们提供参数来更改PHP中的许多函数,这些参数由PHP使用C函数进行解析zend_parse_parameters()。因此,如果您在源代码中看到此函数,则可以假定该函数至少带有一个参数。就足以理解如何运行PHP代码而言,重要的参数及其后的所有内容都是该函数的重要组成部分。PHP使用第三个参数来确定已将哪些类型的数据传递给该函数。以PHP函数中的以下示例为例dns_check_record()。

这里的第三个参数是“ s | s”,这意味着可以将两个字符串传递给该函数。每次将字符串传递给此函数时,两个参数均通过引用传递。第一个是实际的字符串本身,第二个是该字符串的长度。因此,由于上面的函数调用包含两个字符串,因此将创建四个变量。

这不是您必须阅读的代码范围,有时,只有仔细阅读了什么PHP函数以及在什么情况下,您才能运行代码的特定部分。但是,有很多红线可以开始使用。

现在我们准备测试一些PHP代码,为此,我们需要创建phpt文件并使用run-tests.php运行它们。这些文件是独立的单元测试文件,每个文件都应用于测试单个操作。该文件分为多个部分,这些部分通过添加不同的标题来创建。解释phpt文件结构的最佳方法是显示一个示例。以下文件用于测试该dns_get_record()函数是否返回数组。

--TEST--
dns_get_record() function - basic type return test
--CREDITS--
Philip Norton
#!code www.hashbangcode.com
--FILE--
<?php
  var_dump(is_array(dns_get_record("www.example.com")));
?>
--EXPECT--
bool(true)

为了保持一致性,您应该使用以下文件名模板创建测试文件。测试的类型将是基本的,变体,错误或错误之类的东西,并且将用于让另一位测试人员知道该测试将构成哪种类型的东西。例如,基本测试将仅使用默认参数测试功能,该功能的可选参数将包含在变型测试中。

<function_name>_<type>_<number>.phpt

上面的示例可能保存为dns_get_record_basic_001.phpt,因为我们没有将任何可选参数传递给函数调用。我不会在这里详细介绍PHP测试文件,但是,如果您有兴趣,请查看PHP QA网站上的“ PHPT-测试文件布局”页面。

要运行测试,您可以使用标准的run-tests.php,如下所示:

:$ /php53/sapi/cli/php /php53/run-tests.php /php53/svn/testfest2010/

或者,您可以使用上面打印的脚本来运行测试文件,生成代码覆盖率报告并在Firefox中打开它。

要注意的一件事是测试失败时会发生什么。如果发生这种情况,那么测试脚本将创建一堆文件。这是生成的文件及其每个文件的列表。所有这些文件将具有与原始测试文件相同的名称,只是具有不同的扩展名。

  • diff-这是一个差异文件,它将显示代码运行的预期结果与实际结果之间的差异。

  • EXP -这是您的PHPT文件的预期部分的内容。

  • 日志-此文件包含运行代码的日志以及失败的原因。

  • out-这是代码运行的实际输出。

  • php-此文件包含测试期间运行的实际PHP代码,实质上是测试文件的file部分。

当您再次运行测试时,这些文件将被删除,因此无需手动删除它们。

在我们没时间赶往最近的酒吧之前,我们成功地在一天之间写了30至40个测试。总的来说,这是一天的美好时光,也是有经验的人员在现场掌握PHP测试世界的绝妙方法。即使我参加了去年的PHP TestFest,我实际上还没有编写任何测试,但是我认为这次我可能实际上仍会继续编写测试。

最后,我还要借此机会感谢iBuildings(再次)组织此次活动,甚至免费提供午餐的比萨饼。