more tests plus a framework for making test generators

This commit is contained in:
Doug Bell 2007-10-12 20:44:38 +00:00
parent 983a725558
commit 320c2c07b0
5 changed files with 752 additions and 8 deletions

View file

@ -0,0 +1,94 @@
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2007 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
# The goal of this test is to test the editSave and
# processPropertiesFromFormPost methods.
use FindBin;
use strict;
use lib "$FindBin::Bin/../../../../lib";
use Scalar::Util qw( blessed );
use WebGUI::Test;
use WebGUI::Session;
use Test::More;
use WebGUI::Test::Maker::HTML;
use WebGUI::Asset::File::Image::Photo;
#----------------------------------------------------------------------------
# Init
my $session = WebGUI::Test->session;
my $node = WebGUI::Asset->getImportNode($session);
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->set({name=>"Photo Test"});
my $maker = WebGUI::Test::Maker::HTML->new;
my $gallery
= $node->addChild({
className => "WebGUI::Asset::Wobject::PhotoGallery",
});
my $album
= $gallery->addChild({
className => "WebGUI::Asset::Wobject::PhotoAlbum",
});
my $photo
= $gallery->addChild({
className => "WebGUI::Asset::File::Image::Photo",
});
#----------------------------------------------------------------------------
# Cleanup
END {
$versionTag->rollback();
}
#----------------------------------------------------------------------------
# Tests
plan tests => 0;
#----------------------------------------------------------------------------
# Test permissions
# Edit an existing photo
$maker->prepare({
object => $photo,
method => "www_edit",
userId => "1",
test_privilege => "insufficient",
})->run;
# Save a new photo
$maker->prepare({
object => $photo,
method => "www_editSave",
userId => "1",
test_privilege => "insufficient",
})->run;
#----------------------------------------------------------------------------
# Test processPropertiesFromFormPost errors
# TODO: This test should use i18n.
# TODO: This error / test should occur in File, not Photo
$maker->prepare({
object => $album
method => "www_editSave",
formParams => {
},
test_regex => [
qr/You must select a file/,
qr/You must enter a title/,
],
})->run;
#----------------------------------------------------------------------------
# Test editSave success result
#----------------------------------------------------------------------------

View file

