EzDevInfo.com

test-more

Test::More, Test::Simple and Test::Builder Perl modules for writing tests

Devel::Cover merging coverage data for Perl scripts and modules

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)

How to run perl test without t/*.t structure(t/sub_folder/*.t)

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)

Advertisements

Testing failure while Building Module

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)

Cannot detect source of 'factorial'. Why?

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)

What is the significance of the wait status in TAP?

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)

Coro Test::More

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)

How do I change the default Module::Build / Test::More directory from "lib" to something else?

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)

protecting global variables during eval in Test::More

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)

Is it fine to write "skip() unless ok()" with Test::More?

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)

How can I use Test::More and friends to automatically test inherited behavior?

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)

Suppress passed test output in Test::More

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)