Testing mod_perl 2.0
by Geoffrey Young
|
Pages: 1, 2, 3
More and More Tests
What other aspects of the filter can we put to the test?
If you recall from our discussion of output filters last
time, one of the responsibilities of filters that alter
content is to remove the generated Content-Length
header from the server response. The relevant code for this
in our filter was as follows.
# 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');
Here is the test for this bit of logic, which checks that the
Content-Length header is indeed present for plain documents,
but removed by our filter for HTML documents. Again, we will
be using the existing /level URI to request
both index.txt and index.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);
Note the use of the content_length()
method on our HTTP::Response object to retrieve
the Content-Length of the server response. Remember
that you have all the methods from that class to choose from
in your tests.
The final test we will take a look at is
the example we used previous time to illustrate our filter
does indeed co-exist with both mod_include and mod_cgi.
As it turns out, the example was taken right from the
test suite (always a good place from which to
draw examples). Here is the extra.conf.in
snippet.
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>
The nature of our test requires that both mod_include
and a suitable CGI platform (either mod_cgi or mod_cgid)
be available to Apache -
without both of these, our tests are doomed to failure,
so we need a way to test whether these modules are available
to the server before planning the individual tests.
Also required are some CGI scripts, the location
of which is specified by expanding @ServerRoot@.
To include these scripts, we could
just create a t/cgi-bin/ directory and
place the relevant files in it. However,
any CGI scripts we create would probably
include a platform-specific shebang line like
#!/usr/bin/perl. A better solution is to
generate the scripts on-the-fly, specifying a shebang
line that matches the version of Perl we are using
to build and test the module.
Despite the extra work required, the test script used for this test is only a bit more complex than others we have seen so far.
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>';
The first thing to note is that we have joined the familiar
call to have_lwp() with additional calls
to have_cgi() and have_module().
The Apache::Test package comes with a number
of handy shortcuts for querying the server for
information. have_cgi() returns true
if either mod_cgi or mod_cgid are installed.
have_module() is more generic and can
be used to test for either Apache C modules or Perl modules -
for instance, have_module('Template') could
be used to check whether the
Template Toolkit
is installed.
For generation of the CGI scripts, we use the t_write_perl_script()
function from the Apache::TestUtil package.
t_write_perl_script() takes two arguments, the
first of which is the name of the file to generate, relative to the
t/ directory in the distribution. If the
file includes a path, any necessary directories are automatically
created. In the interests of portability, we use
catfile() from the File::Spec::Functions
package to join the file with the directory. In general,
you will want to keep File::Spec and its
associated classes in mind when writing your tests - you never
know when somebody is going to try and run them on
Win32 or VMS. The second argument to t_write_perl_script()
is a list of lines to append to the file after the (calculated)
shebang line.
Although t_write_perl_script() cleans up any
generated files and directories when the test completes, if we were to
intercept include.cgi before removal
it would look similar to something we would have written
ourselves.
#!/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>';
As you probably have guessed by now, just as we
ran tests against scripts in the (generated)
t/cgi-bin/ directory, we can add other directories
to t/ for other kinds of tests.
For instance, we can create t/perl-bin/
to hold standard ModPerl::Registry scripts
(remember, you don't need to generate a shebang
line for those).
We can even create t/My/ to hold a custom
My::ContentGenerator handler, which can be used just
like any other Perl module during Apache's runtime.
All in all, you can simulate practically any
production environment imaginable.
But Wait, There's More!
The tests presented here should be enough to get
you started writing tests for your own modules, but
they are only part of the story. If you are interested
in seeing some of the other tests written to support this article, the
Apache::Clean
distribution is full
of all kinds of different tests and test approaches, including some
that integrate custom handlers as well as one that tests
the POD syntax for the module. In fact, you will find 26 different
tests in 12 test files there, free for the taking.
Stuck using mod_perl 1.0? One of the best things about Apache-Test
is that it is flexible and intelligent enough to be
used for mod_perl 1.0 handlers as well.
In fact, the recent
release of Apache-Test as a CPAN module
outside of the mod_perl 2.0 distribution makes it even
easier for all mod_perl developers to take advantage of
the framework. For the most part, the instructions in
this article should be enough to get you going writing
tests for 1.0-based modules - the only changes specific to
1.0 modules rest in the Makefile.PL. I took
the time to whip up
a version of Apache::Clean for mod_perl 1.0 that
parallels the functionality in these articles,
which you can find
next to
the 2.0 version. The 1.0 distribution runs against
the exact same *.t files (where applicable)
and includes a sample 1.0 Makefile.PL.
Personally, I don't know how I ever got along without
Apache-Test, and I'm sure that once you start using
it you will feel the same. Secretly, I'm hoping that
Apache-Test becomes so popular that end-users
start wrapping their bug reports up in little, self-contained,
Apache-Test-based tarballs so anyone
can reproduce the problem.
More Information
This article was derived from Recipe 7.7 in the
mod_perl Developer's Cookbook,
adjusted to accommodate both mod_perl 2.0 and changes in the overall
Apache-Test interface that have happened
since publication. Despite these differences, the recipe
is useful for its additional descriptions and coverage
of features not discussed here. You can read Recipe 7.7, as well
as the rest
of Chapter 7 from the book's website.
Also, in addition to the
Apache-Test
manpage and
README
there is also the Apache-Test tutorial on
the mod_perl
Project website, all of which are valuable sources of information.
Thanks
The Apache-Test project is the result of the tireless efforts of many, many
developers - far too many to name individually here. However, there has has been a recent
surge of activity as Apache-Test made its way to CPAN, especially in making
it more platform aware and solving a few back compatibility problems with the old
Apache::test that ships with mod_perl 1.0. Special thanks are due
to Stas Bekman, David Wheeler, and Randy Kobes for helping to polish
Apache-Test on Win32 and Mac OS X without requiring
major changes to the API.

