This is my first question to Stack Overflow. Apologies in advance if I am breaking some rules.
I have been reading Chapter 14 of Intermediate Perl, 2nd ed., which discusses testing Perl modules and using features from Test::More. I am referring to code published directly in this book in the Section titled "Adding Our First Tests".
For some background, in this chapter, a sample Animal
class is created in a module with the same name. This class has a simple speak
method which looks like this:
sub speak {
my $class = shift;
print "a $class goes ", $class->sound, "!\n";
}
The sound
method is a simple string returned for an particular Animal, so for example, a Horse's sound
method will be simply sub sound { "neigh" }
and it's speak
method should output the following:
A Horse goes neigh!
The problem I'm running into is the following: in the testing code I've created at ./Animal/t/Animal.t , I am instructed to use bare blocks and Test::More::is
to test that the speak
method is working. The code looks like this in the test file:
[test code snip]
{
package Foofle;
use parent qw(Animal);
sub sound { 'foof' }
is( Foofle->speak,
"A Foofle goes foof!\n",
"An Animal subclass does the right thing"
);
}
The test fails. I ran all the Build commands, but when running "Build test", I get this failure for the Animal test:
Undefined subroutine &Foofle::is called at t/Animal.t line 28.
When I try to explicitly use Test::More::is
instead of just plain is
, the test still fails with the following message:
# Failed test 'An Animal subclass does the right thing'
# at t/Animal.t line 28.
# got: '1'
# expected: 'A Foofle goes foof!
# '
My methods appear to be defined exactly as I explained. I think the first error is a scope issue because of the bare blocks, but not 100% sure. The second error I am unsure about, because if I were to create a Foofle
class as a child of Animal
and called speak
on it, I would not get a 1 response, but rather the expected output.
Would someone be able to help out on what I may be doing wrong? For perhaps relevant software versions, I am using perl v5.16, Test::More v0.98, and Module::Starter v1.58.
» Read more… Intermediate Perl shows the basics of Perl testing. We show you how to write test programs and how to run those from the command line. That’s the language-specific stuff and within the scope of the book. You can take it further though.
You can test Perl on Windows with continuous integration through AppVeyor. I previously showed an example of with Travis CI but that was limited to Linux. You can easily set up an account through GitHub (or other means), select projects to test, and let it do its work.
NOTE This behavior may go away in future versions. Test::More works with Perls as old as 5.8.1. Thread support is not very reliable before 5.10.1, but that's because threads are not very reliable before 5.10.1.
This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself. Irrespective of its distribution, all code examples in these files are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit.
You've quite correctly explained the reason for the first error, and fixed it right (with specifying the correct package name). But you seem to miss the simple fact: speak
method of Animal class does not return
this a $class goes...
string - it returns the result of printing it (which is 1
) instead!
See, this subroutine:
sub speak {
my $class = shift;
print "a $class goes ", $class->sound, "!\n";
}
... does not have an explicit return
statement. In this case returned is the result of evaluating the latest invoked statement of the subroutine - i.e., result of evaluating print something
, which is 1
(true
, actually).
That's why the test fails. You can fix it either with testing for 1
(but that's too trivial, I suppose) or changing the method itself so it will return a string that it prints. For example:
sub speak {
my $class = shift;
my $statement = "a $class goes " . $class->sound . "!\n";
print $statement;
return $statement;
}
... and, frankly speaking, both approaches look a bit... fishy. The latter one, while obviously more complete, will not actually cover all the functionality of this speak
method: it tests whether the statement was correct or not only, but not whether it was printed or not. )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With