Perl Testing (zz)

zz from  http://www.cntesting.com/hphtml/?thread-5511.html
http://www.ddj.com/dept/architect/188500906

Perl Testing
 
作者: Fastpoint   查看次数: 813   发表时间: 2006/6/19 16:42  【论坛浏览】
 
 
Peter Scott

Testing is the cornerstone of robust software development, and Perl supports a flexible and powerful testing capability
Peter Scott is an enterprise system engineering consultant and Perl author and trainer. He can be contacted at http://www.psdt.com/.







A crash is when your competitor's program dies. When your program dies, it is an "idiosyncrasy". Frequently, crashes are followed with a message like "ID 02". "ID" is an abbreviation for idiosyncrasy and the number that follows indicates how many more months of testing the product should have had.

 



-- Guy Kawasaki


Testing is the cornerstone of robust software development, and Perl supports a flexible and powerful testing capability. In this article, I examine the testing mechanisms available to Perl programmers, focusing on the Extreme Programming (XP) Test First principle. Test First turns the traditional waterfall methodology on its head by saying that test writing precedes not only coding but even design, and that tests come straight out of requirements. In fact, the tests are a formal expression of the requirements.


This approach makes enormous sense. A requirement is not a real requirement unless it is testable. "The product shall be user friendly" is not testable, while "the system shall process 100 record updates within 500ms" is. So why interpose a huge hiatus of design and implementation between writing the requirements and finding out whether they're testable? Moreover, a full-fledged regression and unit test suite provides the safety net that lets you perform feats of derring-do on the high wire of development, safe in the knowledge that at every step you can instantly check whether the code passes the tests no matter what massive changes you may have just wrought upon it.


Clearly, the developers of Perl have embraced the XP testing philosophy. Between 1997 and 2004, the number of tests for the core Perl distribution itself mushroomed from 5000 to 70,000.


Simple to Get Started



Being lazy means never having to say you've got carpal tunnel syndrome. The test module designers applied the principle of Huffman coding to the API; that is, the most common functions you call should have the shortest names to optimize typing and reading. The most common test function is simply called ok(), which is vastly more appealing than, say, TestSocketListenerConnectionFailure(). If you're impatient (another fundamental Perl virtue), you can write a test just by creating a program containing. For instance:

 


use Test::Simple tests => 1;
ok(sqrt(16) == 4, "sqrt(16) works");




As this shows, the ok() function is exported by the Test::Simple module that comes with Perl (since Perl 5.8.0, and before that in CPAN) and so is close to hand.


All that the ok() function does is test its first argument and print out "ok" or "not ok", depending on whether it is true. You're probably thinking, "I hardly need anyone to write a module to do that." But from such little test acorns do mighty regression suite oaks sprout. The ok() function also outputs the test label in the second argument and a running count of tests it has run. This is where the tests argument to Test::Simple comes in--it specifies how many tests we intend to run, so that Test::Simple can warn you if it sees a different number of calls to ok(). The output of a typical test program run looks like Listing One.

 

1..12
ok 1 - regex search
ok 2 - regex search
ok 3 - regex search
ok 4 - regex store lives
ok 5 - regex store
ok 6 - Store non-matching regex croaks
ok 7 - Keys on complex store
ok 8 - Hash on complex store
ok 9 - lol regex store lives
ok 10 - lol regex store
ok 11 - Chained assignment
ok 12 - Multiple match croaks




Listing One

The first line shows the range of tests expected to be run; the significance of this will be seen later. Any error output from the program is passed through.


All this serves to show that the testing of Perl programs fits the same philosophy as programming Perl: Simple tasks should be simple to achieve. In practice, most testing uses the Test::More module, which exports a number of more useful functions, including:




