测试 mod_perl 2.0

上次,我们探讨了使用 mod_perl 2.0 API 编写简单的 Apache 输出过滤器 - Apache::Clean。我是如何知道我提供的过滤器真正工作的呢?我为此编写了一个测试套件,它使用 Apache-Test 测试框架针对一个实际的 Apache 服务器测试了 代码

自从 Apache-Test 诞生以来,编写针对实际 Apache 服务器的测试序列变得简单多了。尽管作为 Apache HTTP 测试项目 的一部分,Apache-Test 足够通用,可以与几乎任何版本的 Apache(无论是否启用了 mod_perl)一起使用,但它捆绑了 mod_perl 2.0,使其成为编写 mod_perl 2.0 模块测试的理想工具。

测试,测试,1,2,3

编写测试有很多优点。例如,在编码 Apache::Clean 的过程中维护测试套件,使我能够在我实现每个功能单元时对其进行测试,这使得开发变得更容易。单独的测试还使我能够相当确信,一旦发布,该模块将按预期行为。作为一个额外的奖励,测试提供了以测试脚本、支持库和配置文件的形式存在的额外最终用户文档,任何想要查看发行版的人都可以访问。总的来说,拥有测试套件会极大地增加你代码的价值,同时让你的生活变得更轻松。

当然,这些好处来自于拥有任何测试环境,而不仅仅是限于 Apache-TestApache-Test 带来的特定优势是,它以极简的方式提供了一个完整、原始和隔离的 Apache 服务器,让你能够以最小的努力在实时环境中测试和练习你的代码。不再需要 Apache::FakeRequest,不再需要 httpd.conf 配置分散在开发环境中或被用于保持你忙碌的非错误处理程序破坏,不再需要混乱,不再需要泪水。

如果你曾经使用过 Test.pmTest::More 这样的工具作为测试模块的基础,那么你已经了解了使用 Apache-Test 的大多数内容。实际上,Apache-Test 在内部使用 Test.pm,因此布局和语法类似。如果你从未编写过测试(你真应该感到羞愧),那么 测试简介 提供了使用 Perl 进行测试的概述。不过,大多数情况下,Apache-Test 真的是足够简单,你应该能够轻松地跟随这里,无需任何麻烦或先前的知识。

利用 Apache-Test 框架只需要几个步骤 - 生成测试工具包,配置 Apache 以满足你的特定需求,以及编写测试 - 每个步骤都比较简单。

生成测试工具包

使用 Apache-Test 的第一步是调整你的模块的 Makefile.PL 文件。如果你还没有 Makefile.PL 文件,或者不熟悉如何生成它,那么不要担心 - 所需的一切只是一个简单的 h2xs 调用,这为我们提供了一个标准平台,既可以分发我们的模块,又可以部署 Apache-Test 基础设施。

$ h2xs -AXPn Apache::Clean
Defaulting to backward compatibility with perl 5.9.0
If you intend this module to be compatible with earlier perl versions, then please
specify a minimum perl version with the -b option.

Writing Apache/Clean/Clean.pm
Writing Apache/Clean/Makefile.PL
Writing Apache/Clean/README
Writing Apache/Clean/t/1.t
Writing Apache/Clean/Changes
Writing Apache/Clean/MANIFEST

h2xs 为我们的模块生成必要的结构,包括 Clean.pm 模板和 Makefile.PL,以及存放测试文件和支持文件的 t/ 子目录。你可以进行一些额外操作,对分布进行一些调整(例如删除 t/1.t 并将所有内容放入 Apache-Clean/ 而不是 Apache/Clean/),但这不是必需的。一旦你整理好模块布局并替换了生成的 Clean.pm 空白文件,使用之前提到的 实际的 Clean.pm 过滤器,就到了开始准备基本测试框架的时候了。

首先,我们需要对 Makefile.PL 进行重大修改。最终结果应该类似于以下内容:

#!perl

use 5.008;

use Apache2 ();
use ModPerl::MM ();
use Apache::TestMM qw(test clean);
use Apache::TestRunPerl ();

# configure tests based on incoming arguments
Apache::TestMM::filter_args();