@ -19,6 +19,7 @@ use Scalar::Util qw( blessed );
use WebGUI::Test;
use WebGUI::Session;
use Test::More;
use WebGUI::Test::Maker::HTML;
use WebGUI::Asset::File::Image::Photo;
#----------------------------------------------------------------------------
@ -27,6 +28,7 @@ my $session = WebGUI::Test->session;
my $node = WebGUI::Asset->getImportNode($session);
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->set({name=>"Photo Test"});
my $maker = WebGUI::Test::Maker::HTML->new;
my $otherParent
= $node->addChild({
className => "WebGUI::Asset::Wobject::Layout",
@ -109,14 +111,13 @@ is_deeply(
#----------------------------------------------------------------------------
# www_makeShortcut is only available to those who can edit the photo
my $html = WebGUI::Test->getPage($photo, "www_makeShortcut", {
userId => 1,
});
like(
$html, qr/permission denied/i,
"www_makeShortcut is not allowed to those who can't edit the photo",
);
$maker->prepare({
object => $photo,
method => "www_makeShortcut",
userId => 1,
test_privilege => "insufficient",
});
$maker->run;
#----------------------------------------------------------------------------
# www_makeShortcut

192
t/lib/WebGUI/Test/Maker.pm Normal file
View file

@ -0,0 +1,192 @@
package WebGUI::Test::Maker;
use Test::More;
=head1 NAME
WebGUI::Test::Maker
=head1 SYNOPSIS
use Test::More;
use WebGUI::Test::Maker;
my $maker = WebGUI::Test::Maker->new();
$maker->set( test => sub { ... } );
$maker->set( plan_per_test => 2 );
$maker->prepare({
title => "Test something",
args => [ ... ],
});
plan tests => $maker->plan;
$maker->run;
=head1 DESCRIPTION
Test generator for generating repeatable tests.
Set a subroutine that runs some tests and run it over and over with
different arguments.
=head1 DEPENDS
This module depends on
=over 4
=item *
Test::More
=back
=head1 METHODS
=head2 new
Create a new WebGUI::Test::Maker object.
=cut
sub new {
my $class = shift;
my $self = {};
return bless $self, $class;
}
#----------------------------------------------------------------------------
=head2 get
Get a setting. Set L<set> for a list of settings.
=cut
sub get {
my $self = shift;
my $key = shift;
return $self->{_settings}->{$key};
}
#----------------------------------------------------------------------------
=head2 plan
Returns the number of tests currently prepared. This module is so generic
that you must set the C<plan_per_test> value before calling this method.
=cut
sub plan {
my $self = shift;
return $self->plan_per_test * @{$self->{_tests}};
}
#----------------------------------------------------------------------------
=head2 plan_per_test
Returns the current value of the C<plan_per_test> setting.
=cut
sub plan_per_test {
return $self->get("plan_per_test");
}
#----------------------------------------------------------------------------
=head2 prepare
Prepare a test(s). Returns the object for convenience. The following keys
are optional:
=over 4
=item args
An array reference of arguments to the subroutine.
=back
There are no required arguments.
=cut
sub prepare {
my $self = shift;
my @tests = @_;
my $test_num = 0;
for my $test (@tests) {
$test_num++;
push @{$self->{_tests}}, $test;
}
return $self;
}
#----------------------------------------------------------------------------
=head2 run
Run the tests we've prepared and delete them as we run them.
=cut
sub run {
my $self = shift;
while (my $test = shift @{ $self->{_tests} }) {
my $sub = $self->get("test");
if ($test->{args}) {
$sub->(@{ $test->{args} });
}
else {
$sub->();
}
}
}
#----------------------------------------------------------------------------
=head2 set
Set a setting.
Available settings:
=over 4
=item test
A subref that runs some tests. The first argument to this subref will be the
WebGUI::Test::Maker object. The second and subsequent arguments will be the
C<args> key from the prepared test.
=item plan_per_test
Set the number of tests that each C<test> sub runs to be used to plan the
number of total tests that will be run.
=back
=cut
sub set {
my $self = shift;
my $key = shift;
my $value = shift;
$self->{_setting}->{$key} = $value;
}
1;

View file

@ -0,0 +1,250 @@
package WebGUI::Test::Maker::HTML;
use base 'WebGUI::Test::Maker';
use Scalar::Util qw( blessed );
use Test::More;
=head1 NAME
WebGUI::Test::Maker::HTML -- Test::Maker subclass for WebGUI HTMLs
=head1 SYNOPSIS
use Test::More;
use WebGUI::Test::Maker::HTML;
my $maker = WebGUI::Test::Maker::HTML->new();
$maker->prepare({
object => $object,
method => "www_editSave",
user => WebGUI::User->new,
userId => "userId",
formParams => { ... },
uploads => { ... },
# Test for a WebGUI::Session::Privilege page
test_privilege => "permission",
# Test for some regular expressions
test_regex => [ qr/../, qr/.../, ... ],
});
plan tests => $maker->plan;
$maker->run;
=head1 DESCRIPTION
This Test::Maker subclass tests the HTML output by WebGUI methods in a
variety of ways.
Uses WebGUI::Test->getPage to get the HTML for a page, and so is limited
to whatever C<getPage> can access.
=head1 TODO
Provide a method to give a proper HTML::Parser to test with.
Provide a method to test that a certain page was created with a certain
template.
=head1 DEPENDS
This module depends on
=over 4
=item *
Test::More
=back
=head1 METHODS
=head2 new
Create a new WebGUI::Test::Maker::HTML object.
=head2 get
Get a setting. Set L<set> for a list of settings.
#----------------------------------------------------------------------------
=head2 plan
This module plans as follows:
- 1 and only 1 test for any test_privilege test
- 1 test for each member of a test_regex test
=cut
sub plan {
my $self = shift;
my $plan;
for my $test ( @{ $self->{_tests} } ) {
if ($test->{test_privilege}) {
$plan++;
next;
}
if ($test->{test_regex}) {
$plan += @{$test->{test_regex}};
}
}
return $plan;
}
#----------------------------------------------------------------------------
=head2 plan_per_test
Returns undef. There is no way to pre-calculate how many tests this will run
=cut
sub plan_per_test {
return undef;
}
#----------------------------------------------------------------------------
=head2 prepare
Prepare a test(s). Returns the object for convenience. The following keys
are required:
=over 4
=item object
An instanciated object to work on.
=item method
The permissions method to test
=back
At least one of the following keys are required:
=over 4
=item test_privilege
Tests for a WebGUI::Session::Privilege response. Valid values for this key
are: adminOnly, insufficient, noAccess, notMember, vitalComponent
=item test_regex
Tests for some regular expressions. This key must be an array reference of
qr().
=back
The following key are optional:
=over 4
=item user
A WebGUI::User object to use for the test.
=item userId
A user ID to make a WebGUI::User object to use for the test
=item formParams
A hash reference of form parameters to use for the test
=item uploads
A hash reference of file uploads to use for the test
=back
=cut
sub prepare {
my $self = shift;
my @tests = @_;
my $test_num = 0;
for my $test (@tests) {
$test_num++;
croak("Couldn't prepare: Test $test_num has no object")
unless $test->{object};
croak("Couldn't prepare: Test $test_num has no method")
unless $test->{method};
croak("Couldn't prepare: Test $test_num has test (test_privilege or test_regex)")
unless $test->{test_privilege} || $test->{test_regex};
croak("Couldn't prepare: Test $test_num, test_regex is not an array reference")
if $test->{test_regex} && ref $test->{test_regex} ne "ARRAY";
croak("Couldn't prepare: Test $test_num, $test->{test_privilege} is not a valid test_privilege value (adminOnly, insufficient, noAccess, notMember, vitalComponent)")
if $test->{test_privilege} && $test->{test_privilege} =~ m/adminOnly|insufficient|noAccess|notMember|vitalComponent/;
push @{$self->{_tests}}, $test;
}
return $self;
}
#----------------------------------------------------------------------------
=head2 run
Run the tests we've prepared and delete them as we run them.
=cut
sub run {
my $self = shift;
while (my $test = shift @{ $self->{_tests} }) {
my $o = $test->{object};
my $m = $test->{method};
# Get the HTML
my $opts = {};
for my $key (qw{ }) {
$opts->{$key} = $test->{$key};
}
my $html
= WebGUI::Test->getPage( $o, $m, $opts );
# Run the tests
if ($test->{test_privilege}) {
my $priv_method = $test->{test_privilege};
my $test = $o->session->privilege->$priv_method();
like( $html, $test, "$m contains privilege message $priv_method for object " . blessed $o );
next;
}
if ($test->{test_regex}) {
for my $regex ( @{ $test->{test_regex} } ) {
like( $html, $regex, "$m contains $regex for object " . blessed $o );
}
}
}
}
#----------------------------------------------------------------------------
=head2 set
Set a setting.
Currently this module has no settings
=cut
1;

View file

@ -0,0 +1,207 @@
package WebGUI::Test::Maker::Permission;
use base 'WebGUI::Test::Maker';
use Scalar::Util qw( blessed );
use Test::More;
=head1 NAME
WebGUI::Test::Maker::Permission -- Test::Maker subclass for WebGUI Permissions
=head1 SYNOPSIS
use Test::More;
use WebGUI::Test::Maker::Permission;
my $maker = WebGUI::Test::Maker::Permission->new();
$maker->prepare({
object => WebGUI::Asset->new,
method => "canView",
pass => [userId, userId],
fail => [userId, userId],
});
plan tests => $maker->plan;
$maker->run;
=head1 DESCRIPTION
Test generator for testing WebGUI permissions. WebGUI permissions subroutines
take a single argument (a userId), or they use the default user from the
current session. They return true if the user has permission, or false
otherwise.
This module tests permissions subroutines by running a list of userIds that
should either pass or fail the permissions.
=head1 DEPENDS
This module depends on
=over 4
=item *
Test::More
=back
=head1 METHODS
=head2 new
Create a new WebGUI::Test::Maker::Permission object.
=head2 get
Get a setting. Set L<set> for a list of settings.
#----------------------------------------------------------------------------
=head2 plan
Returns the number of tests currently prepared. This module runs two tests
for each userId in either the C<pass> or C<fail> keys of the C<prepare()>
hash reference.
=cut
sub plan {
my $self = shift;
my $plan;
for my $test ( @{$self->{_tests}} ) {
if ($test->{pass}) {
$plan += @{$test->{pass}} * 2;
}
if ($test->{fail}) {
$plan += @{$test->{fail}} * 2;
}
}
return $plan;
}
#----------------------------------------------------------------------------
=head2 plan_per_test
Returns undef. There is no way to pre-calculate how many tests this will run
=cut
sub plan_per_test {
return undef;
}
#----------------------------------------------------------------------------
=head2 prepare
Prepare a test(s). Returns the object for convenience. The following keys
are required:
=over 4
=item object
An instanciated object to work on.
=item method
The permissions method to test
=item pass
An array reference of userIds that should pass the permissions test.
=item fail
An array reference of userIds that should fail the permissions test.
=back
There are no optional parameters.
=cut
sub prepare {
my $self = shift;
my @tests = @_;
my $test_num = 0;
for my $test (@tests) {
$test_num++;
croak("Couldn't prepare: Test $test_num has no object")
unless $test->{object};
croak("Couldn't prepare: Test $test_num has no method")
unless $test->{method};
croak("Couldn't prepare: Test $test_num has no pass/fail")
unless $test->{pass} || $test->{fail};
croak("Couldn't prepare: Test $test_num, pass is not an array reference")
if $test->{pass} && ref $test->{pass} ne "ARRAY";
croak("Couldn't prepare: Test $test_num, fail is not an array reference")
if $test->{fail} && ref $test->{fail} ne "ARRAY";
push @{$self->{_tests}}, $test;
}
return $self;
}
#----------------------------------------------------------------------------
=head2 run
Run the tests we've prepared and delete them as we run them.
=cut
sub run {
my $self = shift;
while (my $test = shift @{ $self->{_tests} }) {
my $o = $test->{object};
my $m = $test->{method};
if ($test->{pass}) {
for my $userId (@{$test->{pass}}) {
# Test the userId parameter
ok( $o->$m($userId), "$userId passes $m check for " . blessed $o );
# Test the default session user
my $oldUser = $o->session->user;
$o->session->user( WebGUI::User->new($o->session, $userId) );
ok( $o->$m(), "$userId passes $m check using default user for " . blessed $o );
$o->session->user($oldUser);
}
}
if ($test->{fail}) {
for my $userId (@{$test->{fail}}) {
# Test the userId parameter
ok( !($o->$m($userId)), "$userId fails $m check for " . blessed $o );
# Test the default session user
my $oldUser = $o->session->user;
$o->session->user( WebGUI::User->new($o->session, $userId) );
ok( !($o->$m()), "$userId fails $m check using default user for " . blessed $o );
$o->session->user($oldUser);
}
}
}
}
#----------------------------------------------------------------------------
=head2 set
Set a setting.
Currently this module has no settings
=cut
1;