is($expr, $value, $tag) same as ok($expr eq $value, $tag).
like($expr, $regex, $tag, same as ok($expr =~ $regex, $tag).
is_deeply($struct1, $struct2, $tag), compares arbitrarily deep structures. isa_ok($object, $class), verifies that an object is a member of a given class.
use_ok($module, @imports), test that a module can be loaded

 



Note again the Huffman principle on names of commonly used functions. Even though several of the functions are syntactic sugar for variations on ok() (and all of them end up calling ok() anyway), any improvement in readability justifies a new function so that testing can be made as painless as possible. (There's even an isnt() function to avoid having to put a negation operator in an is() call, and, in true Perl tradition, there's an isn't() alias.)


Test::More lets you designate blocks of tests as conditional in two different ways. By naming a block SKIP, you can then call the skip() function inside the block if you want to skip the tests in it:

 


SKIP: {
eval { require Acme::Garden;
Acme::Garden->export;
};
$@ and skip "Don't have Acme::Garden installed", 2;
is(pull_weed(), "kudzu", "It's taking over!");
is(seed_depth("gladiolus"), 7, "Flower module ok");
}




The other way of marking tests as conditional is to put them in a block named "TODO". Failing tests in such a block will be specially annotated so as not to perturb aggregate statistics reported by Test::Harness.


The Perl test mechanism is not coupled to source code (Perl 5 does not lend itself easily to reflective tools; this will be remedied in Perl 6.) On the other hand, its simplicity allows it to be used to write unit tests, integration tests, regression tests, or acceptance tests.


Test::Simple is itself built on a module, Test::Builder, which is designed for reuse by modules providing testing functionality. The introduction of Test::Builder spurred an explosion in the creation of testing modules; there are currently over 250 such modules on CPAN in nearly 100 distributions. One of the more useful ones is Test::Exception, which verifies that code dies or fails to die when it should. You can also find Test::Pod, which vets the syntax of inline documentation written in POD ("Plain Old Documentation").


Use In Practice



Many tools have been created and integrated with the Perl core to make testing easy. A basic test skeleton can be created with the all-purpose h2xs program that has come with all versions of Perl 5. (If you want to be on the leading edge, the CPAN module ExtUtils::ModuleMaker is better.) h2xs is best used when you're developing a module, because it creates the skeleton for that at the same time. The command:

 


h2xs -Xan Store::Inventory



creates a tree under a subdirectory Store-Inventory (or Store/Inventory prior to Perl 5.8.1) with a stub for the Store::Inventory module, and a subdirectory t with an initial test file. (Old versions of Perl created a test.pl test file instead.) In fact, as soon as you create a makefile from the skeleton instructions that h2xs made, via:

 


perl Makefile.PL




you can immediately type make test and see that first test run. You now have a test that passes (it verifies that the module skeleton loads) and you haven't even written any code yet.


The output of make test looks different from that of a standalone test file, however. That's because make test aggregates test files using another key core module, Test::Harness. Reading the output of all the ok() calls to tabulate their successes would be tedious. Test::Harness exports a function, runtests(), used by make test to run all the test files in the t directory. runtests() intercepts their output and tallies the ok/not ok results, presenting a running count and a statistical summary. The output of runtests() looks familiar to anyone who has built Perl from source, because the make test stage of building Perl uses the same testing mechanism. This is where the first line of output from an individual test ("1..N") comes in. This tells runtests() how many tests it should expect to see output for.


You can now develop your module following the Test First principle. First you write a unit test, then you write a method to satisfy the requirement of the test. With a little work the end-to-end tests can be the actual requirements document for the application. Listings Two and Three are a sample test file and module file, respectively.

 

use Test::More tests => 11;
use Test::Exception;


BEGIN { use_ok('Store::Inventory') };


my $stock = Store::Inventory->new;


isa_ok($stock, 'Store::Inventory');


my $total;
while ()
{
my ($name, $price, $count) = split;
my $item = Store::Item->new(name => $name, price => $price, count => $count);
isa_ok($item, 'Store::Item');
lives_ok { $stock->add_item($item) } 'Added item';
is($stock->total_assets, $total += $count * $price);
}
lives_ok { $stock->sell('cornflakes') };
is($stock->total_assets, $total -= 2.99);
throws_ok { $stock->sell('hedgehogs') }
qr/No hedgehogs in stock/, "Can't sell what we don't have";
__END__
cornflakes 2.99 250
bananas 0.39 400



Listing Two







 

package Store::Inventory;
use strict;
use warnings;


use Class::Struct;
use List::Util 'sum';


struct(items => '%');


sub add_item {
my ($self, $item) = @_;
$self->items->{$item->name} = $item;
}
sub total_assets {
my $self = shift;
return sum(map

zz from  http://www.cntesting.com/hphtml/?thread-5511.html
http://www.ddj.com/dept/architect/188500906

Perl Testing
 
作者: Fastpoint   查看次数: 813   发表时间: 2006/6/19 16:42  【论坛浏览】
 
 
Peter Scott

Testing is the cornerstone of robust software development, and Perl supports a flexible and powerful testing capability
Peter Scott is an enterprise system engineering consultant and Perl author and trainer. He can be contacted at http://www.psdt.com/.







A crash is when your competitor's program dies. When your program dies, it is an "idiosyncrasy". Frequently, crashes are followed with a message like "ID 02". "ID" is an abbreviation for idiosyncrasy and the number that follows indicates how many more months of testing the product should have had.

 



-- Guy Kawasaki


Testing is the cornerstone of robust software development, and Perl supports a flexible and powerful testing capability. In this article, I examine the testing mechanisms available to Perl programmers, focusing on the Extreme Programming (XP) Test First principle. Test First turns the traditional waterfall methodology on its head by saying that test writing precedes not only coding but even design, and that tests come straight out of requirements. In fact, the tests are a formal expression of the requirements.


This approach makes enormous sense. A requirement is not a real requirement unless it is testable. "The product shall be user friendly" is not testable, while "the system shall process 100 record updates within 500ms" is. So why interpose a huge hiatus of design and implementation between writing the requirements and finding out whether they're testable? Moreover, a full-fledged regression and unit test suite provides the safety net that lets you perform feats of derring-do on the high wire of development, safe in the knowledge that at every step you can instantly check whether the code passes the tests no matter what massive changes you may have just wrought upon it.


Clearly, the developers of Perl have embraced the XP testing philosophy. Between 1997 and 2004, the number of tests for the core Perl distribution itself mushroomed from 5000 to 70,000.


Simple to Get Started



Being lazy means never having to say you've got carpal tunnel syndrome. The test module designers applied the principle of Huffman coding to the API; that is, the most common functions you call should have the shortest names to optimize typing and reading. The most common test function is simply called ok(), which is vastly more appealing than, say, TestSocketListenerConnectionFailure(). If you're impatient (another fundamental Perl virtue), you can write a test just by creating a program containing. For instance:

 


use Test::Simple tests => 1;
ok(sqrt(16) == 4, "sqrt(16) works");




As this shows, the ok() function is exported by the Test::Simple module that comes with Perl (since Perl 5.8.0, and before that in CPAN) and so is close to hand.


All that the ok() function does is test its first argument and print out "ok" or "not ok", depending on whether it is true. You're probably thinking, "I hardly need anyone to write a module to do that." But from such little test acorns do mighty regression suite oaks sprout. The ok() function also outputs the test label in the second argument and a running count of tests it has run. This is where the tests argument to Test::Simple comes in--it specifies how many tests we intend to run, so that Test::Simple can warn you if it sees a different number of calls to ok(). The output of a typical test program run looks like Listing One.

 

1..12
ok 1 - regex search
ok 2 - regex search
ok 3 - regex search
ok 4 - regex store lives
ok 5 - regex store
ok 6 - Store non-matching regex croaks
ok 7 - Keys on complex store
ok 8 - Hash on complex store
ok 9 - lol regex store lives
ok 10 - lol regex store
ok 11 - Chained assignment
ok 12 - Multiple match croaks




Listing One

The first line shows the range of tests expected to be run; the significance of this will be seen later. Any error output from the program is passed through.


All this serves to show that the testing of Perl programs fits the same philosophy as programming Perl: Simple tasks should be simple to achieve. In practice, most testing uses the Test::More module, which exports a number of more useful functions, including:




is($expr, $value, $tag) same as ok($expr eq $value, $tag).
like($expr, $regex, $tag, same as ok($expr =~ $regex, $tag).
is_deeply($struct1, $struct2, $tag), compares arbitrarily deep structures. isa_ok($object, $class), verifies that an object is a member of a given class.
use_ok($module, @imports), test that a module can be loaded

 



Note again the Huffman principle on names of commonly used functions. Even though several of the functions are syntactic sugar for variations on ok() (and all of them end up calling ok() anyway), any improvement in readability justifies a new function so that testing can be made as painless as possible. (There's even an isnt() function to avoid having to put a negation operator in an is() call, and, in true Perl tradition, there's an isn't() alias.)


Test::More lets you designate blocks of tests as conditional in two different ways. By naming a block SKIP, you can then call the skip() function inside the block if you want to skip the tests in it:

 


SKIP: {
eval { require Acme::Garden;
Acme::Garden->export;
};
$@ and skip "Don't have Acme::Garden installed", 2;
is(pull_weed(), "kudzu", "It's taking over!");
is(seed_depth("gladiolus"), 7, "Flower module ok");
}




The other way of marking tests as conditional is to put them in a block named "TODO". Failing tests in such a block will be specially annotated so as not to perturb aggregate statistics reported by Test::Harness.


The Perl test mechanism is not coupled to source code (Perl 5 does not lend itself easily to reflective tools; this will be remedied in Perl 6.) On the other hand, its simplicity allows it to be used to write unit tests, integration tests, regression tests, or acceptance tests.


Test::Simple is itself built on a module, Test::Builder, which is designed for reuse by modules providing testing functionality. The introduction of Test::Builder spurred an explosion in the creation of testing modules; there are currently over 250 such modules on CPAN in nearly 100 distributions. One of the more useful ones is Test::Exception, which verifies that code dies or fails to die when it should. You can also find Test::Pod, which vets the syntax of inline documentation written in POD ("Plain Old Documentation").


Use In Practice



Many tools have been created and integrated with the Perl core to make testing easy. A basic test skeleton can be created with the all-purpose h2xs program that has come with all versions of Perl 5. (If you want to be on the leading edge, the CPAN module ExtUtils::ModuleMaker is better.) h2xs is best used when you're developing a module, because it creates the skeleton for that at the same time. The command:

 


h2xs -Xan Store::Inventory



creates a tree under a subdirectory Store-Inventory (or Store/Inventory prior to Perl 5.8.1) with a stub for the Store::Inventory module, and a subdirectory t with an initial test file. (Old versions of Perl created a test.pl test file instead.) In fact, as soon as you create a makefile from the skeleton instructions that h2xs made, via:

 


perl Makefile.PL




you can immediately type make test and see that first test run. You now have a test that passes (it verifies that the module skeleton loads) and you haven't even written any code yet.


The output of make test looks different from that of a standalone test file, however. That's because make test aggregates test files using another key core module, Test::Harness. Reading the output of all the ok() calls to tabulate their successes would be tedious. Test::Harness exports a function, runtests(), used by make test to run all the test files in the t directory. runtests() intercepts their output and tallies the ok/not ok results, presenting a running count and a statistical summary. The output of runtests() looks familiar to anyone who has built Perl from source, because the make test stage of building Perl uses the same testing mechanism. This is where the first line of output from an individual test ("1..N") comes in. This tells runtests() how many tests it should expect to see output for.


You can now develop your module following the Test First principle. First you write a unit test, then you write a method to satisfy the requirement of the test. With a little work the end-to-end tests can be the actual requirements document for the application. Listings Two and Three are a sample test file and module file, respectively.

 

use Test::More tests => 11;
use Test::Exception;


BEGIN { use_ok('Store::Inventory') };


my $stock = Store::Inventory->new;


isa_ok($stock, 'Store::Inventory');


my $total;
while ()
{
my ($name, $price, $count) = split;
my $item = Store::Item->new(name => $name, price => $price, count => $count);
isa_ok($item, 'Store::Item');
lives_ok { $stock->add_item($item) } 'Added item';
is($stock->total_assets, $total += $count * $price);
}
lives_ok { $stock->sell('cornflakes') };
is($stock->total_assets, $total -= 2.99);
throws_ok { $stock->sell('hedgehogs') }
qr/No hedgehogs in stock/, "Can't sell what we don't have";
__END__
cornflakes 2.99 250
bananas 0.39 400



Listing Two







 

___FCKpd___6

Listing Three


Segregating tests into multiple files within the t directory can be used either to make the sizes of each file more manageable, or as a guide to partitioning the tests. You could define setup and teardown procedures in each file if you wanted to make each one effectively a single independent unit test; it's up to you. In true Perl fashion, you have enough rope either to hang yourself or to make a lasso.






For Further Exploration



Once you've mastered the basics of Perl testing, you may be interested in more advanced capabilities. For rigorous unit testing of legacy object-oriented applications, Test::MockObject provides a complete, if lengthy, solution. Test::MockObject lets you create objects that mock the behavior of the ones actually used in your application so they present apparently the same interface to the calling tests but under your complete control and without the side effects. (Testing a database is such a common need for mocking that the module DBD::Mock was created to help with it.) This is so-called "white box" testing: instead of looking only at the interfaces a method presents to the outside world, you craft unit tests for it by inspecting its code to see where it calls functions or methods that may alter state. Then you mock those functions to track whether they are being called the way you expect at that point.


If you like to integrate code and its documentation, you might like to do the same with its tests, in which case the CPAN module Test::Inline lets you embed tests within code in an extension of the POD language. Just encapsulate them in POD-like blocks marked "=begin testing" ... "=end testing" and then extract the tests into a test file with the program pod2test that comes with Test::Inline. (This step can be automated in your module's Makefile.PL during the make test phase.)


Test::Unit



If you're coming from a Java/JUnit background and want a familiar testing environment in Perl, the CPAN module Test::Unit is for you. You define set_up() and tear_down() procedures to prepare for and clean up after each test case so there can be no side effects between tests. Test::Unit even provides the green/red bar, courtesy of PerlTk.

Coverage Testing



The value of tests is proportional to the proportion of possible equivalence classes that are exercised. Generating the valid equivalence classes is still a manual task, but you can at least verify that all the statements in your code have been exercised during testing. Once again, this has been automated. Modules for measuring code coverage have existed for some time: Devel::DProf and Devel::SmallProf profile code and the parts that haven't been called can be inferred. Devel::Coverage shows them explicitly. But that's still too much work for the lazy. Therefore the modern module Devel::Cover has been extended to include coverage for tests. Now, simply by defining an environment variable, you can trigger analysis during make test and generate a coverage database that can be analyzed with the cover program that comes with Devel::Cover. That program outputs HTML that provides a tabular representation of the lines of code that did not get exercised. There's even another module, Test::Pod::Coverage, that verifies that all the files in your distribution provide documentation.

Legacy Application Testing



Perl programmers are often faced with having to deal with legacy applications which lack unit tests or, for that matter, coherent units. Perl's testing framework at this point becomes useful for creating end-to-end regression tests to provide a safety net while the application is modified. This can even be extended to testing web interfaces via the CPAN module Test::WWW::Mechanize. If you find the work of programming the necessary inputs to navigate a web interface too tedious, the module HTTP::Recorder will do it for you.


Automated tests can be useful for other purposes than just application testing. With the web-based testing tools just mentioned, you could write something like Listing Four to verify that your bank account is doing alright. (If you want to put it in a cron job, knowing that the exit code of a test run is the number of tests that failed may be useful.)

 

use strict;
use warnings;


use Test::WWW::Mechanize tests => 7;


my $mech = Test::WWW::Mechanize->new;


$mech->get_ok("http://www.mybank.example.com/", "My bank is still there");
$mech->content_contains("Login", "and it still has a login page");


my ($username, $password) = @ARGV;
$mech->set_visible($username, $password);


ok($mech->submit->is_success, "Login form submitted okay");

  ->count *

zz from  http://www.cntesting.com/hphtml/?thread-5511.html
http://www.ddj.com/dept/architect/188500906

Perl Testing
 
作者: Fastpoint   查看次数: 813   发表时间: 2006/6/19 16:42  【论坛浏览】
 
 
Peter Scott

Testing is the cornerstone of robust software development, and Perl supports a flexible and powerful testing capability
Peter Scott is an enterprise system engineering consultant and Perl author and trainer. He can be contacted at http://www.psdt.com/.







A crash is when your competitor's program dies. When your program dies, it is an "idiosyncrasy". Frequently, crashes are followed with a message like "ID 02". "ID" is an abbreviation for idiosyncrasy and the number that follows indicates how many more months of testing the product should have had.

 



-- Guy Kawasaki


Testing is the cornerstone of robust software development, and Perl supports a flexible and powerful testing capability. In this article, I examine the testing mechanisms available to Perl programmers, focusing on the Extreme Programming (XP) Test First principle. Test First turns the traditional waterfall methodology on its head by saying that test writing precedes not only coding but even design, and that tests come straight out of requirements. In fact, the tests are a formal expression of the requirements.


This approach makes enormous sense. A requirement is not a real requirement unless it is testable. "The product shall be user friendly" is not testable, while "the system shall process 100 record updates within 500ms" is. So why interpose a huge hiatus of design and implementation between writing the requirements and finding out whether they're testable? Moreover, a full-fledged regression and unit test suite provides the safety net that lets you perform feats of derring-do on the high wire of development, safe in the knowledge that at every step you can instantly check whether the code passes the tests no matter what massive changes you may have just wrought upon it.


Clearly, the developers of Perl have embraced the XP testing philosophy. Between 1997 and 2004, the number of tests for the core Perl distribution itself mushroomed from 5000 to 70,000.


Simple to Get Started



Being lazy means never having to say you've got carpal tunnel syndrome. The test module designers applied the principle of Huffman coding to the API; that is, the most common functions you call should have the shortest names to optimize typing and reading. The most common test function is simply called ok(), which is vastly more appealing than, say, TestSocketListenerConnectionFailure(). If you're impatient (another fundamental Perl virtue), you can write a test just by creating a program containing. For instance:

 


use Test::Simple tests => 1;
ok(sqrt(16) == 4, "sqrt(16) works");




As this shows, the ok() function is exported by the Test::Simple module that comes with Perl (since Perl 5.8.0, and before that in CPAN) and so is close to hand.


All that the ok() function does is test its first argument and print out "ok" or "not ok", depending on whether it is true. You're probably thinking, "I hardly need anyone to write a module to do that." But from such little test acorns do mighty regression suite oaks sprout. The ok() function also outputs the test label in the second argument and a running count of tests it has run. This is where the tests argument to Test::Simple comes in--it specifies how many tests we intend to run, so that Test::Simple can warn you if it sees a different number of calls to ok(). The output of a typical test program run looks like Listing One.

 

1..12
ok 1 - regex search
ok 2 - regex search
ok 3 - regex search
ok 4 - regex store lives
ok 5 - regex store
ok 6 - Store non-matching regex croaks
ok 7 - Keys on complex store
ok 8 - Hash on complex store
ok 9 - lol regex store lives
ok 10 - lol regex store
ok 11 - Chained assignment
ok 12 - Multiple match croaks




Listing One

The first line shows the range of tests expected to be run; the significance of this will be seen later. Any error output from the program is passed through.


All this serves to show that the testing of Perl programs fits the same philosophy as programming Perl: Simple tasks should be simple to achieve. In practice, most testing uses the Test::More module, which exports a number of more useful functions, including:




is($expr, $value, $tag) same as ok($expr eq $value, $tag).
like($expr, $regex, $tag, same as ok($expr =~ $regex, $tag).
is_deeply($struct1, $struct2, $tag), compares arbitrarily deep structures. isa_ok($object, $class), verifies that an object is a member of a given class.
use_ok($module, @imports), test that a module can be loaded

 



Note again the Huffman principle on names of commonly used functions. Even though several of the functions are syntactic sugar for variations on ok() (and all of them end up calling ok() anyway), any improvement in readability justifies a new function so that testing can be made as painless as possible. (There's even an isnt() function to avoid having to put a negation operator in an is() call, and, in true Perl tradition, there's an isn't() alias.)


Test::More lets you designate blocks of tests as conditional in two different ways. By naming a block SKIP, you can then call the skip() function inside the block if you want to skip the tests in it:

 


SKIP: {
eval { require Acme::Garden;
Acme::Garden->export;
};
$@ and skip "Don't have Acme::Garden installed", 2;
is(pull_weed(), "kudzu", "It's taking over!");
is(seed_depth("gladiolus"), 7, "Flower module ok");
}




The other way of marking tests as conditional is to put them in a block named "TODO". Failing tests in such a block will be specially annotated so as not to perturb aggregate statistics reported by Test::Harness.


The Perl test mechanism is not coupled to source code (Perl 5 does not lend itself easily to reflective tools; this will be remedied in Perl 6.) On the other hand, its simplicity allows it to be used to write unit tests, integration tests, regression tests, or acceptance tests.


Test::Simple is itself built on a module, Test::Builder, which is designed for reuse by modules providing testing functionality. The introduction of Test::Builder spurred an explosion in the creation of testing modules; there are currently over 250 such modules on CPAN in nearly 100 distributions. One of the more useful ones is Test::Exception, which verifies that code dies or fails to die when it should. You can also find Test::Pod, which vets the syntax of inline documentation written in POD ("Plain Old Documentation").


Use In Practice



Many tools have been created and integrated with the Perl core to make testing easy. A basic test skeleton can be created with the all-purpose h2xs program that has come with all versions of Perl 5. (If you want to be on the leading edge, the CPAN module ExtUtils::ModuleMaker is better.) h2xs is best used when you're developing a module, because it creates the skeleton for that at the same time. The command:

 


h2xs -Xan Store::Inventory



creates a tree under a subdirectory Store-Inventory (or Store/Inventory prior to Perl 5.8.1) with a stub for the Store::Inventory module, and a subdirectory t with an initial test file. (Old versions of Perl created a test.pl test file instead.) In fact, as soon as you create a makefile from the skeleton instructions that h2xs made, via:

 


perl Makefile.PL




you can immediately type make test and see that first test run. You now have a test that passes (it verifies that the module skeleton loads) and you haven't even written any code yet.


The output of make test looks different from that of a standalone test file, however. That's because make test aggregates test files using another key core module, Test::Harness. Reading the output of all the ok() calls to tabulate their successes would be tedious. Test::Harness exports a function, runtests(), used by make test to run all the test files in the t directory. runtests() intercepts their output and tallies the ok/not ok results, presenting a running count and a statistical summary. The output of runtests() looks familiar to anyone who has built Perl from source, because the make test stage of building Perl uses the same testing mechanism. This is where the first line of output from an individual test ("1..N") comes in. This tells runtests() how many tests it should expect to see output for.


You can now develop your module following the Test First principle. First you write a unit test, then you write a method to satisfy the requirement of the test. With a little work the end-to-end tests can be the actual requirements document for the application. Listings Two and Three are a sample test file and module file, respectively.

 

use Test::More tests => 11;
use Test::Exception;


BEGIN { use_ok('Store::Inventory') };


my $stock = Store::Inventory->new;


isa_ok($stock, 'Store::Inventory');


my $total;
while ()
{
my ($name, $price, $count) = split;
my $item = Store::Item->new(name => $name, price => $price, count => $count);
isa_ok($item, 'Store::Item');
lives_ok { $stock->add_item($item) } 'Added item';
is($stock->total_assets, $total += $count * $price);
}
lives_ok { $stock->sell('cornflakes') };
is($stock->total_assets, $total -= 2.99);
throws_ok { $stock->sell('hedgehogs') }
qr/No hedgehogs in stock/, "Can't sell what we don't have";
__END__
cornflakes 2.99 250
bananas 0.39 400



Listing Two







 

___FCKpd___6

Listing Three


Segregating tests into multiple files within the t directory can be used either to make the sizes of each file more manageable, or as a guide to partitioning the tests. You could define setup and teardown procedures in each file if you wanted to make each one effectively a single independent unit test; it's up to you. In true Perl fashion, you have enough rope either to hang yourself or to make a lasso.






For Further Exploration



Once you've mastered the basics of Perl testing, you may be interested in more advanced capabilities. For rigorous unit testing of legacy object-oriented applications, Test::MockObject provides a complete, if lengthy, solution. Test::MockObject lets you create objects that mock the behavior of the ones actually used in your application so they present apparently the same interface to the calling tests but under your complete control and without the side effects. (Testing a database is such a common need for mocking that the module DBD::Mock was created to help with it.) This is so-called "white box" testing: instead of looking only at the interfaces a method presents to the outside world, you craft unit tests for it by inspecting its code to see where it calls functions or methods that may alter state. Then you mock those functions to track whether they are being called the way you expect at that point.


If you like to integrate code and its documentation, you might like to do the same with its tests, in which case the CPAN module Test::Inline lets you embed tests within code in an extension of the POD language. Just encapsulate them in POD-like blocks marked "=begin testing" ... "=end testing" and then extract the tests into a test file with the program pod2test that comes with Test::Inline. (This step can be automated in your module's Makefile.PL during the make test phase.)


Test::Unit



If you're coming from a Java/JUnit background and want a familiar testing environment in Perl, the CPAN module Test::Unit is for you. You define set_up() and tear_down() procedures to prepare for and clean up after each test case so there can be no side effects between tests. Test::Unit even provides the green/red bar, courtesy of PerlTk.

Coverage Testing



The value of tests is proportional to the proportion of possible equivalence classes that are exercised. Generating the valid equivalence classes is still a manual task, but you can at least verify that all the statements in your code have been exercised during testing. Once again, this has been automated. Modules for measuring code coverage have existed for some time: Devel::DProf and Devel::SmallProf profile code and the parts that haven't been called can be inferred. Devel::Coverage shows them explicitly. But that's still too much work for the lazy. Therefore the modern module Devel::Cover has been extended to include coverage for tests. Now, simply by defining an environment variable, you can trigger analysis during make test and generate a coverage database that can be analyzed with the cover program that comes with Devel::Cover. That program outputs HTML that provides a tabular representation of the lines of code that did not get exercised. There's even another module, Test::Pod::Coverage, that verifies that all the files in your distribution provide documentation.

Legacy Application Testing



Perl programmers are often faced with having to deal with legacy applications which lack unit tests or, for that matter, coherent units. Perl's testing framework at this point becomes useful for creating end-to-end regression tests to provide a safety net while the application is modified. This can even be extended to testing web interfaces via the CPAN module Test::WWW::Mechanize. If you find the work of programming the necessary inputs to navigate a web interface too tedious, the module HTTP::Recorder will do it for you.


Automated tests can be useful for other purposes than just application testing. With the web-based testing tools just mentioned, you could write something like Listing Four to verify that your bank account is doing alright. (If you want to put it in a cron job, knowing that the exit code of a test run is the number of tests that failed may be useful.)

 

___FCKpd___7
  ->price => values %{ $self->items });
}
sub sell {
my ($self, $name) = @_;
my $item = $self->items->{$name}
or die "No $name in stock/n";
$item->sell;
}
package Store::Item;
use Class::Struct;
struct(name => '
Listing Three


Segregating tests into multiple files within the t directory can be used either to make the sizes of each file more manageable, or as a guide to partitioning the tests. You could define setup and teardown procedures in each file if you wanted to make each one effectively a single independent unit test; it's up to you. In true Perl fashion, you have enough rope either to hang yourself or to make a lasso.






For Further Exploration



Once you've mastered the basics of Perl testing, you may be interested in more advanced capabilities. For rigorous unit testing of legacy object-oriented applications, Test::MockObject provides a complete, if lengthy, solution. Test::MockObject lets you create objects that mock the behavior of the ones actually used in your application so they present apparently the same interface to the calling tests but under your complete control and without the side effects. (Testing a database is such a common need for mocking that the module DBD::Mock was created to help with it.) This is so-called "white box" testing: instead of looking only at the interfaces a method presents to the outside world, you craft unit tests for it by inspecting its code to see where it calls functions or methods that may alter state. Then you mock those functions to track whether they are being called the way you expect at that point.


If you like to integrate code and its documentation, you might like to do the same with its tests, in which case the CPAN module Test::Inline lets you embed tests within code in an extension of the POD language. Just encapsulate them in POD-like blocks marked "=begin testing" ... "=end testing" and then extract the tests into a test file with the program pod2test that comes with Test::Inline. (This step can be automated in your module's Makefile.PL during the make test phase.)


Test::Unit



If you're coming from a Java/JUnit background and want a familiar testing environment in Perl, the CPAN module Test::Unit is for you. You define set_up() and tear_down() procedures to prepare for and clean up after each test case so there can be no side effects between tests. Test::Unit even provides the green/red bar, courtesy of PerlTk.

Coverage Testing



The value of tests is proportional to the proportion of possible equivalence classes that are exercised. Generating the valid equivalence classes is still a manual task, but you can at least verify that all the statements in your code have been exercised during testing. Once again, this has been automated. Modules for measuring code coverage have existed for some time: Devel::DProf and Devel::SmallProf profile code and the parts that haven't been called can be inferred. Devel::Coverage shows them explicitly. But that's still too much work for the lazy. Therefore the modern module Devel::Cover has been extended to include coverage for tests. Now, simply by defining an environment variable, you can trigger analysis during make test and generate a coverage database that can be analyzed with the cover program that comes with Devel::Cover. That program outputs HTML that provides a tabular representation of the lines of code that did not get exercised. There's even another module, Test::Pod::Coverage, that verifies that all the files in your distribution provide documentation.

Legacy Application Testing



Perl programmers are often faced with having to deal with legacy applications which lack unit tests or, for that matter, coherent units. Perl's testing framework at this point becomes useful for creating end-to-end regression tests to provide a safety net while the application is modified. This can even be extended to testing web interfaces via the CPAN module Test::WWW::Mechanize. If you find the work of programming the necessary inputs to navigate a web interface too tedious, the module HTTP::Recorder will do it for you.


Automated tests can be useful for other purposes than just application testing. With the web-based testing tools just mentioned, you could write something like Listing Four to verify that your bank account is doing alright. (If you want to put it in a cron job, knowing that the exit code of a test run is the number of tests that failed may be useful.)

 

___FCKpd___7
  , count => '
Listing Three


Segregating tests into multiple files within the t directory can be used either to make the sizes of each file more manageable, or as a guide to partitioning the tests. You could define setup and teardown procedures in each file if you wanted to make each one effectively a single independent unit test; it's up to you. In true Perl fashion, you have enough rope either to hang yourself or to make a lasso.






For Further Exploration



Once you've mastered the basics of Perl testing, you may be interested in more advanced capabilities. For rigorous unit testing of legacy object-oriented applications, Test::MockObject provides a complete, if lengthy, solution. Test::MockObject lets you create objects that mock the behavior of the ones actually used in your application so they present apparently the same interface to the calling tests but under your complete control and without the side effects. (Testing a database is such a common need for mocking that the module DBD::Mock was created to help with it.) This is so-called "white box" testing: instead of looking only at the interfaces a method presents to the outside world, you craft unit tests for it by inspecting its code to see where it calls functions or methods that may alter state. Then you mock those functions to track whether they are being called the way you expect at that point.


If you like to integrate code and its documentation, you might like to do the same with its tests, in which case the CPAN module Test::Inline lets you embed tests within code in an extension of the POD language. Just encapsulate them in POD-like blocks marked "=begin testing" ... "=end testing" and then extract the tests into a test file with the program pod2test that comes with Test::Inline. (This step can be automated in your module's Makefile.PL during the make test phase.)


Test::Unit



If you're coming from a Java/JUnit background and want a familiar testing environment in Perl, the CPAN module Test::Unit is for you. You define set_up() and tear_down() procedures to prepare for and clean up after each test case so there can be no side effects between tests. Test::Unit even provides the green/red bar, courtesy of PerlTk.

Coverage Testing



The value of tests is proportional to the proportion of possible equivalence classes that are exercised. Generating the valid equivalence classes is still a manual task, but you can at least verify that all the statements in your code have been exercised during testing. Once again, this has been automated. Modules for measuring code coverage have existed for some time: Devel::DProf and Devel::SmallProf profile code and the parts that haven't been called can be inferred. Devel::Coverage shows them explicitly. But that's still too much work for the lazy. Therefore the modern module Devel::Cover has been extended to include coverage for tests. Now, simply by defining an environment variable, you can trigger analysis during make test and generate a coverage database that can be analyzed with the cover program that comes with Devel::Cover. That program outputs HTML that provides a tabular representation of the lines of code that did not get exercised. There's even another module, Test::Pod::Coverage, that verifies that all the files in your distribution provide documentation.

Legacy Application Testing



Perl programmers are often faced with having to deal with legacy applications which lack unit tests or, for that matter, coherent units. Perl's testing framework at this point becomes useful for creating end-to-end regression tests to provide a safety net while the application is modified. This can even be extended to testing web interfaces via the CPAN module Test::WWW::Mechanize. If you find the work of programming the necessary inputs to navigate a web interface too tedious, the module HTTP::Recorder will do it for you.


Automated tests can be useful for other purposes than just application testing. With the web-based testing tools just mentioned, you could write something like Listing Four to verify that your bank account is doing alright. (If you want to put it in a cron job, knowing that the exit code of a test run is the number of tests that failed may be useful.)

 

___FCKpd___7
  , price => '
Listing Three


Segregating tests into multiple files within the t directory can be used either to make the sizes of each file more manageable, or as a guide to partitioning the tests. You could define setup and teardown procedures in each file if you wanted to make each one effectively a single independent unit test; it's up to you. In true Perl fashion, you have enough rope either to hang yourself or to make a lasso.






For Further Exploration



Once you've mastered the basics of Perl testing, you may be interested in more advanced capabilities. For rigorous unit testing of legacy object-oriented applications, Test::MockObject provides a complete, if lengthy, solution. Test::MockObject lets you create objects that mock the behavior of the ones actually used in your application so they present apparently the same interface to the calling tests but under your complete control and without the side effects. (Testing a database is such a common need for mocking that the module DBD::Mock was created to help with it.) This is so-called "white box" testing: instead of looking only at the interfaces a method presents to the outside world, you craft unit tests for it by inspecting its code to see where it calls functions or methods that may alter state. Then you mock those functions to track whether they are being called the way you expect at that point.


If you like to integrate code and its documentation, you might like to do the same with its tests, in which case the CPAN module Test::Inline lets you embed tests within code in an extension of the POD language. Just encapsulate them in POD-like blocks marked "=begin testing" ... "=end testing" and then extract the tests into a test file with the program pod2test that comes with Test::Inline. (This step can be automated in your module's Makefile.PL during the make test phase.)


Test::Unit



If you're coming from a Java/JUnit background and want a familiar testing environment in Perl, the CPAN module Test::Unit is for you. You define set_up() and tear_down() procedures to prepare for and clean up after each test case so there can be no side effects between tests. Test::Unit even provides the green/red bar, courtesy of PerlTk.

Coverage Testing



The value of tests is proportional to the proportion of possible equivalence classes that are exercised. Generating the valid equivalence classes is still a manual task, but you can at least verify that all the statements in your code have been exercised during testing. Once again, this has been automated. Modules for measuring code coverage have existed for some time: Devel::DProf and Devel::SmallProf profile code and the parts that haven't been called can be inferred. Devel::Coverage shows them explicitly. But that's still too much work for the lazy. Therefore the modern module Devel::Cover has been extended to include coverage for tests. Now, simply by defining an environment variable, you can trigger analysis during make test and generate a coverage database that can be analyzed with the cover program that comes with Devel::Cover. That program outputs HTML that provides a tabular representation of the lines of code that did not get exercised. There's even another module, Test::Pod::Coverage, that verifies that all the files in your distribution provide documentation.

Legacy Application Testing



Perl programmers are often faced with having to deal with legacy applications which lack unit tests or, for that matter, coherent units. Perl's testing framework at this point becomes useful for creating end-to-end regression tests to provide a safety net while the application is modified. This can even be extended to testing web interfaces via the CPAN module Test::WWW::Mechanize. If you find the work of programming the necessary inputs to navigate a web interface too tedious, the module HTTP::Recorder will do it for you.


Automated tests can be useful for other purposes than just application testing. With the web-based testing tools just mentioned, you could write something like Listing Four to verify that your bank account is doing alright. (If you want to put it in a cron job, knowing that the exit code of a test run is the number of tests that failed may be useful.)

 

___FCKpd___7
  );
sub sell {
my $self = shift;
$self->count($self->count - 1);
}
1;



Listing Three


Segregating tests into multiple files within the t directory can be used either to make the sizes of each file more manageable, or as a guide to partitioning the tests. You could define setup and teardown procedures in each file if you wanted to make each one effectively a single independent unit test; it's up to you. In true Perl fashion, you have enough rope either to hang yourself or to make a lasso.






For Further Exploration



Once you've mastered the basics of Perl testing, you may be interested in more advanced capabilities. For rigorous unit testing of legacy object-oriented applications, Test::MockObject provides a complete, if lengthy, solution. Test::MockObject lets you create objects that mock the behavior of the ones actually used in your application so they present apparently the same interface to the calling tests but under your complete control and without the side effects. (Testing a database is such a common need for mocking that the module DBD::Mock was created to help with it.) This is so-called "white box" testing: instead of looking only at the interfaces a method presents to the outside world, you craft unit tests for it by inspecting its code to see where it calls functions or methods that may alter state. Then you mock those functions to track whether they are being called the way you expect at that point.


If you like to integrate code and its documentation, you might like to do the same with its tests, in which case the CPAN module Test::Inline lets you embed tests within code in an extension of the POD language. Just encapsulate them in POD-like blocks marked "=begin testing" ... "=end testing" and then extract the tests into a test file with the program pod2test that comes with Test::Inline. (This step can be automated in your module's Makefile.PL during the make test phase.)


Test::Unit



If you're coming from a Java/JUnit background and want a familiar testing environment in Perl, the CPAN module Test::Unit is for you. You define set_up() and tear_down() procedures to prepare for and clean up after each test case so there can be no side effects between tests. Test::Unit even provides the green/red bar, courtesy of PerlTk.

Coverage Testing



The value of tests is proportional to the proportion of possible equivalence classes that are exercised. Generating the valid equivalence classes is still a manual task, but you can at least verify that all the statements in your code have been exercised during testing. Once again, this has been automated. Modules for measuring code coverage have existed for some time: Devel::DProf and Devel::SmallProf profile code and the parts that haven't been called can be inferred. Devel::Coverage shows them explicitly. But that's still too much work for the lazy. Therefore the modern module Devel::Cover has been extended to include coverage for tests. Now, simply by defining an environment variable, you can trigger analysis during make test and generate a coverage database that can be analyzed with the cover program that comes with Devel::Cover. That program outputs HTML that provides a tabular representation of the lines of code that did not get exercised. There's even another module, Test::Pod::Coverage, that verifies that all the files in your distribution provide documentation.

Legacy Application Testing



Perl programmers are often faced with having to deal with legacy applications which lack unit tests or, for that matter, coherent units. Perl's testing framework at this point becomes useful for creating end-to-end regression tests to provide a safety net while the application is modified. This can even be extended to testing web interfaces via the CPAN module Test::WWW::Mechanize. If you find the work of programming the necessary inputs to navigate a web interface too tedious, the module HTTP::Recorder will do it for you.


Automated tests can be useful for other purposes than just application testing. With the web-based testing tools just mentioned, you could write something like Listing Four to verify that your bank account is doing alright. (If you want to put it in a cron job, knowing that the exit code of a test run is the number of tests that failed may be useful.)

 

___FCKpd___7
 

你可能感兴趣的:(testing,perl,module,application,documentation,regex)