# provide the test harness
Apache::TestRunPerl->generate_script();

# now, write out the Makefile
ModPerl::MM::WriteMakefile(
  NAME      => 'Apache::Clean',
  VERSION   => '2.0',
  PREREQ_PM => { HTML::Clean      => 0.8,
                 mod_perl         => 1.9909, },
);

让我们花点时间分析一下我们的非标准 Makefile.PL。我们首先导入一些新的 mod_perl 2.0 库。第一个是 Apache2.pm。为了与 mod_perl 1.0 安装和平共处,mod_perl 2.0 允许你在 @INC 中相对于 Apache2/ 安装 mod_perl,以避免与同名的 1.0 模块发生冲突。例如,我们用于编写输出过滤接口的 mod_perl 2.0 Apache::Filter 将安装为 Apache2/Apache/Filter.pm。当然,在 mod_perl 2.0 代码中使用 require()use() Apache::Filter 的普通调用将无法找到正确的版本(如果找到了的话),因为它被安装在一个非标准的位置。《Apache2.pm 扩展 @INC 以包括任何(现有)Apache2/ 目录,以便 use() 和相关语句能够按预期工作。在我们的例子中,我们需要 use() Apache2 来确保,无论最终用户如何配置其 mod_perl 2.0 安装,我们都可以找到所需的其余库。

在确信我们的 Makefile.PL 能够找到所有其他 mod_perl 2.0 软件包(无论它们在哪里)之后,我们可以继续前进。《ModPerl::MM 提供了 WriteMakefile() 函数,它与同名 ExtUtils::MakeMaker 函数类似,并具有相同的选项。你想要使用来自 ModPerl::MMWriteMakefile() 的原因是通过非常神奇的手段,满足了所有你的 mod_perl 特定需求。例如,你的模块将根据 mod_perl 本身的安装方式安装到 Apache/Apache2/。其他一些不错的功能包括自动包含 mod_perl 的 typemap 以及基于 XS 的模块所需的头文件,以及过去在 Win32 编译中令人烦恼的跨平台兼容性。

请记住,使用 Apache-Test 不需要 Apache2.pmModPerl::MM - 这两个都是特定于 mod_perl 2.0 以及你可能为该版本编写的任何处理程序(稍后将会讨论,Apache-Test 也可以用于基于 mod_perl 1.0 的模块,或者甚至是独立于 mod_perl 的 Apache 1.3 或 2.0 模块)。下一个包是 Apache::TestMM,它是 Apache-Test 的实际接口。

Apache::TestMM 包含我们需要的用于配置测试框架的函数。我们首先导入 test()clean() 函数,它们生成相应的 Makefile 目标,这样我们就可以运行(并重新运行)我们的测试。之后,我们调用 filter_args() 函数。这允许我们使用不同的选项在命令行上配置测试的各个部分,稍后将会讨论。

配置的最后部分使用来自 Apache::TestRunPerl 类的 generate_script() 方法,该方法写入负责运行我们的测试的脚本 t/TEST。当用户发出 make test 时,将调用 t/TEST,尽管也可以直接调用该脚本。虽然 t/TEST 最终可能包含大量信息,但如果你打开它,你会看到真正驱动测试套件的引擎相当简单。

use Apache::TestRunPerl ();
Apache::TestRunPerl->new->run(@ARGV);

信不信由你,单次调用 run() 就完成了启动、配置和停止Apache的所有复杂工作,以及运行我们(仍然)尚未定义的各个测试。

尽管解释得很长,但我们到目前为止的活动净结果是修改了一些典型的 Makefile.PL,使其反映我们mod_perl 2.0模块的需求以及我们即将使用的 Apache-Test 基础设施。接下来,我们需要为我们的处理器中的特定功能配置Apache。

配置Apache

通常,你需要将许多东西放入 httpd.conf 以使服务器能够响应用户请求,其中只有一部分与服务器将提供的内容有关。《Apache-Test》框架提供了一个最小的Apache配置,例如默认的 DocumentRootErrorLogListen 以及服务器正常操作所需的其它设置。实际上,在不进行干预的情况下,《Apache-Test》提供了一种配置,使你可以成功地从服务器请求 /index.html。然而,你可能需要比基本配置更复杂的配置来适当地测试你的模块。

