Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added README back in - just for github

  • Loading branch information...
commit f3291cbed31dda8d41fed348e73b258a25c42b1e 1 parent 0ebe3ce
Adrian Howard authored
Showing with 1,307 additions and 1 deletion.
  1. +0 −1  .gitignore
  2. +1,307 −0 README
1  .gitignore
View
@@ -4,5 +4,4 @@ META.yml
MYMETA.yml
_build/
blib
-README
Makefile.PL
1,307 README
View
@@ -0,0 +1,1307 @@
+NAME
+ Test::Class - Easily create test classes in an xUnit/JUnit style
+
+SYNOPSIS
+ package Example::Test;
+ use base qw(Test::Class);
+ use Test::More;
+
+ # setup methods are run before every test method.
+ sub make_fixture : Test(setup) {
+ my $array = [1, 2];
+ shift->{test_array} = $array;
+ };
+
+ # a test method that runs 1 test
+ sub test_push : Test {
+ my $array = shift->{test_array};
+ push @$array, 3;
+ is_deeply($array, [1, 2, 3], 'push worked');
+ };
+
+ # a test method that runs 4 tests
+ sub test_pop : Test(4) {
+ my $array = shift->{test_array};
+ is(pop @$array, 2, 'pop = 2');
+ is(pop @$array, 1, 'pop = 1');
+ is_deeply($array, [], 'array empty');
+ is(pop @$array, undef, 'pop = undef');
+ };
+
+ # teardown methods are run after every test method.
+ sub teardown : Test(teardown) {
+ my $array = shift->{test_array};
+ diag("array = (@$array) after test(s)");
+ };
+
+ later in a nearby .t file
+
+ #! /usr/bin/perl
+ use Example::Test;
+
+ # run all the test methods in Example::Test
+ Test::Class->runtests;
+
+ Outputs:
+
+ 1..5
+ ok 1 - pop = 2
+ ok 2 - pop = 1
+ ok 3 - array empty
+ ok 4 - pop = undef
+ # array = () after test(s)
+ ok 5 - push worked
+ # array = (1 2 3) after test(s)
+
+DESCRIPTION
+ Test::Class provides a simple way of creating classes and objects to
+ test your code in an xUnit style.
+
+ Built using Test::Builder, it was designed to work with other
+ Test::Builder based modules (Test::More, Test::Differences,
+ Test::Exception, etc.).
+
+ *Note:* This module will make more sense, if you are already familiar
+ with the "standard" mechanisms for testing perl code. Those unfamiliar
+ with Test::Harness, Test::Simple, Test::More and friends should go take
+ a look at them now. Test::Tutorial is a good starting point.
+
+INTRODUCTION
+ A brief history lesson
+ In 1994 Kent Beck wrote a testing framework for Smalltalk called SUnit.
+ It was popular. You can read a copy of his original paper at
+ <http://www.xprogramming.com/testfram.htm>.
+
+ Later Kent Beck and Erich Gamma created JUnit for testing Java
+ <http://www.junit.org/>. It was popular too.
+
+ Now there are xUnit frameworks for every language from Ada to XSLT. You
+ can find a list at <http://www.xprogramming.com/software.htm>.
+
+ While xUnit frameworks are traditionally associated with unit testing
+ they are also useful in the creation of functional/acceptance tests.
+
+ Test::Class is (yet another) implementation of xUnit style testing in
+ Perl.
+
+ Why you should use Test::Class
+ Test::Class attempts to provide simple xUnit testing that integrates
+ simply with the standard perl *.t style of testing. In particular:
+
+ * All the advantages of xUnit testing. You can easily create test
+ fixtures and isolate tests. It provides a framework that should be
+ familiar to people who have used other xUnit style test systems.
+
+ * It is built with Test::Builder and should co-exist happily with all
+ other Test::Builder based modules. This makes using test classes in
+ *.t scripts, and refactoring normal tests into test classes, much
+ simpler because:
+
+ * You do not have to learn a new set of new test APIs and can
+ continue using ok(), like(), etc. from Test::More and friends.
+
+ * Skipping tests and todo tests are supported.
+
+ * You can have normal tests and Test::Class classes co-existing in
+ the same *.t script. You don't have to re-write an entire
+ script, but can use test classes as and when it proves useful.
+
+ * You can easily package your tests as classes/modules, rather than
+ *.t scripts. This simplifies reuse, documentation and distribution,
+ encourages refactoring, and allows tests to be extended by
+ inheritance.
+
+ * You can have multiple setup/teardown methods. For example have one
+ teardown method to clean up resources and another to check that
+ class invariants still hold.
+
+ * It can make running tests faster. Once you have refactored your *.t
+ scripts into classes they can be easily run from a single script.
+ This gains you the (often considerable) start up time that each
+ separate *.t script takes.
+
+ Why you should *not* use Test::Class
+ * If your *.t scripts are working fine then don't bother with
+ Test::Class. For simple test suites it is almost certainly overkill.
+ Don't start thinking about using Test::Class until issues like
+ duplicate code in your test scripts start to annoy.
+
+ * If you are distributing your code it is yet another module that the
+ user has to have to run your tests (unless you distribute it with
+ your test suite of course).
+
+ * If you are used to the TestCase/Suite/Runner class structure used by
+ JUnit and similar testing frameworks you may find Test::Unit more
+ familiar (but try reading "HELP FOR CONFUSED JUNIT USERS" before you
+ give up).
+
+TEST CLASSES
+ A test class is just a class that inherits from Test::Class. Defining a
+ test class is as simple as doing:
+
+ package Example::Test;
+ use base qw(Test::Class);
+
+ Since Test::Class does not provide its own test functions, but uses
+ those provided by Test::More and friends, you will nearly always also
+ want to have:
+
+ use Test::More;
+
+ to import the test functions into your test class.
+
+METHOD TYPES
+ There are three different types of method you can define using
+ Test::Class.
+
+ 1) Test methods
+ You define test methods using the Test attribute. For example:
+
+ package Example::Test;
+ use base qw(Test::Class);
+ use Test::More;
+
+ sub subtraction : Test {
+ is( 2-1, 1, 'subtraction works );
+ };
+
+ This declares the "subtraction" method as a test method that runs one
+ test.
+
+ If your test method runs more than one test, you should put the number
+ of tests in brackets like this:
+
+ sub addition : Test(2) {
+ is(10 + 20, 30, 'addition works');
+ is(20 + 10, 30, ' both ways');
+ };
+
+ If you don't know the number of tests at compile time you can use
+ "no_plan" like this.
+
+ sub check_class : Test(no_plan) {
+ my $objects = shift->{objects};
+ isa_ok($_, "Object") foreach @$objects;
+ };
+
+ or use the :Tests attribute, which acts just like ":Test" but defaults
+ to "no_plan" if no number is given:
+
+ sub check_class : Tests {
+ my $objects = shift->{objects};
+ isa_ok($_, "Object") foreach @$objects;
+ };
+
+ 2) Setup and teardown methods
+ Setup and teardown methods are run before and after every test. For
+ example:
+
+ sub before : Test(setup) { diag("running before test") };
+ sub after : Test(teardown) { diag("running after test") };
+
+ You can use setup and teardown methods to create common objects used by
+ all of your test methods (a test *fixture*) and store them in your
+ Test::Class object, treating it as a hash. For example:
+
+ sub pig : Test(setup) {
+ my $self = shift;
+ $self->{test_pig} = Pig->new;
+ };
+
+ sub born_hungry : Test {
+ my $pig = shift->{test_pig};
+ is($pig->hungry, 'pigs are born hungry');
+ };
+
+ sub eats : Test(3) {
+ my $pig = shift->{test_pig};
+ ok( $pig->feed, 'pig fed okay');
+ ok(! $pig->hungry, 'fed pig not hungry');
+ ok(! $pig->feed, 'cannot feed full pig');
+ };
+
+ You can also declare setup and teardown methods as running tests. For
+ example you could check that the test pig survives each test method by
+ doing:
+
+ sub pig_alive : Test(teardown => 1) {
+ my $pig = shift->{test_pig};
+ ok($pig->alive, 'pig survived tests' );
+ };
+
+ 3) Startup and shutdown methods
+ Startup and shutdown methods are like setup and teardown methods for the
+ whole test class. All the startup methods are run once when you start
+ running a test class. All the shutdown methods are run once just before
+ a test class stops running.
+
+ You can use these to create and destroy expensive objects that you don't
+ want to have to create and destroy for every test - a database
+ connection for example:
+
+ sub db_connect : Test(startup) {
+ shift->{dbi} = DBI->connect;
+ };
+
+ sub db_disconnect : Test(shutdown) {
+ shift->{dbi}->disconnect;
+ };
+
+ Just like setup and teardown methods you can pass an optional number of
+ tests to startup and shutdown methods. For example:
+
+ sub example : Test(startup => 1) {
+ ok(1, 'a startup method with one test');
+ };
+
+ If a startup method has a failing test or throws an exception then all
+ other tests for the current test object are ignored.
+
+RUNNING TESTS
+ You run test methods with runtests(). Doing:
+
+ Test::Class->runtests
+
+ runs all of the test methods in every loaded test class. This allows you
+ to easily load multiple test classes in a *.t file and run them all.
+
+ #! /usr/bin/perl
+
+ # load all the test classes I want to run
+ use Foo::Test;
+ use Foo::Bar::Test;
+ use Foo::Fribble::Test;
+ use Foo::Ni::Test;
+
+ # and run them all
+ Test::Class->runtests;
+
+ You can use Test::Class::Load to automatically load all the test classes
+ in a given set of directories.
+
+ If you need finer control you can create individual test objects with
+ new(). For example to just run the tests in the test class
+ "Foo::Bar::Test" you can do:
+
+ Example::Test->new->runtests
+
+ You can also pass runtests() a list of test objects to run. For example:
+
+ my $o1 = Example::Test->new;
+ my $o2 = Another::Test->new;
+ # runs all the tests in $o1 and $o2
+ $o1->runtests($o2);
+
+ Since, by definition, the base Test::Class has no tests you could also
+ have written:
+
+ my $o1 = Example::Test->new;
+ my $o2 = Another::Test->new;
+ Test::Class->runtests($o1, $o2);
+
+ If you pass runtests() class names it will automatically create test
+ objects for you, so the above can be written more compactly as:
+
+ Test::Class->runtests(qw( Example::Test Another::Test ))
+
+ In all of the above examples runtests() will look at the number of tests
+ both test classes run and output an appropriate test header for
+ Test::Harness automatically.
+
+ What happens if you run test classes and normal tests in the same
+ script? For example:
+
+ Test::Class->runtests;
+ ok(Example->new->foo, 'a test not in the test class');
+ ok(Example->new->bar, 'ditto');
+
+ Test::Harness will complain that it saw more tests than it expected
+ since the test header output by runtests() will not include the two
+ normal tests.
+
+ To overcome this problem you can pass an integer value to runtests().
+ This is added to the total number of tests in the test header. So the
+ problematic example can be rewritten as follows:
+
+ Test::Class->runtests(+2);
+ ok(Example->new->foo, 'a test not in the test class');
+ ok(Example->new->bar, 'ditto');
+
+ If you prefer to write your test plan explicitly you can use
+ expected_tests() to find out the number of tests a class/object is
+ expected to run.
+
+ Since runtests() will not output a test plan if one has already been set
+ the previous example can be written as:
+
+ plan tests => Test::Class->expected_tests(+2);
+ Test::Class->runtests;
+ ok(Example->new->foo, 'a test not in the test class');
+ ok(Example->new->bar, 'ditto');
+
+ *Remember:* Test objects are just normal perl objects. Test classes are
+ just normal perl classes. Setup, test and teardown methods are just
+ normal methods. You are completely free to have other methods in your
+ class that are called from your test methods, or have object specific
+ "new" and "DESTROY" methods.
+
+ In particular you can override the new() method to pass parameters to
+ your test object, or re-define the number of tests a method will run.
+ See num_method_tests() for an example.
+
+TEST DESCRIPTIONS
+ The test functions you import from Test::More and other Test::Builder
+ based modules usually take an optional third argument that specifies the
+ test description, for example:
+
+ is $something, $something_else, 'a description of my test';
+
+ If you do not supply a test description, and the test function does not
+ supply its own default, then Test::Class will use the name of the
+ currently running test method, replacing all "_" characters with spaces
+ so:
+
+ sub one_plus_one_is_two : Test {
+ is 1+1, 2;
+ }
+
+ will result in:
+
+ ok 1 - one plus one is two
+
+RUNNING ORDER OF METHODS
+ Methods of each type are run in the following order:
+
+ 1. All of the startup methods in alphabetical order
+
+ 2. For each test method, in alphabetical order:
+
+ * All of the setup methods in alphabetical order
+
+ * The test method.
+
+ * All of the teardown methods in alphabetical order
+
+ 3. All of the shutdown methods in alphabetical order.
+
+ Most of the time you should not care what order tests are run in, but it
+ can occasionally be useful to force some test methods to be run early.
+ For example:
+
+ sub _check_new {
+ my $self = shift;
+ isa_ok(Object->new, "Object") or $self->BAILOUT('new fails!');
+ };
+
+ The leading "_" will force the above method to run first - allowing the
+ entire suite to be aborted before any other test methods run.
+
+HANDLING EXCEPTIONS
+ If a startup, setup, test, teardown or shutdown method dies then
+ runtests() will catch the exception and fail any remaining test. For
+ example:
+
+ sub test_object : Test(2) {
+ my $object = Object->new;
+ isa_ok( $object, "Object" ) or die "could not create object\n";
+ ok( $object->open, "open worked" );
+ };
+
+ will produce the following if the first test failed:
+
+ not ok 1 - The object isa Object
+ # Failed test 'The object isa Object'
+ # at /Users/adrianh/Desktop/foo.pl line 14.
+ # (in MyTest->test_object)
+ # The object isn't defined
+ not ok 2 - test_object died (could not create object)
+ # Failed test 'test_object died (could not create object)'
+ # at /Users/adrianh/Desktop/foo.pl line 19.
+ # (in MyTest->test_object)
+
+ This can considerably simplify testing code that throws exceptions.
+
+ Rather than having to explicitly check that the code exited normally
+ (e.g. with "lives_ok" in Test::Exception) the test will fail
+ automatically - without aborting the other test methods. For example
+ contrast:
+
+ use Test::Exception;
+
+ my $file;
+ lives_ok { $file = read_file('test.txt') } 'file read';
+ is($file, "content", 'test file read');
+
+ with:
+
+ sub read_file : Test {
+ is(read_file('test.txt'), "content", 'test file read');
+ };
+
+ If more than one test remains after an exception then the first one is
+ failed, and the remaining ones are skipped.
+
+ Startup methods are a special case. Since startup methods will usually
+ be creating state needed by all the other test methods an exception
+ within a startup method will prevent all other test methods running.
+
+SKIPPED TESTS
+ You can skip the rest of the tests in a method by returning from the
+ method before all the test have finished running. The value returned is
+ used as the reason for the tests being skipped.
+
+ This makes managing tests that can be skipped for multiple reasons very
+ simple. For example:
+
+ sub flying_pigs : Test(5) {
+ my $pig = Pig->new;
+ isa_ok($pig, 'Pig') or return("cannot breed pigs")
+ can_ok($pig, 'takeoff') or return("pigs don't fly here");
+ ok($pig->takeoff, 'takeoff') or return("takeoff failed");
+ ok( $pig->altitude > 0, 'Pig is airborne' );
+ ok( $pig->airspeed > 0, ' and moving' );
+ };
+
+ If you run this test in an environment where "Pig->new" worked and the
+ takeoff method existed, but failed when ran, you would get:
+
+ ok 1 - The object isa Pig
+ ok 2 - can takeoff
+ not ok 3 - takeoff
+ ok 4 # skip takeoff failed
+ ok 5 # skip takeoff failed
+
+ You can also skip tests just as you do in Test::More or Test::Builder -
+ see "Conditional tests" in Test::More for more information.
+
+ *Note:* if you want to skip tests in a method with "no_plan" tests then
+ you have to explicitly skip the tests in the method - since Test::Class
+ cannot determine how many tests (if any) should be skipped:
+
+ sub test_objects : Tests {
+ my $self = shift;
+ my $objects = $self->{objects};
+ if (@$objects) {
+ isa_ok($_, "Object") foreach (@$objects);
+ } else {
+ $self->builder->skip("no objects to test");
+ };
+ };
+
+ Another way of overcoming this problem is to explicitly set the number
+ of tests for the method at run time using num_method_tests() or
+ "num_tests".
+
+ You can make a test class skip all of its tests by setting SKIP_CLASS()
+ before runtests() is called.
+
+TO DO TESTS
+ You can create todo tests just as you do in Test::More and Test::Builder
+ using the $TODO variable. For example:
+
+ sub live_test : Test {
+ local $TODO = "live currently unimplemented";
+ ok(Object->live, "object live");
+ };
+
+ See "Todo tests" in Test::Harness for more information.
+
+EXTENDING TEST CLASSES BY INHERITANCE
+ You can extend test methods by inheritance in the usual way. For example
+ consider the following test class for a "Pig" object.
+
+ package Pig::Test;
+ use base qw(Test::Class);
+ use Test::More;
+
+ sub testing_class { "Pig" };
+ sub new_args { (-age => 3) };
+
+ sub setup : Test(setup) {
+ my $self = shift;
+ my $class = $self->testing_class;
+ my @args = $self->new_args;
+ $self->{pig} = $class->new( @args );
+ };
+
+ sub _creation : Test {
+ my $self = shift;
+ isa_ok($self->{pig}, $self->testing_class)
+ or $self->FAIL_ALL('Pig->new failed');
+ };
+
+ sub check_fields : Test {
+ my $pig = shift->{pig};
+ is($pig->age, 3, "age accessed");
+ };
+
+ Next consider "NamedPig" a subclass of "Pig" where you can give your pig
+ a name.
+
+ We want to make sure that all the tests for the "Pig" object still work
+ for "NamedPig". We can do this by subclassing "Pig::Test" and overriding
+ the "testing_class" and "new_args" methods.
+
+ package NamedPig::Test;
+ use base qw(Pig::Test);
+ use Test::More;
+
+ sub testing_class { "NamedPig" };
+ sub new_args { (shift->SUPER::new_args, -name => 'Porky') };
+
+ Now we need to test the name method. We could write another test method,
+ but we also have the option of extending the existing "check_fields"
+ method.
+
+ sub check_fields : Test(2) {
+ my $self = shift;
+ $self->SUPER::check_fields;
+ is($self->{pig}->name, 'Porky', 'name accessed');
+ };
+
+ While the above works, the total number of tests for the method is
+ dependent on the number of tests in its "SUPER::check_fields". If we add
+ a test to "Pig::Test->check_fields" we will also have to update the
+ number of tests of "NamedPig::test->check_fields".
+
+ Test::Class allows us to state explicitly that we are adding tests to an
+ existing method by using the "+" prefix. Since we are adding a single
+ test to "check_fields" it can be rewritten as:
+
+ sub check_fields : Test(+1) {
+ my $self = shift;
+ $self->SUPER::check_fields;
+ is($self->{pig}->name, 'Porky', 'name accessed');
+ };
+
+ With the above definition you can add tests to "check_fields" in
+ "Pig::Test" without affecting "NamedPig::Test".
+
+RUNNING INDIVIDUAL TESTS
+ NOTE: The exact mechanism for running individual tests is likely to
+ change in the future.
+
+ Sometimes you just want to run a single test. Commenting out other tests
+ or writing code to skip them can be a hassle, so you can specify the
+ "TEST_METHOD" environment variable. The value is expected to be a valid
+ regular expression and, if present, only runs test methods whose names
+ match the regular expression. Startup, setup, teardown and shutdown
+ tests will still be run.
+
+ One easy way of doing this is by specifying the environment variable
+ *before* the "runtests" method is called.
+
+ Running a test named "customer_profile":
+
+ #! /usr/bin/perl
+ use Example::Test;
+
+ $ENV{TEST_METHOD} = 'customer_profile';
+ Test::Class->runtests;
+
+ Running all tests with "customer" in their name:
+
+ #! /usr/bin/perl
+ use Example::Test;
+
+ $ENV{TEST_METHOD} = '.*customer.*';
+ Test::Class->runtests;
+
+ If you specify an invalid regular expression, your tests will not be
+ run:
+
+ #! /usr/bin/perl
+ use Example::Test;
+
+ $ENV{TEST_METHOD} = 'C++';
+ Test::Class->runtests;
+
+ And when you run it:
+
+ TEST_METHOD (C++) is not a valid regular expression: Search pattern \
+ not terminated at (eval 17) line 1.
+
+ORGANISING YOUR TEST CLASSES
+ You can, of course, organise your test modules as you wish. My personal
+ preferences is:
+
+ * Name test classes with a suffix of "::Test" so the test class for
+ the "Foo::Bar" module would be "Foo::Bar::Test".
+
+ * Place all test classes in t/lib.
+
+ The Test::Class::Load provides a simple mechanism for easily loading all
+ of the test classes in a given set of directories.
+
+A NOTE ON LOADING TEST CLASSES
+ Due to its use of subroutine attributes Test::Class based modules must
+ be loaded at compile rather than run time. This is because the :Test
+ attribute is applied by a CHECK block.
+
+ This can be problematic if you want to dynamically load Test::Class
+ modules. Basically while:
+
+ require $some_test_class;
+
+ will break, doing:
+
+ BEGIN { require $some_test_class };
+
+ will work just fine. For more information on CHECK blocks see "BEGIN,
+ CHECK, INIT and END" in perlmod.
+
+ If you still can't arrange for your classes to be loaded at runtime, you
+ could use an alternative mechanism for adding your tests:
+
+ # sub test_something : Test(3) {...}
+ # becomes
+ sub test_something {...}
+ __PACKAGE__->add_testinfo('test_something', test => 3);
+
+ See the add_testinfo method for more details.
+
+METHODS
+ Creating and running tests
+ Test
+ # test methods
+ sub method_name : Test { ... };
+ sub method_name : Test(N) { ... };
+
+ # setup methods
+ sub method_name : Test(setup) { ... };
+ sub method_name : Test(setup => N) { ... };
+
+ # teardown methods
+ sub method_name : Test(teardown) { ... };
+ sub method_name : Test(teardown => N) { ... };
+
+ # startup methods
+ sub method_name : Test(startup) { ... };
+ sub method_name : Test(startup => N) { ... };
+
+ # shutdown methods
+ sub method_name : Test(shutdown) { ... };
+ sub method_name : Test(shutdown => N) { ... };
+
+ Marks a startup, setup, test, teardown or shutdown method. See
+ runtests() for information on how to run methods declared with the
+ "Test" attribute.
+
+ N specifies the number of tests the method runs.
+
+ * If N is an integer then the method should run exactly N tests.
+
+ * If N is an integer with a "+" prefix then the method is expected
+ to call its "SUPER::" method and extend it by running N
+ additional tests.
+
+ * If N is the string "no_plan" then the method can run an
+ arbitrary number of tests.
+
+ If N is not specified it defaults to 1 for test methods, and 0 for
+ startup, setup, teardown and shutdown methods.
+
+ You can change the number of tests that a method runs using
+ num_method_tests() or num_tests().
+
+ Tests
+ sub method_name : Tests { ... };
+ sub method_name : Tests(N) { ... };
+
+ Acts just like the ":Test" attribute, except that if the number of
+ tests is not specified it defaults to "no_plan". So the following
+ are equivalent:
+
+ sub silly1 :Test( no_plan ) { ok(1) foreach (1 .. rand 5) };
+ sub silly2 :Tests { ok(1) foreach (1 .. rand 5) };
+
+ new
+ $Tests = CLASS->new(KEY => VAL ...)
+ $Tests2 = $Tests->new(KEY => VAL ...)
+
+ Creates a new test object (blessed hashref) containing the specified
+ key/value pairs.
+
+ If called as an object method the existing object's key/value pairs
+ are copied into the new object. Any key/value pairs passed to "new"
+ override those in the original object if duplicates occur.
+
+ Since the test object is passed to every test method as it runs it
+ is a convenient place to store test fixtures. For example:
+
+ sub make_fixture : Test(setup) {
+ my $self = shift;
+ $self->{object} = Object->new();
+ $self->{dbh} = Mock::DBI->new(-type => normal);
+ };
+
+ sub test_open : Test {
+ my $self = shift;
+ my ($o, $dbh) = ($self->{object}, $self->{dbh});
+ ok($o->open($dbh), "opened ok");
+ };
+
+ See num_method_tests() for an example of overriding "new".
+
+ expected_tests
+ $n = $Tests->expected_tests
+ $n = CLASS->expected_tests
+ $n = $Tests->expected_tests(TEST, ...)
+ $n = CLASS->expected_tests(TEST, ...)
+
+ Returns the total number of tests that runtests() will run on the
+ specified class/object. This includes tests run by any setup and
+ teardown methods.
+
+ Will return "no_plan" if the exact number of tests is undetermined
+ (i.e. if any setup, test or teardown method has an undetermined
+ number of tests).
+
+ The "expected_tests" of an object after runtests() has been executed
+ will include any run time changes to the expected number of tests
+ made by num_tests() or num_method_tests().
+
+ "expected_tests" can also take an optional list of test objects,
+ test classes and integers. In this case the result is the total
+ number of expected tests for all the test/object classes (including
+ the one the method was applied to) plus any integer values.
+
+ "expected_tests" is useful when you're integrating one or more test
+ classes into a more traditional test script, for example:
+
+ use Test::More;
+ use My::Test::Class;
+
+ plan tests => My::Test::Class->expected_tests(+2);
+
+ ok(whatever, 'a test');
+ ok(whatever, 'another test');
+ My::Test::Class->runtests;
+
+ runtests
+ $allok = $Tests->runtests
+ $allok = CLASS->runtests
+ $allok = $Tests->runtests(TEST, ...)
+ $allok = CLASS->runtests(TEST, ...)
+
+ "runtests" is used to run test classes. At its most basic doing:
+
+ $test->runtests
+
+ will run the test methods of the test object $test, unless
+ "$test->SKIP_CLASS" returns a true value.
+
+ Unless you have already specified a test plan using Test::Builder
+ (or Test::More, et al) "runtests" will set the test plan just before
+ the first method that runs a test is executed.
+
+ If the environment variable "TEST_VERBOSE" is set "runtests" will
+ display the name of each test method before it runs like this:
+
+ # My::Test::Class->my_test
+ ok 1 - fribble
+ # My::Test::Class->another_test
+ ok 2 - bar
+
+ Just like expected_tests(), "runtests" can take an optional list of
+ test object/classes and integers. All of the test object/classes are
+ run. Any integers are added to the total number of tests shown in
+ the test header output by "runtests".
+
+ For example, you can run all the tests in test classes A, B and C,
+ plus one additional normal test by doing:
+
+ Test::Class->runtests(qw(A B C), +1);
+ ok(1==1, 'non class test');
+
+ Finally, if you call "runtests" on a test class without any
+ arguments it will run all of the test methods of that class, and all
+ subclasses of that class. For example:
+
+ #! /usr/bin/perl
+ # Test all the Foo stuff
+
+ use Foo::Test;
+ use Foo::Bar::Test;
+ use Foo::Ni::Test;
+
+ # run all the Foo*Test modules we just loaded
+ Test::Class->runtests;
+
+ SKIP_CLASS
+ $reason = CLASS->SKIP_CLASS;
+ CLASS->SKIP_CLASS( $reason );
+
+ Determines whether the test class CLASS should run it's tests. If
+ SKIP_CLASS returns a true value then runtests() will not run any of
+ the test methods in CLASS.
+
+ You can override the default on a class-by-class basis by supplying
+ a new value to SKIP_CLASS. For example if you have an abstract base
+ class that should not run just add the following to your module:
+
+ My::Abstract::Test->SKIP_CLASS( 1 );
+
+ This will not affect any sub-classes of "My::Abstract::Test" which
+ will run as normal.
+
+ If the true value returned by SKIP_CLASS is anything other than "1"
+ then a skip test is output using this value as the skip message. For
+ example:
+
+ My::Postgres::Test->SKIP_CLASS(
+ $ENV{POSTGRES_HOME} ? 0 : '$POSTGRES_HOME needs to be set'
+ );
+
+ will output something like this if "POSTGRES_HOME" is not set
+
+ ... other tests ...
+ ok 123 # skip My::Postgres::Test - $POSTGRES_HOME needs to be set
+ ... more tests ...
+
+ You can also override SKIP_CLASS for a class hierarchy. For example,
+ to prevent any subclasses of My::Postgres::Test running we could
+ override SKIP_CLASS like this:
+
+ sub My::Postgres::Test::SKIP_CLASS {
+ $ENV{POSTGRES_HOME} ? 0 : '$POSTGRES_HOME needs to be set'
+ };
+
+ Fetching and setting a method's test number
+ num_method_tests
+ $n = $Tests->num_method_tests($method_name)
+ $Tests->num_method_tests($method_name, $n)
+ $n = CLASS->num_method_tests($method_name)
+ CLASS->num_method_tests($method_name, $n)
+
+ Fetch or set the number of tests that the named method is expected
+ to run.
+
+ If the method has an undetermined number of tests then $n should be
+ the string "no_plan".
+
+ If the method is extending the number of tests run by the method in
+ a superclass then $n should have a "+" prefix.
+
+ When called as a class method any change to the expected number of
+ tests applies to all future test objects. Existing test objects are
+ unaffected.
+
+ When called as an object method any change to the expected number of
+ tests applies to that object alone.
+
+ "num_method_tests" is useful when you need to set the expected
+ number of tests at object creation time, rather than at compile
+ time.
+
+ For example, the following test class will run a different number of
+ tests depending on the number of objects supplied.
+
+ package Object::Test;
+ use base qw(Test::Class);
+ use Test::More;
+
+ sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ my $num_objects = @{$self->{objects}};
+ $self->num_method_tests('test_objects', $num_objects);
+ return($self);
+ };
+
+ sub test_objects : Tests {
+ my $self = shift;
+ ok($_->open, "opened $_") foreach @{$self->{objects}};
+ };
+ ...
+ # This runs two tests
+ Object::Test->new(objects => [$o1, $o2]);
+
+ The advantage of setting the number of tests at object creation
+ time, rather than using a test method without a plan, is that the
+ number of expected tests can be determined before testing begins.
+ This allows better diagnostics from runtests(), Test::Builder and
+ Test::Harness.
+
+ "num_method_tests" is a protected method and can only be called by
+ subclasses of Test::Class. It fetches or sets the expected number of
+ tests for the methods of the class it was *called in*, not the
+ methods of the object/class it was *applied to*. This allows test
+ classes that use "num_method_tests" to be subclassed easily.
+
+ For example, consider the creation of a subclass of Object::Test
+ that ensures that all the opened objects are read-only:
+
+ package Special::Object::Test;
+ use base qw(Object::Test);
+ use Test::More;
+
+ sub test_objects : Test(+1) {
+ my $self = shift;
+ $self->SUPER::test_objects;
+ my @bad_objects = grep {! $_->read_only} (@{$self->{objects}});
+ ok(@bad_objects == 0, "all objects read only");
+ };
+ ...
+ # This runs three tests
+ Special::Object::Test->new(objects => [$o1, $o2]);
+
+ Since the call to "num_method_tests" in Object::Test only affects
+ the "test_objects" of Object::Test, the above works as you would
+ expect.
+
+ num_tests
+ $n = $Tests->num_tests
+ $Tests->num_tests($n)
+ $n = CLASS->num_tests
+ CLASS->num_tests($n)
+
+ Set or return the number of expected tests associated with the
+ currently running test method. This is the same as calling
+ num_method_tests() with a method name of current_method().
+
+ For example:
+
+ sub txt_files_readable : Tests {
+ my $self = shift;
+ my @files = <*.txt>;
+ $self->num_tests(scalar(@files));
+ ok(-r $_, "$_ readable") foreach (@files);
+ };
+
+ Setting the number of expected tests at run time, rather than just
+ having a "no_plan" test method, allows runtests() to display
+ appropriate diagnostic messages if the method runs a different
+ number of tests.
+
+ Support methods
+ builder
+ $Tests->builder
+
+ Returns the underlying Test::Builder object that Test::Class uses.
+ For example:
+
+ sub test_close : Test {
+ my $self = shift;
+ my ($o, $dbh) = ($self->{object}, $self->{dbh});
+ $self->builder->ok($o->close($dbh), "closed ok");
+ };
+
+ current_method
+ $method_name = $Tests->current_method
+ $method_name = CLASS->current_method
+
+ Returns the name of the test method currently being executed by
+ runtests(), or "undef" if runtests() has not been called.
+
+ The method name is also available in the setup and teardown methods
+ that run before and after the test method. This can be useful in
+ producing diagnostic messages, for example:
+
+ sub test_invarient : Test(teardown => 1) {
+ my $self = shift;
+ my $m = $self->current_method;
+ ok($self->invarient_ok, "class okay after $m");
+ };
+
+ BAILOUT
+ $Tests->BAILOUT($reason)
+ CLASS->BAILOUT($reason)
+
+ Things are going so badly all testing should terminate, including
+ running any additional test scripts invoked by Test::Harness. This
+ is exactly the same as doing:
+
+ $self->builder->BAILOUT
+
+ See "BAILOUT" in Test::Builder for details. Any teardown and
+ shutdown methods are *not* run.
+
+ FAIL_ALL
+ $Tests->FAIL_ALL($reason)
+ CLASS->FAIL_ALL($reason)
+
+ Things are going so badly all the remaining tests in the current
+ script should fail. Exits immediately with the number of tests
+ failed, or 254 if more than 254 tests were run. Any teardown methods
+ are *not* run.
+
+ This does not affect the running of any other test scripts invoked
+ by Test::Harness.
+
+ For example, if all your tests rely on the ability to create objects
+ then you might want something like this as an early test:
+
+ sub _test_new : Test(3) {
+ my $self = shift;
+ isa_ok(Object->new, "Object")
+ || $self->FAIL_ALL('cannot create Objects');
+ ...
+ };
+
+ SKIP_ALL
+ $Tests->SKIP_ALL($reason)
+ CLASS->SKIP_ALL($reason)
+
+ Things are going so badly all the remaining tests in the current
+ script should be skipped. Exits immediately with 0 - teardown
+ methods are *not* run.
+
+ This does not affect the running of any other test scripts invoked
+ by Test::Harness.
+
+ For example, if you had a test script that only applied to the
+ darwin OS you could write:
+
+ sub _darwin_only : Test(setup) {
+ my $self = shift;
+ $self->SKIP_ALL("darwin only") unless $^O eq "darwin";
+ };
+
+ add_testinfo
+ CLASS->add_test($name, $type, $num_tests)
+
+ Chiefly for use by libraries like Test::Class::Sugar, which can't
+ use the ":Test(...)" interfaces make test methods. "add_testinfo"
+ informs the class about a test method that has been defined without
+ a "Test", "Tests" or other attribute.
+
+ $name is the name of the method, $type must be one of "startup",
+ "setup", "test", "teardown" or "shutdown", and $num_tests has the
+ same meaning as "N" in the description of the Test attribute.
+
+HELP FOR CONFUSED JUNIT USERS
+ This section is for people who have used JUnit (or similar) and are
+ confused because they don't see the TestCase/Suite/Runner class
+ framework they were expecting. Here we take each of the major classes in
+ JUnit and compare them with their equivalent Perl testing modules.
+
+ Class Assert
+ The test assertions provided by Assert correspond to the test
+ functions provided by the Test::Builder based modules (Test::More,
+ Test::Exception, Test::Differences, etc.)
+
+ Unlike JUnit the test functions supplied by Test::More et al do
+ *not* throw exceptions on failure. They just report the failure to
+ STDOUT where it is collected by Test::Harness. This means that where
+ you have
+
+ sub foo : Test(2) {
+ ok($foo->method1);
+ ok($foo->method2);
+ };
+
+ The second test *will* run if the first one fails. You can emulate
+ the JUnit way of doing it by throwing an explicit exception on test
+ failure:
+
+ sub foo : Test(2) {
+ ok($foo->method1) or die "method1 failed";
+ ok($foo->method2);
+ };
+
+ The exception will be caught by Test::Class and the other test
+ automatically failed.
+
+ Class TestCase
+ Test::Class corresponds to TestCase in JUnit.
+
+ In Test::Class setup, test and teardown methods are marked
+ explicitly using the Test attribute. Since we need to know the total
+ number of tests to provide a test plan for Test::Harness we also
+ state how many tests each method runs.
+
+ Unlike JUnit you can have multiple setup/teardown methods in a
+ class.
+
+ Class TestSuite
+ Test::Class also does the work that would be done by TestSuite in
+ JUnit.
+
+ Since the methods are marked with attributes Test::Class knows what
+ is and isn't a test method. This allows it to run all the test
+ methods without having the developer create a suite manually, or use
+ reflection to dynamically determine the test methods by name. See
+ the runtests() method for more details.
+
+ The running order of the test methods is fixed in Test::Class.
+ Methods are executed in alphabetical order.
+
+ Unlike JUnit, Test::Class currently does not allow you to run
+ individual test methods.
+
+ Class TestRunner
+ Test::Harness does the work of the TestRunner in JUnit. It collects
+ the test results (sent to STDOUT) and collates the results.
+
+ Unlike JUnit there is no distinction made by Test::Harness between
+ errors and failures. However, it does support skipped and todo test
+ - which JUnit does not.
+
+ If you want to write your own test runners you should look at
+ Test::Harness::Straps.
+
+OTHER MODULES FOR XUNIT TESTING IN PERL
+ In addition to Test::Class there are two other distributions for xUnit
+ testing in perl. Both have a longer history than Test::Class and might
+ be more suitable for your needs.
+
+ I am biased since I wrote Test::Class - so please read the following
+ with appropriate levels of scepticism. If you think I have
+ misrepresented the modules please let me know.
+
+ Test::SimpleUnit
+ A very simple unit testing framework. If you are looking for a
+ lightweight single module solution this might be for you.
+
+ The advantage of Test::SimpleUnit is that it is simple! Just one
+ module with a smallish API to learn.
+
+ Of course this is also the disadvantage.
+
+ It's not class based so you cannot create testing classes to reuse
+ and extend.
+
+ It doesn't use Test::Builder so it's difficult to extend or
+ integrate with other testing modules. If you are already familiar
+ with Test::Builder, Test::More and friends you will have to learn a
+ new test assertion API. It does not support todo tests.
+
+ Test::Unit
+ Test::Unit is a port of JUnit <http://www.junit.org/> into perl. If
+ you have used JUnit then the Test::Unit framework should be very
+ familiar.
+
+ It is class based so you can easily reuse your test classes and
+ extend by subclassing. You get a nice flexible framework you can
+ tweak to your heart's content. If you can run Tk you also get a
+ graphical test runner.
+
+ However, Test::Unit is not based on Test::Builder. You cannot easily
+ move Test::Builder based test functions into Test::Unit based
+ classes. You have to learn another test assertion API.
+
+ Test::Unit implements it's own testing framework separate from
+ Test::Harness. You can retrofit *.t scripts as unit tests, and
+ output test results in the format that Test::Harness expects, but
+ things like todo tests and skipping tests are not supported.
+
+BUGS
+ None known at the time of writing.
+
+ If you find any bugs please let me know by e-mail at
+ <adrianh@quietstars.com>, or report the problem with
+ <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-Class>.
+
+COMMUNITY
+ perl-qa
+ If you are interested in testing using Perl I recommend you visit
+ <http://qa.perl.org/> and join the excellent perl-qa mailing list. See
+ <http://lists.perl.org/showlist.cgi?name=perl-qa> for details on how to
+ subscribe.
+
+ perlmonks
+ You can find users of Test::Class, including the module author, on
+ <http://www.perlmonks.org/>. Feel free to ask questions on Test::Class
+ there.
+
+ CPAN::Forum
+ The CPAN Forum is a web forum for discussing Perl's CPAN modules. The
+ Test::Class forum can be found at
+ <http://www.cpanforum.com/dist/Test-Class>.
+
+TO DO
+ If you think this module should do something that it doesn't (or does
+ something that it shouldn't) please let me know.
+
+ You can see my current to do list at
+ <http://adrianh.tadalist.com/lists/public/4798>, with an RSS feed of
+ changes at <http://adrianh.tadalist.com/lists/feed_public/4798>.
+
+ACKNOWLEDGMENTS
+ This is yet another implementation of the ideas from Kent Beck's Testing
+ Framework paper <http://www.xprogramming.com/testfram.htm>.
+
+ Thanks to Adam Kennedy, agianni, Apocalypse, Ask Bjorn Hansen, Chris
+ Dolan, Chris Williams, Corion, Cosimo Streppone, Daniel Berger, Dave
+ O'Neill, David Cantrell, David Wheeler, Emil Jansson, Gunnar Wolf, Hai
+ Pham, Hynek, imacat, Jeff Deifik, Jim Brandt, Jochen Stenzel, Johan
+ Lindstrom, John West, Jonathan R. Warden, Joshua ben Jore, Jost Krieger,
+ Kenichi Ishigaki Lee Goddard, Mark Reynolds, Mark Stosberg, Martin
+ Ferrari, Mathieu Sauve-Frankel, Matt Trout, Matt Williamson, Michael G
+ Schwern, Murat Uenalan, Nicholas Clark, Ovid, Piers Cawley, Rob Kinyon,
+ Scott Lanning, Sebastien Aperghis-Tramoni, Steve Kirkup, Stray Toaster,
+ Ted Carnahan, Terrence Brannon, Tom Metro, Tony Bowden, Tony Edwardson,
+ William McKee, various anonymous folk and all the fine people on perl-qa
+ for their feedback, patches, suggestions and nagging.
+
+ This module wouldn't be possible without the excellent Test::Builder.
+ Thanks to chromatic and Michael G Schwern for creating such a useful
+ module.
+
+AUTHORS
+ Adrian Howard <adrianh@quietstars.com>, Curtis "Ovid" Poe, <ovid at
+ cpan.org>, Mark Morgan <makk384@gmail.com>.
+
+ If you use this module, and can spare the time please let us know or
+ rate it at <http://cpanratings.perl.org/rate/?distribution=Test-Class>.
+
+SEE ALSO
+ Test::Class::Load
+ Simple way to load "Test::Class" classes automatically.
+
+ <http://del.icio.us/tag/Test::Class>
+ Delicious links on Test::Class.
+
+ Perl Testing: A Developer's Notebook by Ian Langworth and chromatic
+ Chapter 8 covers using Test::Class.
+
+ Advanced Perl Programming, second edition by Simon Cozens
+ Chapter 8 has a few pages on using Test::Class.
+
+ The Perl Journal, April 2003
+ Includes the article "Test-Driven Development in Perl" by Piers
+ Cawley that uses Test::Class.
+
+ Test::Builder
+ Support module for building test libraries.
+
+ Test::Simple & Test::More
+ Basic utilities for writing tests.
+
+ <http://qa.perl.org/test-modules.html>
+ Overview of some of the many testing modules available on CPAN.
+
+ <http://del.icio.us/tag/perl+testing>
+ Delicious links on perl testing.
+
+ Test::Object
+ Another approach to object oriented testing.
+
+ Test::Group and Test::Block
+ Alternatives to grouping sets of tests together.
+
+ The following modules use Test::Class as part of their test suite. You
+ might want to look at them for usage examples:
+
+ Aspect, Bricolage (<http://www.bricolage.cc/>),
+ Class::StorageFactory, CGI::Application::Search, DBIx::Romani,
+ Xmldoom, Object::Relational, File::Random,
+ Geography::JapanesePrefectures, Google::Adwords, Merge::HashRef,
+ PerlBuildSystem, Pixie, Yahoo::Marketing, and XUL-Node
+
+ The following modules are not based on Test::Builder, but may be of
+ interest as alternatives to Test::Class.
+
+ Test::Unit
+ Perl unit testing framework closely modeled on JUnit.
+
+ Test::SimpleUnit
+ A very simple unit testing framework.
+
+LICENCE
+ Copyright 2002-2010 Adrian Howard, All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the same terms as Perl itself.
+
Please sign in to comment.
Something went wrong with that request. Please try again.