Testing with Apache-Test

     

"Running Your Own Apache Server" demonstrated how to start and stop an Apache server manually. In real life, you'll probably start and stop the test server automatically when you want to run your test suite. This lab shows how to test and create a simple Apache module, called Thumbnail , that uses the Imager module to resize images to a certain width and height. How do you know this module works? Use Apache-Test to test it!

How do I do that?

First, create a lib/ directory. You should already have the t/ and /t/conf/ directories from the previous lab. t/TEST will be the same, but t/conf/extra.conf.in needs some editing.


Note: Remember to add this new lib/ directory to Perl's search path .

In custom configuration files such as extra.conf.in , the server substitutes special variables (in the form of @ NAME @ ) with useful values when it starts. The server uses those directives in the file as its configuration. Adding the lib/ directory to Perl's module search path is easy; add it to the SERVERROOT variable.

Save the following as t/conf/extra.conf.in :

 <IfModule mod_perl.c>              <Perl>             use lib '@SERVERROOT@/../lib';             use Thumbnail (  );         </Perl>              <Location /images>             SetHandler perl-script             PerlHandler Thumbnail         </Location>          </IfModule> 

Save the Thumbnail module as lib/Thumbnail.pm :

 package Thumbnail;          use strict;     use warnings;          use Apache::Constants qw(:common);     use Apache::File;     use Imager;          our $constraint = 150;          sub handler     {         my ($r) = @_;              return DECLINED unless $r->content_type(  ) =~ m{^image/};              my $img = Imager->new(  );         $img->open( file => $r->filename ) or die $img->errstr(  );              $img    = $img->scale( xpixels => $constraint, ypixels => $constraint );              my ( $tmpfile, $tmpfh ) = Apache::File->tmpfile(  );         $img->write( file => $tmpfile, type => 'jpeg' )             or die $img->errstr(  );              $r->send_http_header('image/jpeg');         $r->send_fd($tmpfh);              return OK;     }          1; 

Save the following test file as t/thumbnail.t :

 #!perl          use strict;     use warnings;          use Apache::Test;     use Apache::TestUtil;     use Apache::TestRequest qw( GET_BODY );     use Imager;          plan( tests => 1, need_module('mod_perl') );          my $content = GET_BODY('/images/panorama.jpg');          my $img     = Imager->new(  );     $img->open( data => $content, type => 'jpeg' )         or die $img->errstr(  );          my $max     = 150;          t_debug( "assuming constraint is $max pixels" );          t_debug( 'width: '  . $img->getwidth(  )    );     t_debug( 'height: ' . $img->getheight(  )   );          ok( ( $img->getwidth(  ) =  = $max ) or ( $img->getheight(  ) =  = $max ) ); 

Finally, you need a picture for the module to transform. Pick something large, such as a breathtaking scene of Bryce Canyon with deer grazing in the distance. Save it as t/htdocs/images/panorama.jpg .

First make sure that Apache-Test knows where to find your Apache executable by setting the APACHE_TEST_HTTPD environment variable:


Note: If you're not using a bash-like shell, see your shell's documentation to set this variable correctly .
 $  export APACHE_TEST_HTTPD=/usr/sbin/apache-perl  

Run TEST to run the tests:

 $  perl t/TEST  [warning] setting ulimit to allow core files     ulimit -c unlimited; /usr/bin/perl /home/anu/thumbnail/t/TEST     /usr/sbin/apache-perl  -d /home/anu/thumbnail/t -f         /home/anu/thumbnail/t/conf/httpd.conf -D APACHE1 -D PERL_USEITHREADS     using Apache/1.3.33          waiting 60 seconds for server to start: .     waiting 60 seconds for server to start: ok (waited 0 secs)     server localhost:8529 started     t/thumbnail....ok     All tests successful.     Files=1, Tests=1,  2 wallclock secs ( 0.35 cusr +  0.05 csys =  0.40 CPU)     [warning] server localhost:8529 shutdown 

Within the Apache-Test diagnostic output, you'll see that all of the tests succeeded.

What just happened ?

t/ is the server root directory, which is where Apache looks for the conf/ or htdocs/ directory. If an htdocs/ directory is present, Apache will use it as the document root. By default, Apache-Test saves a simple index.html in the document root when it starts, but the images/ directory is more interesting right now.

Requesting the URI /images/panorama.jpg without using the handler would simply return the picture of the canyon with the lovely grazing Cervidae. extra.conf.in , however, uses a < Location > directive to specify that the thumbnail-generating module will handle paths beginning with /images .

Thumbnail is a fairly straightforward Apache module. It handles only images, returning DECLINED if Apache doesn't believe that the file's type is some sort of image. If it is an image, the handler reads in the file and resizes it (in memory, not on disk) so that it is at the most 150 pixels square. Finally, it sends the resized image as the content of the response.


Note: Instead of printing a gigantic scalar, Thumbnail.pm uses Apache:: File to create a temporary file and uses the send_fd() method with a filehandle .

...or does it? Does the module truly resize the image? This is precisely what t/thumbnail.t tests.

thumbnail.t doesn't use Test::More . Instead, it uses Apache-Test's framework, which is a bit different. Remember, though, that tests always boil down to a simple "ok" or "not ok."