为了向默认设置添加额外的设置,我们创建了 t/conf/extra.conf.in 文件,并在途中添加了任何所需的目录。如果《Apache-Test》看到 extra.conf.in,则它会使用 Include 指令将其文件拉入默认配置(之后我们将讨论的一些操作)。这提供了一种方便的方法,只添加你需要的测试配置数据,并让你不必担心服务器运行的日常问题。

我们应该首先测试《Apache::Clean》的第一个方面是它是否能够清理一个简单的静态HTML文件。因此,我们在 extra.conf.in 中开始如下

PerlSwitches -w

Alias /level @DocumentRoot@
<Location /level>
  PerlOutputFilterHandler Apache::Clean
  PerlSetVar CleanLevel 2
</Location>

这激活了针对 /level 请求的输出过滤器。注意引入了一个新的指令 PerlSwitches,它允许你向嵌入的Perl解释器传递命令行开关。在这里,我们使用它来启用警告,类似于在mod_perl 1.0中 PerlWarn 的作用。《PerlSwitches》实际上可以接受任何Perl命令行开关,这使得它成为一个相当有用且灵活的工具。例如,我们可以使用 -I 开关来扩展 @INC,而不是在 startup.pl 中添加 use lib 语句,或者使用 -T 来启用taint模式,代替以前的 PerlTaintMode 指令,该指令不是mod_perl 2.0的一部分。

接下来,我们来到熟悉的 Alias 指令,尽管有一些变化。如前所述,《Apache-Test》配置了几个默认值,包括 DocumentRootServerRoot。《Apache-Test》的一个很好的功能是它为你跟踪默认值并提供一些有用的变量扩展。在我特别的情况下,Alias 指令中的 @DocumentRoot@ 变量被《Apache-Test》为我的构建计算出的默认 DocumentRoot 的值所替换。实际的配置最终看起来像

Alias /level /src/perl.com/Apache-Clean-2.0/t/htdocs

当运行测试时。这很有用,特别是考虑到你的测试可能在不同的平台上运行。

其余的配置与上次我们的示例非常相似 - 使用 PerlOutputFilterHandler 指定 Apache::Clean 作为我们的输出过滤器,以及使用 PerlSetVar 指定特定的 HTML::Clean 级别。在我们准备好足够的模块以运行第一个测试之前,唯一缺少的是 DocumentRoot 中的可测试内容。

正如你在前一个示例中的 @DocumentRoot@ 扩展中可以看到,DocumentRoot 解析为 ServerRoot/t/htdocs/,因此这是我们可以在其中放置任何我们感兴趣的测试文档的地方。因此,我们创建 t/htdocs/index.html 并在其中放置一些有用的内容。

<i    ><strong>&quot;This is a test&quot;</strong></i   >

我们的 index.html 包含多个不同的元素,这些元素可以通过 HTML::Clean 进行整理,使其对测试各种配置的 Apache::Clean 非常有用。

现在我们已经有了所需的全部 Apache 配置:在 t/conf/extra.conf.in 中有一些自定义配置指令,在 t/htdocs/index.html 中有一些有用的内容。接下来要做的就是编写测试。

编写测试

到目前为止我们创建的 Apache 配置提供了一个通过 /level/index.html 测试 Apache::Clean 的方法。这个请求的结果应该是默认的 Apache 内容处理器提供 index.html,在文件发送到线路上之前应用我们的 PerlOutputFilterHandler。考虑到配置了 PerlSetVar CleanLevel 2,我们预计请求的最终结果将是

<i><b>&quot;This is a test&quot;</b></i>

其中标签被缩短,空白被删除,但 &quot; 实体保持不变。好吧,这可能不是你期望的,但是打开 HTML::Clean 的代码 reveals that level(2) 包括 whitespaceshortertags 选项,但不包括 entities 选项。这引出了测试设计和可能掩盖真正错误的错误期望的更大问题——当测试失败时,错误是在测试还是在代码中?——但这将是另一个话题的讨论。

