WWW::Mechanize subclassing to help tests

petdance on 2004-04-20T20:34:37

We do plenty of web app testing using WWW::Mechanize. A typical .t file will look like:

use WWW::Mechanize; use Test::HTML::Lint;

my $startURL = $ENV{TWSMOKESERVER} or die "TWSMOKESERVER not set";

my $agent = WWW::Mechanize->new(); $agent->get( "$startURL/about_reading_programs.html" ); ok( $agent->success, 'got a page' ); like( $agent->title, qr/Reading Management Programs/, 'about reading programs page title' );

html_ok( $agent->content, 'about reading programs page HTML' );


So now we've started using a subclass, TW::Mechanize (TW is our app).

use TW::Mechanize;

my $startURL = $ENV{TWSMOKESERVER} or die "TWSMOKESERVER not set";

my $agent = TW::Mechanize->new(); # make sure we get the about-reading-programs page $agent->get( "$startURL/about_reading_programs.html" ); ok( $agent->success, 'got a page' ); $agent->title_like( qr/Reading Management Programs/, 'about reading programs page title' ); $agent->html_ok( 'about reading programs page HTML' );


At some point, we'll probably make that html_ok call part of every call that gets made.

Here's what TW::Mechanize looks like:

package TW::Mechanize;

use strict; use warnings; use WWW::Mechanize; use Test::More;

use base qw( WWW::Mechanize );

=head1 NAME

TW::Mechanize - The TW-specific mech subclass

=head1 SYNOPSIS

use TW::Mechanize;

my $mech = TW::Mechanize->new; $mech->get( $url );

=head1 DESCRIPTION

The TW mech is a standard WWW::Mechanize, with TW-specific methods added.

=head1 METHODS

=head2 new

Standard Mech constructor.

=cut

sub new { my $class = shift;

my %default_args = ( # None yet ); my $self = $class->SUPER::new( %default_args, @_ );

return $self; }

=head2 html_ok( [$msg] )

Checks the validity of the HTML on the current page. If the page is not HTML, then it fails.

=cut

sub html_ok { my $self = shift; my $msg = shift;

my $ok;

if ( $self->is_html ) { require Test::HTML::Lint; $ok = Test::HTML::Lint::html_ok( $self->content, $msg ); } else { $ok = fail( $msg ); }

return $ok; }

=head2 title_is( $str [, $msg ] )

Tells if the title of the page is the given string.

=cut

sub title_is { my $self = shift; my $str = shift; my $msg = shift;

return is( $self->title, $str, $msg ); }

=head2 title_like( $regex [, $msg ] )

Tells if the title of the page matches the given regex

=cut

sub title_like { my $self = shift; my $regex = shift; my $msg = shift;

return like( $self->title, $regex, $msg ); }

1; # Happy
We could put autocheck => 1 as a default parm in the constructor and not have to check success any more, too....


Decorate!

brian_d_foy on 2004-04-21T00:41:10

If you only want to add new methods, you could decorate WWW::Mech rather than subclass it. Just add methods to WWW::Mech from TW::Mech since it does not have to actually be the package TW::Mech.

At some point, it looks like you will have Mech doing everything. :)

Test module

Dom2 on 2004-04-21T08:27:17

Looks like Test::Mechanize would be a good addition to the WWW::Mechanize distribution. :-)

-Dom

Re:Test module

petdance on 2004-04-21T13:49:32

Well, don't think I haven't thought about it. :-)

I don't see it being a Test:: module, but maybe so. It wouldn't be part of Mech proper, because it would bring in too many requirements, and Mech is fat enough as is.

It's certainly an idea rolling around in my head....