test-more
Test::More, Test::Simple and Test::Builder Perl modules for writing tests
I'm having issues merging data for coverage on Perl scripts and modules.. Running Devel::Cover individually works just fine, but when I try to combine the data I lose statistics for just the Perl script not the module..
Let me explain..
I have a directory tree that looks like so..
Code_Coverage_Test
|
|---->lib
|
|---->t
|
Inside the root Code_Coverage_Test directory I have the Build.pl file that builds the tests for the module and script that kickoff two other scripts that automate some commands for me..
./Build.pl
#!/usr/bin/perl -w
use strict;
use Module::Build;
my $buildTests = Module::Build->new(
module_name => 'testPMCoverage',
license => 'perl',
dist_abstract => 'Perl .pm Test Code Coverage',
dist_author => 'me@myEmail.com',
build_requires => {
'Test::More' => '0.10',
},
);
$buildTests->create_build_script();
./startTests.sh
#!/bin/sh
cd t
./doPMtest.sh
./doPLtest.sh
cd ../
perl Build testcover
Inside the lib dir I have the files I'm trying to run Code coverage on..
lib/testPLCoverage.pl
#!/usr/bin/perl -w
use strict;
print "Ok!";
lib/testPMCoverage.pm
use strict;
use warnings;
package testPMCoverage;
sub hello {
return "Hello";
}
sub bye {
return "Bye";
}
1;
In the t dir I have my .t test file for the module and 2 scripts that kickoff the tests for me.. Both of which are called by the startTests.sh in the root directory
t/testPMCoverage.t
#!/usr/bin/perl -w
use strict;
use Test::More;
require_ok( 'testPMCoverage' );
my $test = testPMCoverage::hello();
is($test, "Hello", "hello() test");
done_testing();
t/doPLtest.sh
#!/bin/sh
#Test 1
cd ../
cd lib
perl -MDevel::Cover=-db,../cover_db testPLCoverage.pl
t/doPMtest.sh
#!/bin/bash
cd ../
perl Build.pl
perl Build test
The issue I'm running into is that when the doPLtests.sh script runs, I get coverage data, no problem..
---------------------------- ------ ------ ------ ------ ------ ------ ------
File STMT Bran Cond Sub pod Time total
---------------------------- ------ ------ ------ ------ ------ ------ ------
testPLCoverage.pl 100.0 n/a n/a 100.0 n/a 100.0 100.0
Total 100.0 n/a n/a 100.0 n/a 100.0 100.0
---------------------------- ------ ------ ------ ------ ------ ------ ------
However, when the doPMtest.sh script finishes and the startTests.sh script initiates the Build testcover command I lose that data along the way and I get these messages ...
Reading database path/Code_Coverage_Tests/cover_db
Devel::Cover: Warning: can't open testPLCoverage.pl for MD5 digest: No such file or directory
Devel::Cover: Warning: can't locate structure for statement in testPLCoverage.pl
Devel::Cover: Warning: can't locate structure for subroutine in testPLCoverage.pl
Devel::Cover: Warning: can't locate structure for time in testPLCoverage.pl
..and somehow I lose the data
---------------------------- ------ ------ ------ ------ ------ ------ ------
File STMT Bran Cond Sub pod Time total
---------------------------- ------ ------ ------ ------ ------ ------ ------
blib/lib/testPMCoverage.pm 87.5 n/a n/a 75.0 0.0 100.0 71.4
testPLCoverage.pl n/a n/a n/a n/a n/a n/a n/a
Total 87.5 n/a n/a 75.0 0.0 100.0 71.4
---------------------------- ------ ------ ------ ------ ------ ------ ------
How can I combine the Perl module and Perl script tests to get valid code coverage in ONE file?
Source: (StackOverflow)
I try to gather my code and manage my perl project via Makefile.PL or Build.PL, everything goes well and I got the correct test result with TAP format. But I'd like to make some sub folders under t/ folder to gather different test file, then I found that when I run make test
, ./Build test
or prove
, they say no tests
. Is there any way to resolve this?
Source: (StackOverflow)
I'm currently working on building a library to implement in Project Euler puzzles. I've gotten to the point of building tests but at some point my tests fail. Everything imports okay but as soon is I test for the existence of a subroutine my newly created test fails. I initially started Test::More but to simplify things I switched to Test::Simple. With each run, even after simplifying to less complex functions for testing, I get the same error output. Is there some error in my code that I'm overlooking or is there some aspect of my system or environment that is affecting this?
NOTE: I have reviewed Test::Tutorial several times in addition to Test::Simple and Test::More docs. I also made sure to review the Perl Docs for the relevant functions (defined and exists). Using Perl 5.18.2 on Ubuntu 14.04.
Here's the output:
t/00-load.t ....... 1/? # Testing EulerUtils 0.01, Perl 5.018002, /usr/bin/perl
t/00-load.t ....... ok
t/Qual.t .......... 1/2
# Failed test 'isEven() exists'
# at t/Qual.t line 8.
# Looks like you failed 1 test of 2.
t/Qual.t .......... Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/2 subtests
t/boilerplate.t ... ok
t/manifest.t ...... skipped: Author tests not required for installation
t/pod-coverage.t .. ok
t/pod.t ........... ok
Test Summary Report
-------------------
t/Qual.t (Wstat: 256 Tests: 2 Failed: 1)
Failed test: 2
Non-zero exit status: 1
Files=6, Tests=10, 0 wallclock secs ( 0.06 usr 0.01 sys + 0.23 cusr 0.04 csys = 0.34 CPU)
Result: FAIL
Failed 1/6 test programs. 1/10 subtests failed.
Nothing object oriented, by the way...at least so far. I made a dummy test too, which explains the 2 subtests.
The test itself (updated to make the library location explicit):
use v5.18.2;
use strict;
use warnings;
use diagnostics;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::Simple tests => 1;
use Qual;
ok( defined(&isEven), 'isEven() exists' );
The subroutine from the module itself, made with module-starter:
...
sub isEven {
my $n = shift;
return 1 if ($n % 2 == 0);
}
...
Let me know if there's something needed.
Source: (StackOverflow)
I am getting the following traceback when I try and prove factorial
:
Cannot detect source of 'factorial'! at /usr/share/perl/5.18/TAP/Parser/IteratorFactory.pm line 263.
TAP::Parser::IteratorFactory::detect_source('TAP::Parser::IteratorFactory=HASH(0x2856b08)', 'TAP::Parser::Source=HASH(0x2856bc8)') called at /usr/share/perl/5.18/TAP/Parser/IteratorFactory.pm line 213
TAP::Parser::IteratorFactory::make_iterator('TAP::Parser::IteratorFactory=HASH(0x2856b08)', 'TAP::Parser::Source=HASH(0x2856bc8)') called at /usr/share/perl/5.18/TAP/Parser.pm line 469
TAP::Parser::_initialize('TAP::Parser=HASH(0x28569e8)', 'HASH(0x23d8cb8)') called at /usr/share/perl/5.18/TAP/Object.pm line 58
TAP::Object::new('TAP::Parser', 'HASH(0x23d8cb8)') called at /usr/share/perl/5.18/TAP/Object.pm line 133
TAP::Object::_construct('TAP::Harness=HASH(0x2131db8)', 'TAP::Parser', 'HASH(0x23d8cb8)') called at /usr/share/perl/5.18/TAP/Harness.pm line 779
TAP::Harness::make_parser('TAP::Harness=HASH(0x2131db8)', 'TAP::Parser::Scheduler::Job=HASH(0x28235d0)') called at /usr/share/perl/5.18/TAP/Harness.pm line 578
TAP::Harness::_aggregate_single('TAP::Harness=HASH(0x2131db8)', 'TAP::Parser::Aggregator=HASH(0x2740ae0)', 'TAP::Parser::Scheduler=HASH(0x2823570)') called at /usr/share/perl/5.18/TAP/Harness.pm line 670
TAP::Harness::aggregate_tests('TAP::Harness=HASH(0x2131db8)', 'TAP::Parser::Aggregator=HASH(0x2740ae0)', 'factorial') called at /usr/share/perl/5.18/TAP/Harness.pm line 485
TAP::Harness::__ANON__() called at /usr/share/perl/5.18/TAP/Harness.pm line 498
TAP::Harness::runtests('TAP::Harness=HASH(0x2131db8)', 'factorial') called at /usr/share/perl/5.18/App/Prove.pm line 554
App::Prove::_runtests('App::Prove=HASH(0x2120170)', 'HASH(0x2606428)', 'TAP::Harness', 'factorial') called at /usr/share/perl/5.18/App/Prove.pm line 512
App::Prove::run('App::Prove=HASH(0x2120170)') called at /usr/bin/prove line 11
This is my factorial.pm
:
package factorial;
use Exporter qw(import);
BEGIN {
our @EXPORT_OK = qw(factorial);
}
sub factorial
{
my ($parm) = @_;
my $factorial = 1;
if ($parm == 0)
{
return $factorial;
}
foreach my $i (1..$parm) {
$factorial *= $i;
}
return $factorial;
}
1;
And my factorial.t
:
#!/usr/bin/perl -w
use Test::More;
use factorial 'factorial';
is(factorial(0), 1, "boundary case");
is(factorial(1), 1, "factorial(1)");
is(factorial(2), 2, "factorial(2)");
is(factorial(6), 720, "factorial(6)");
done_testing;
I verified that my factorial
module works by running this program (or, at least, does one thing correctly).
#!/usr/bin/perl -w
use factorial 'factorial';
my $parm = 5;
print "Factorial($parm) = ", factorial($parm), "\n";
Source: (StackOverflow)
This is a question more for my understanding than anything else. I'm using Test::More
to run some tests via TAP::Harness
.
When a test runs, it returns an exit code and a wait code.
The exit code is designed to return non-zero upon failure, as per the Test::More
documentation.
But what does the wait code signify? It appears to be a multiple of the number of failed tests (256 * n) for the tests I'm running.
My guess is that the protocol is trying to emulate parent-child process relationships à la Unix but I don't know anything about wait codes.
Source: (StackOverflow)
I have a working Coro program which I'm writing test scripts for
This is a cut down version of how I'm trying to test
use Test::More ;#tests => 9;
BEGIN{
use_ok( 'EV' ) || print "Bail out!\n";
use_ok( 'Coro' ) || print "Bail out!\n";
use_ok( 'AnyEvent' ) || print "Bail out!\n";
use_ok( 'Coro::AnyEvent' ) || print "Bail out!\n";
}
my @coro;
push @coro, async sub{ok(Coro::AnyEvent::sleep(2), 'sleep')};
push @coro, async sub{ok (1 == 1, 'one equals one')};
push @coro, async sub{isnt (1, 2, 'one does not equal two')};
#push @coro, async sub{is(EV::unloop, undef, 'unloop')};
#EV::run;
map {ok($_->join, 'join')} @coro;
which gives me
t/coro-test.t ..
ok 1 - use EV;
ok 2 - use Coro;
ok 3 - use AnyEvent;
ok 4 - use Coro::AnyEvent;
ok 5 - one equals one
ok 6 - one does not equal two
Undefined subroutine &main:: called at /usr/lib/perl5/Coro/AnyEvent.pm line 218.
Dubious, test returned 9 (wstat 2304, 0x900)
All 6 subtests passed
Test Summary Report
-------------------
t/coro-test.t (Wstat: 2304 Tests: 6 Failed: 0)
Non-zero exit status: 9
Parse errors: No plan found in TAP output
Files=1, Tests=6, 0 wallclock secs ( 0.02 usr 0.01 sys + 0.18 cusr 0.03 csys = 0.24 CPU)
Result: FAIL
My (real) program sets coroutines off then they sleep whist they have nothing to do so its not a contrived example.
Any help gratefully received. (I think the unloop and EV::run aren't required)
Source: (StackOverflow)
Using the directory and file architecture in this Post on Perl Unit testing and Code Coverage (which btw was VERY helpful), I copied the files I'll be running unit tests and code coverage on into a new "lib" directory and it works like a charm!
However, I need the module to look in an existing "scripts" directory..
I have combed through the Module::Build documentation on CPAN, but I still get a Can't find file lib/processBuildSubs.pm error
Here's what I have thus far...
use strict;
use Module::Build;
my $newBuild = Module::Build->new(
module_name => 'processBuildSubs',
license => 'perl',
dist_abstract => 'processBuildSubs Unit Test',
dist_author => 'me@myemail.com',
build_requires => {
'Test::More' => '0.10',
},
);
$newBuild->create_build_script();
UPDATE!
Also just tried this..
my $newBuild = Module::Build->new(
module_name => 'scripts::processBuildSubs',
pm_files => {'processBuildSubs.pm' => 'lib/processBuildSubs.pm'},
license => 'perl',
dist_abstract => 'processBuildSubs Unit Test',
dist_author => 'me@myemail.com',
build_requires => {
'Test::More' => '0.10',
},
);
Some progress I guess, it seems to be looking in lib/scripts/.., still not quite what I need though..
UPDATE!
Sort of a hack job, but for now it does the trick for me..
#!/bin/bash
mv scripts lib
perl ./Build.pl
perl ./Build testcover
mv lib scripts
firefox cover_db/coverage.html
I run this script to change the directory name, run the tests/coverage and change the directory name back... Anyone have better ideas?
Source: (StackOverflow)
I was scrolling through the code for Test::More because I wanted to see how use_ok
and require_ok
were implemented (and why Ovid doesn't like them). I came to the _eval
subroutine, which contains some special logic that I don't fully understand for protecting variables during an eval
call. I understand from the documentation of Try::Tiny how difficult it is to deal with $@
. However, I don't understand the handling of $!
and $SIG{__DIE__}
(below block copied verbatim):
# Work around oddities surrounding resetting of $@ by immediately
# storing it.
my( $sigdie, $eval_result, $eval_error );
{
local( $@, $!, $SIG{__DIE__} ); # isolate eval
$eval_result = eval $code; ## no critic (BuiltinFunctions::ProhibitStringyEval)
$eval_error = $@;
$sigdie = $SIG{__DIE__} || undef;
}
# make sure that $code got a chance to set $SIG{__DIE__}
$SIG{__DIE__} = $sigdie if defined $sigdie;
The handling of $SIG{__DIE__}
is related to RT #34065, but I still don't get it. Why is it necessary to set the variable again in that last line, since it should always get set in the last line of the block? If the whole point of these lines is to set the variable to whatever it became in the eval
call, why does it have to be localized in the first place?
Also, if using eval
without clobbering error vars means localizing both $@
and $!
, do we not also have to localize $?
?
Source: (StackOverflow)
I've gone through the documentation and can't find a definitive answer to my query.
In a lot of my tests, the execution of a SKIP
block is conditional to the success of a prior test.
So, for example, this what I write:
ok( @results > $threshold , 'Threshold met' );
SKIP: {
skip 'due to insufficient results', 3
unless @results > $threshold;
# ...
}
If my test changes, I don't want to have to change two locations, so I'd like a DRY-er equivalent:
SKIP: {
skip 'due to insufficient results', 3
unless ok( @results > $threshold , 'Threshold met' );
# ...
}
My initial tests suggest that the two snippets are equivalent.
However, something in the documentation caught my eye:
Each SKIP
block must have the label SKIP
, or Test::More
can't work its magic.
My concern here is that the magic may spill over to the ok()
as it is now inside the block.
Source: (StackOverflow)
Context:
Say I have a few modules that inherit from each other (using old-school inheritance with base
and parent
, not Moose or similar). Foo::Bar
inherits Foo
, and Foo::Bar::Baz
inherits Foo::Bar
. All of these modules have test suites written with Test::More
. The test suite for a child class only tests the methods that it implements. Child classes do not necessarily override all methods in their parents, though they may add new methods that their parent does not have.
Question:
Is there some testing framework, technique, or Test::More
feature with which I can write tests that will not only test subclass-specific behavior, but will also then run test suites for any inherited behavior/parent classes as well? Basically, I'm looking for something that allows me to write tests for the unique/special behavior of a subclass, but will also test and make sure that the subclass behaves in tests the same way that its parent class(es) are expected to.
What I've tried:
I've written a very simple test harness with a generator method that builds an instance of a string-specified module and runs tests against it depending on what type of module was requested (there's a central hash that keeps track of subclass/superclass hierarchy), but this seems crude. I'm assuming that (like most things I need to do in Perl), someone else has already done this in a much more elegant and robust way.
Source: (StackOverflow)
I have a Perl unit test that outputs "ok" for every passed test. I find myself scrolling up and up to find the first failed test, since that's the only thing I'm interested in. I am using Test::More.
use strict; use warnings;
use JSONRegex;
use Test::More;
I would like only failed tests to appear. I tried the solution of using
perl -MTest::Harness -e 'runtests @ARGV' path/to/test_JSONRegex.pl
and it worked. But I wanted to put that in the shebang line so I could just forget about it. The shebang
#!/usr/bin/env perl -MTest::Harness
failed with message Too late for "-MTest::Harness" option at ./test_JSONRegex.pl line 1.
What is the best way to suppress passed test output while still using strict
in my script?
Source: (StackOverflow)