The first difference is that Apache::Test provides a different plan( ) function. While it appears the same as the Test::More version, it actually provides many more features, allowing developers to specify requirements for the tests that skip the tests if not met. thumbnail.t ensures that the Apache server used for testing does indeed have mod_perl enabled by specifying need_module('mod_perl') . Without mod_perl , the file skips the tests.

Alternatively, you can use need_module( ) to specify that the tests require a certain Perl module. For example, to modify the plan( ) statement to specify that you need the Imager module, write:

 plan tests => 1  , need_module('Imager')  ; 

To skip the test file completely, use the skip_reason( ) function exported by Apache::Test in combination with plan( ) :

 plan tests => 1  , skip_reason("our Perl ain't up to snuff")  ; 

This is merely the tip of the iceberg in terms of what Apache::Test 's plan( ) function can do. For more information, see the Apache::Test documentation.

Continuing with differences between Apache-Test and Test::More , note that there are no is( ) or diag( ) functions. Instead, Apache::TestUtil exports t_cmp( ) and t_debug( ) . t_cmp( ) takes the same arguments as is( ) , but you must use it in conjunction with ok( ) . For example, to test that the image uses 16-bit color :

 ok( t_cmp($img->bits(  ), 16, 'image has sixteen bits') ); 

t_debug( ) prints out diagnostic messages in the same manner as Test::More 's diag( ) function. thumbnail.t uses t_debug( ) to print out the value of the image's actual size . To see these diagnostic messages, run TEST with the -verbose option. When you do, you'll see other debugging information in addition to your own messages:


Note: If your tests suddenly stop working, run TEST with the "-clean" option to remove extra generated files. Then be sure to run TEST with -verbose" .
 $  perl t/TEST -verbose  [warning] setting ulimit to allow core files     ulimit -c unlimited; /usr/bin/perl /home/anu/thumbnail/t/TEST -verbose     /usr/sbin/apache-perl  -d /home/anu/thumbnail/t -f         /home/anu/thumbnail/t/conf/httpd.conf -D APACHE1 -D PERL_USEITHREADS     using Apache/1.3.33          waiting 60 seconds for server to start: .     waiting 60 seconds for server to start: ok (waited 0 secs)     server localhost:8529 started     t/thumbnail....1..1     # Running under perl version 5.008004 for linux     # Current time local: Thu Mar 24 11:13:55 2005     # Current time GMT:   Thu Mar 24 16:13:55 2005     # Using Test.pm version 1.24     # Using Apache/Test.pm version 1.20     # assuming constraint is 150 pixels     # width: 200     # height: 150     ok 1     ok     All tests successful.     Files=1, Tests=1,  1 wallclock secs ( 0.35 cusr +  0.06 csys =  0.41 CPU)     [warning] server localhost:8529 shutdown 


Note: Want even more diagnostic output? Set APACHE_ TEST_TRACE_ LEVEL=debug and APACHE_ TEST_COLOR=1 to see colorized , lower-level debugging information .

The biggest step is to contact the test server to make requests so that you can test whether the returned content is what you expected. Apache::TestRequest optionally exports a slew of functions that make this easy. thumbnail.t uses the GET_BODY( ) function, which makes a simple GET request to the test server and returns the content. By using Apache::TestRequest 's functions, you never have to know the port number or IP address of your test server.

Other useful Apache::TestRequest exports include functions such as GET( ) , HEAD( ) , PUT( ) , and POST( ) to make those types of requests. Each of these has a corresponding _OK function. For example, GET_OK( ) makes a GET request and checks the resulting response code. Similarly, _BODY functions retrieve just the content of the response. _BODY_ASSERT functions check the success of the request and return the content. Finally, a set of UPLOAD( ) functions exist for sending entire files.


Note: If you extended Thumbnail.pm to allow the pixel constraint to be set in the Apache configuration with PerlSetVar, what would you add to the tests?

What about...

Q:

Can I use other test modules with Apache::Test ?

A:

Sure. Provide -withtestmore as an argument to use Apache::Test and all of Test::More 's functions instantly become available:

 #!perl          use strict;     use warnings;          use Apache::Test  qw(-withtestmore)  ;     use Apache::TestUtil;     use Apache::TestRequest qw( GET_BODY );     use Imager;          plan( tests => 1, need_module('mod_perl') );          my $content = GET_BODY('/images/panorama.jpg');          my $img     = Imager->new(  );     $img->open( data => $content, type => 'jpeg' )         or die $img->errstr(  );          my $max     = 150;  diag  ( 'assuming constraint is $max pixels' );  diag  ( 'width: '  . $img->getwidth(  )    );  diag  ( 'height: ' . $img->getheight(  )   );          ok( ( $img->getwidth(  ) =  = $max ) or ( $img->getheight(  ) =  = $max ) ); 

Note that at the time of this writing, compatibility with test modules that use Test::Builder is still experimental.

Where to learn more

This lab is only a glimpse into the world of testing Apache with Perl. More advanced concepts include testing C modules and debugging tests. "Running and Developing Tests with the Apache::Test Framework" at http://perl.apache.org/docs/general/testing/testing.html covers these subjects in more detail.



Perl Testing. A Developer's Notebook
Perl Testing: A Developers Notebook
ISBN: 0596100922
EAN: 2147483647
Year: 2003
Pages: 107

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net