考虑到我们的配置和预期结果,我们可以编写一个请求 /level/index.html,从服务器响应中隔离内容,然后测试内容是否符合我们的预期。这里所示的文件 t/01level.t 正是这样做。

use strict;
use warnings FATAL => 'all';

use Apache::Test qw(plan ok have_lwp);
use Apache::TestRequest qw(GET);
use Apache::TestUtil qw(t_cmp);

plan tests => 1, have_lwp;

my $response = GET '/level/index.html';
chomp(my $content = $response->content);

ok ($content eq q!<i><b>&quot;This is a test&quot;</b></i>!);

t/01level.t 展示了你将要编写的多数测试中将常见的几个事物。首先,我们进行一些记账并使用来自 Apache::Testplan() 函数计划要尝试的测试数量——在我们的例子中只有一个。最后,可选的 plan() 参数使用 have_lwp() 函数检查来自 libwww-perl 分发的模块的可用性。如果 have_lwp() 返回 true,则我们知道我们可以利用 LWP 提供的快捷方式 Apache::TestRequest。如果 have_lwp() 返回 false,则不计划任何测试,并且在运行时跳过整个测试。

计划测试后,我们使用来自 Apache::TestRequest 的快捷函数 GET()/level/index.html 发起请求。 GET() 返回一个 HTTP::Response 对象,所以如果你熟悉 LWP 套件模块,你应该会感到很自在。使用 $response 中的对象,我们使用 content() 方法隔离服务器响应,并与我们的预期字符串进行比较。比较使用 ok() 调用,如果两个字符串等效,则会报告成功。

请注意,尽管此示例明确导入了 plan()ok()have_lwp()GET() 函数到我们的测试脚本中,但这只是为了说明测试不同部分的来源——这些函数以及你可能需要的几乎所有其他函数都默认导出。因此,典型的测试脚本通常只是调用

use Apache::Test;
use Apache::TestRequest;

然后继续。

这就是编写测试的全部内容。在最简单的情况下,使用 Apache-Test 几乎涉及与其他 Perl 测试工具编写测试时相同的步骤:在脚本中 plan() 测试数量,做一些事情,然后对每个你 plan() 的测试调用 ok()Apache-Test 和其实用类仅提供了使编写针对运行中的 Apache 服务器进行测试变得通用的快捷方式。

运行测试

在所有准备工作完成之后——生成和自定义 Makefile.PL、使用 extra.conf.in 配置 Apache、编写 index.html01level.t——我们已经有了所有部件,可以(最终)运行我们的测试。

在分发中运行测试有几种不同的方法,但所有方法都需要首先完成标准的构建步骤。

$ perl Makefile.PL -apxs /usr/local/apache2/bin/apxs
Checking if your kit is complete ...
Looks good
Writing Makefile for Apache::Clean

$ make
cp Clean.pm blib/lib/Apache2/Apache/Clean.pm
Manifying blib/man3/Apache::Clean.3

Makefile.PL通过调用Apache::TestRunPerl->generate_script()生成t/TEST脚本,从而开始处理过程。我们传递的额外参数-apxsApache::TestMM::filter_args()捕获,并用于指定我们想要测试代码的Apache安装。在这里,我使用-apxs来指定本地Apache DSO安装中apxs二进制文件的位置——对于静态构建,您将想要使用-httpd来指向httpd二进制文件。在Makefile.PL退出时,我们已经有了测试框架,并且知道服务器所在的位置。

运行make将创建我们的构建目录blib/,并将Clean.pm本地安装,以便我们可以在测试中使用它。请注意,ModPerl::MMApache2相对路径下安装了Clean.pm,神奇地跟随我当前的mod_perl 2.0安装路径。

到此为止,我们可以运行我们的测试。执行make test将运行t/目录下的所有测试,正如您可能预期的那样。但是,我们也可以单独运行测试,这在调试时特别有用。要运行特定的测试,我们直接调用t/TEST并给它我们感兴趣的测试名称。

$ t/TEST t/01level.t
*** setting ulimit to allow core files
ulimit -c unlimited; t/TEST 't/01level.t'
/usr/local/apache2/bin/httpd  -d /src/perl.com/Apache-Clean-2.0/t 
    -f /src/perl.com/Apache-Clean-2.0/t/conf/httpd.conf 
    -DAPACHE2 -DPERL_USEITHREADS
using Apache/2.1.0-dev (prefork MPM)

waiting for server to start: ..
waiting for server to start: ok (waited 1 secs)
server localhost:8529 started
01level....ok                                                                
All tests successful.
Files=1, Tests=1,  4 wallclock secs ( 3.15 cusr +  0.13 csys =  3.28 CPU)
*** server localhost:8529 shutdown

正如您所看到的,服务器已启动,我们的测试已运行,服务器已关闭,并生成了报告——这一切都是在我们最小的工作量下完成的。向Apache-Test的开发者表示衷心的感谢,他们使实时测试的开发变得如此简单。

超越基础

我们之前讨论的内容只是基础,该框架包含了许多不同的选项,旨在使编写和调试测试更加容易。其中之一是Apache::TestUtil包,它提供了一些您可以在测试中使用的实用函数。其中最有用的是t_cmp(),这是一个简单的相等性测试函数,在以详细模式运行测试时还提供额外信息。例如,在将use Apache::TestUtil;添加到我们的01level.t测试后,我们可以修改ok()的调用,使其看起来像

ok t_cmp(q!<i><b>&quot;This is a test&quot;</b></i>!, $content);

并且结果将包括预期的和接收的通知(以及标准详细输出)

$ t/TEST t/01level.t -v
[lines snipped]
01level....1..1
# Running under perl version 5.009 for linux
# Current time local: Mon May  5 11:04:09 2003
# Current time GMT:   Mon May  5 15:04:09 2003
# Using Test.pm version 1.24
# expected: <i><b>&quot;This is a test&quot;</b></i>
# received: <i><b>&quot;This is a test&quot;</b></i>
ok 1
ok
All tests successful.

这在调试最终用户报告的问题时特别有帮助。请参阅Apache::TestUtil的手册页面,其中列出了大量辅助函数,以及Apache-Test分发中的README,其中提供了除-v之外的额外命令行选项。

当然,01level.t只测试了我们的Clean.pm输出过滤器的某个方面,还有更多功能我们可能想要验证。因此,让我们快速查看一些与Apache::Clean分发一起提供的其他测试。

Apache::Clean的一个特点是它自动拒绝处理非HTML文档。这种逻辑就在我们的过滤器的开头定义了几行。

# we only process HTML documents
unless ($r->content_type =~ m!text/html!i) {
  $log->info('skipping request to ', $r->uri, ' (not an HTML document)');

  return Apache::DECLINED;
}

对此代码的良好测试是验证来自纯文本文档的内容确实通过了我们的过滤器而没有改变,即使它包含HTML::Clean通常会处理的HTML标签。我们的测试套件包括一个文件t/htdocs/index.txt,其内容与我们之前创建的index.html文件相同。记住,我们已经有一个为/level插入我们的过滤器的Apache配置,我们可以使用对/level/index.txt的请求来测试拒绝逻辑。

use Apache::Test;
use Apache::TestRequest;

plan tests => 1, have_lwp;

my $response = GET '/level/index.txt';
chomp(my $content = $response->content);

ok ($content eq q!<i><strong>&quot;This is a test&quot;</strong></i>!);

这可能是显而易见的,但如果我们思考我们真正在这里测试的是什么,那并不是内容没有改变——这只是为了衡量测试的成功。真正的测试是针对决定过滤器是否作用于内容的准则。如果我们想做得更彻底,那么我们可以添加

AddDefaultCharset On

将测试逻辑应用于类似于 text/html; charset=iso-8859-1 的头信息,而不是仅仅 text/html,并测试 Content-Type 逻辑。实际上,不止一个人评论说,使用正则表达式来测试 Content-Type 是过度的——添加 AddDefaultCharset On 指令表明正则逻辑可以处理比简单的 $r->content_type eq 'text/html' 检查更多的运行时环境。哦,当你开始编写测试时,你会发现、修复和捍卫的bug。

越来越多的测试

我们可以将过滤器的哪些方面用于测试?如果您还记得我们上次讨论输出过滤器时提到的内容,过滤器改变内容的职责之一是从服务器响应中删除生成的 Content-Length 头。在我们的过滤器中,与此相关的代码如下。

# output filters that alter content are responsible for removing
# the Content-Length header, but we only need to do this once.
$r->headers_out->unset('Content-Length');

这里是这个逻辑的测试,它检查对于普通文档确实存在 Content-Length 头,但我们的过滤器会将其从 HTML 文档中删除。同样,我们将使用现有的 /level URI 请求 index.txtindex.html

use Apache::Test;
use Apache::TestRequest;

plan tests => 2, have_lwp;

my $response = GET '/level/index.txt';
ok ($response->content_length == 58);

$response = GET '/level/index.html';
ok (! $response->content_length);

注意使用我们的 HTTP::Response 对象上的 content_length() 方法来获取服务器响应的 Content-Length。记住,在测试中你可以选择使用该类上的所有方法。

我们将要查看的最后一个是上次示例中用来说明我们的过滤器确实与 mod_include 和 mod_cgi 共存的例子。实际上,这个例子直接来自测试套件(总是从好的地方抽取例子)。以下是 extra.conf.in 的片段。

Alias /cgi-bin @ServerRoot@/cgi-bin
<Location /cgi-bin>
  SetHandler cgi-script

  SetOutputFilter INCLUDES
  PerlOutputFilterHandler Apache::Clean

  PerlSetVar CleanOption shortertags
  PerlAddVar CleanOption whitespace
  Options +ExecCGI +Includes
</Location>

我们测试的性质要求 Apache 有 mod_include 和合适的 CGI 平台(无论是 mod_cgi 还是 mod_cgid)——没有这两个,我们的测试注定会失败,因此我们需要一种方法来测试在计划单个测试之前这些模块是否对服务器可用。还需要一些 CGI 脚本,其位置由 @ServerRoot@ 指定。为了包含这些脚本,我们可以创建一个 t/cgi-bin/ 目录并将相关文件放在其中。然而,我们创建的任何 CGI 脚本都可能包含一个特定平台的 shebang 行,如 #!/usr/bin/perl。更好的解决方案是即时生成脚本,指定一个与构建和测试模块所使用的 Perl 版本匹配的 shebang 行。

尽管需要额外的工作,但用于此测试的脚本与我们之前看到的其他脚本相比仅略复杂。

use Apache::Test;
use Apache::TestRequest;
use Apache::TestUtil qw(t_write_perl_script);

use File::Spec::Functions qw(catfile);

plan tests => 4, (have_lwp && 
                  have_cgi &&
                  have_module('include'));

my @lines = <DATA>;
t_write_perl_script(catfile(qw(cgi-bin plain.cgi)), @lines[0,2]);
t_write_perl_script(catfile(qw(cgi-bin include.cgi)), @lines[1,2]);

my $response = GET '/cgi-bin/plain.cgi';
chomp(my $content = $response->content);

ok ($content eq q!<strong>/cgi-bin/plain.cgi</strong>!);
ok ($response->content_type =~ m!text/plain!);

$response = GET '/cgi-bin/include.cgi';
chomp($content = $response->content);

ok ($content eq q!<b>/cgi-bin/include.cgi</b>!);
ok ($response->content_type =~ m!text/html!);

__END__
print "Content-Type: text/plain\n\n";
print "Content-Type: text/html\n\n";
print '<strong><!--#echo var="DOCUMENT_URI" --></strong>';

首先要注意的是,我们将熟悉的 have_lwp() 调用与额外的 have_cgi()have_module() 调用结合起来。Apache::Test 包包含一系列方便的快捷方式来查询服务器信息。have_cgi() 如果安装了 mod_cgi 或 mod_cgid 则返回 true。have_module() 更通用,可以用于测试 Apache C 模块或 Perl 模块——例如,可以使用 have_module('Template') 来检查 Template Toolkit 是否已安装。

为了生成CGI脚本,我们使用来自Apache::TestUtil包的t_write_perl_script()函数。t_write_perl_script()函数接收两个参数,第一个参数是要生成的文件名,相对于分布中的t/目录。如果文件包含路径,任何必要的目录都会自动创建。出于可移植性的考虑,我们使用来自File::Spec::Functions包的catfile()函数将文件与目录连接起来。通常,在编写测试时,您需要记住File::Spec及其相关类 - 你永远不知道有人在Win32或VMS上尝试运行它们。到t_write_perl_script()的第二个参数是追加到文件中的行,这些行位于(计算的)shebang行之后。

尽管t_write_perl_script()在测试完成后清理所有生成的文件和目录,但如果我们在删除之前拦截include.cgi,它看起来会类似于我们自己编写的代码。

#!/src/bleedperl/bin/perl
# WARNING: this file is generated, do not edit
# 01: /src/bleedperl/lib/site_perl/5.9.0/i686-linux-thread-multi/
      Apache/TestUtil.pm:129
# 02: 06mod_cgi.t:18
print "Content-Type: text/html\n\n";
print '<strong><!--#echo var="DOCUMENT_URI" --></strong>';

正如你可能已经猜到的,我们运行了针对(生成)t/cgi-bin/目录中的脚本的测试,我们也可以将其他目录添加到t/中,以进行其他类型的测试。例如,我们可以创建t/perl-bin/来存放标准的ModPerl::Registry脚本(记住,对于这些脚本,你不需要生成shebang行)。我们甚至可以创建t/My/来存放自定义的My::ContentGenerator处理器,它可以像任何其他Perl模块一样在Apache运行时使用。总的来说,你可以模拟任何可以想象的生产环境。

但是,还有更多!

这里展示的测试应该足以让你开始为自己的模块编写测试,但它们只是故事的一部分。如果你对看到为这篇文章编写的其他测试感兴趣,可以查看Apache::Clean分布,其中充满了各种不同的测试和测试方法,包括集成自定义处理器的测试以及测试模块POD语法的测试。实际上,你将在12个测试文件中找到26个不同的测试,供你免费使用。

还在使用mod_perl 1.0吗?Apache-Test的一个优点是它足够灵活和智能,可以用于mod_perl 1.0处理器。事实上,作为mod_perl 2.0分布之外的CPAN模块的最新发布,使得所有mod_perl开发人员都能更方便地利用该框架。在大多数情况下,这篇文章中的说明应该足以让你开始为基于1.0的模块编写测试 - 1.0模块特有的更改仅限于Makefile.PL。我花时间创建了一个与这些文章中功能相似的Apache::Clean版本,你可以找到2.0版本旁边的版本。1.0分布针对相同的*.t文件(适用的情况下)并包括一个示例1.0的Makefile.PL

我个人不知道在没有Apache-Test的情况下我怎么能过得去,我相信一旦开始使用它,你也会有同样的感觉。秘密地,我希望Apache-Test变得如此受欢迎,以至于最终用户开始用小型的、自包含的、基于Apache-Test的tar包包装他们的错误报告,这样任何人都可以重现问题。

更多信息

本文源自《mod_perl 开发者手册》第 7.7 节,网址为 mod_perl 开发者手册,根据 2.0 版本及自出版以来 Apache-Test 接口的变化进行了调整。尽管存在这些差异,但这个配方因其额外的描述和讨论了此处未提及的功能而非常有用。您可以阅读书中的第 7.7 节,以及第 7 章的其他内容,这些内容都可以在网站上找到。此外,除了 Apache-Test 的手册页和 README,还有mod_perl 项目网站上的 Apache-Test 教程,这些都是非常有价值的信息来源。

感谢

Apache-Test 项目是许多开发者不懈努力的结果——人数众多,无法一一列举。然而,随着 Apache-Test 进入 CPAN,近期活动明显增加,特别是在使其更具有平台感知性和解决与 mod_perl 1.0 一起提供的旧 Apache::test 的一些向后兼容性问题。特别感谢 Stas Bekman、David Wheeler 和 Randy Kobes,他们帮助在 Win32 和 Mac OS X 上润色 Apache-Test,而无需对 API 进行重大更改。

标签

反馈

这篇文章有什么问题吗?请通过在GitHub上打开一个 issue 或 pull request 来帮助我们。