Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Can I use Test::Differences with Test::LectroTest?

by pernod (Chaplain)
on Feb 01, 2005 at 16:36 UTC ( [id://426952]=perlquestion: print w/replies, xml ) Need Help??

pernod has asked for the wisdom of the Perl Monks concerning the following question:

Greetings

From time to time I use Test::LectroTest for specifications based testing, which allows me to do neat things like:

Property { ##[ x <- Int #]## square( $x ) == $x * $x; }, name => "Finding \$x's square";

This will generate a thousand tests and rapidly uncovers tricky edge cases. Take a look at the author's tutorial for a more detailed presentation of this technique.

Lately I have been thinking about comparing more complex data structures than what is shown in the basic documentation. As many of my functions return data structures, being able to compare these results with Test::Differences' eq_or_diff, or something from Test::Deep would have been nice. Something like:

use Test::Differences; Property { ##[ x <- Int, y <- Int #]## my @expected = map { $x * $_ } 0 .. $y; # Or something ... my @result = getDataAsArray( $x, $y ); eq_or_diff( \@result, \@expected ); }, name => "Transmogrifer parameters ok";

I only fiddled a little bit around with this (without success), and some googling didn't find much. I wonder if anyone knows if this is possible, or even useful?

Have a nice day :)

Edit: Changed title, the old one sounded like a howto.

pernod
--
Mischief. Mayhem. Soap.

Replies are listed 'Best First'.
Re: Can I use Test::Differences with Test::LectroTest?
by fergal (Chaplain) on Feb 01, 2005 at 17:46 UTC
    I haven't used LectroTest but if you could explain what goes wrong when you try to use Test::Deep then I might be able to tell you what to do or change Test::Deep so that it just works.

    Update. After a quick look at LT's docs it seems that using eq_deeply() is the right thing to do and the following should just work.

    use Test::Deep; Property { ##[ x <- Int, y <- Int #]## my @expected = map { $x * $_ } 0 .. $y; # Or something ... my @result = getDataAsArray( $x, $y ); eq_deeply( \@result, \@expected ); }, name => "Transmogrifer parameters ok";
    Does something bad happen when you try this?

      Oh! Seems like I should have fiddled more ...

      I built a little on my square example, and made this trivial snippet.

      #! /usr/bin/perl use Test::LectroTest; use Test::Deep; sub square { my $square = $_[ 0 ] * $_[ 0 ]; return [ $square, $square ]; } Property { ##[ x <- Int #]## my $sq = $x * $x; eq_deeply( square( $x ), [ $sq, $sq ] ); }, name => "Finding \$x's square. Twice!";

      This passes, and gives the normal output of:

      c:/dev/fun $ perl lec.pl 1..1 ok 1 - 'Finding $x's square. Twice!' (1000 attempts)

      Not enough research on my part evidently. My bad. At least it answers my original question. Yes, you can use other testing modules with Test::LectroTest :)

      But if I try the same with Test::Differences (by changing Test::Deep to Test::Differences and swapping eq_or_diff with eq_deeply), I get the following:

      c:/dev/fun $ perl lec.pl 1..1 Can't identify test lib in use, doesn't seem to be Test.pm or Test::Bu +ilder based at c:/perl/site/lib/Test/Differences.pm line 409 Test::Differences::eq_or_diff('ARRAY(0x11c9fec)', 'ARRAY(0x11c9fe0 +)') called at lec.pl line 15 main::__ANON__('Test::LectroTest::TestRunner::testcontroller=ARRAY +(0x11c9fb0)', 1) called at c:/perl/site/lib/Test/LectroTest/TestRunne +r.pm line 196 eval {...} called at c:/perl/site/lib/Test/LectroTest/TestRunner.p +m line 193 Test::LectroTest::TestRunner::run('Test::LectroTest::TestRunner=HA +SH(0x1263fbc)', 'Test::LectroTest::Property=HASH(0x11c9f68)') called +at c:/perl/site/lib/Test/LectroTest/TestRunner.pm line 289 Test::LectroTest::TestRunner::run_suite('Test::LectroTest::TestRun +ner=HASH(0x1263fbc)', 'Test::LectroTest::Property=HASH(0x11c9f68)') c +alled at c:/perl/site/lib/Test/LectroTest.pm line 157 Test::LectroTest::run() called at c:/perl/site/lib/Test/LectroTest +.pm line 160 Test::LectroTest::END() called at lec.pl line 0 eval {...} called at lec.pl line 0 ok ok ok . . . # Followed by 997 more ok's

      Looks like this is something related to how Test::Differences reports results. A Test::Builder issue, perhaps? I'll have a look into the code and see if I can figure something out.

      Thanks for the quick reply, fergal, and for pointing me in the right direction.

      pernod
      --
      Mischief. Mayhem. Soap.

        Both Test::Differences::eq_or_diff and Test::Deep::is_deeply want to call Test::Builder->ok($pass_or_fail) after they do their comparison, they also output diagnostics each time. They are not suitable for use with LT as LT wants to call them 1000s of times for each call to Test::Builder->ok.

        Test::Deep::eq_deeply is different, it just returns the result, no diagnostics, no talking to the test framework, it's designed for use independently of the test framework. Test::Differences may have a similar function, I'm not sure.

Try Test::LectroTest::Compat
by tmoertel (Chaplain) on Feb 08, 2005 at 05:22 UTC
    I have created a new compatibility module that allows Test::LectroTest and the Test::* family of modules to be mixed together. The implementation relies upon a tiny element of hackishness right now but seems to work well.

    The idea is that you build up test plans as usual with Test::More and friends. Just use Test::LectroTest::Compat if you want to use specification-based property checks as part of your plans. Define your properties in the usual LectroTest way and then use holds(property) assertions to insert property checks into your test plan. Properties that are checked within a holds assertion are free to call ok()-style assertions provided by Test::* modules (such as Test::Deep).

    When invoked this way, LectroTest runs batteries of trials to check your properties, as usual, but instead of reporting the results of each battery using LectroTest's own reporting engine, it passes the result out to Test::Builder, which records and reports the result along with the rest of your plan's tests.

    Give it a try and let me know what you think.

    See the LectroTest FAQ list for more on the subject and info on where to download the (presently in-development) module.

      I didn't see this node until today. Sorry for the delay.

      Test::LectroTest::Compat fits the bill. I had to download the package from your website and install manually though, but this looks like an issue with my CPAN mirror. Anyhow, the above example with Test::Differences rewritten to Test::LectroTest::Compat:

      #! /usr/bin/perl use Test::More tests => 1; use Test::LectroTest::Compat; use Test::Differences; sub square { my $square = $_[ 0 ] * $_[ 0 ]; return [ $square, $square ]; } my $square_property = Property { ##[ x <- Int #]## my $sq = $x * $x; eq_or_diff( square( $x ), [ $sq, $sq ] ); }, name => "Finding \$x's square. Twice!"; holds( $square_property );

      Which gives me the expected:

      shiny:~/dev/perl$ perl lec.pl 1..1 ok 1 - property 'Finding $x's square. Twice!' (1000 attempts)

      Once again, thank you very much for a great module!

      pernod
      --
      Mischief. Mayhem. Soap.

Re: Can I use Test::Differences with Test::LectroTest?
by tmoertel (Chaplain) on Feb 02, 2005 at 16:46 UTC
    The problem is that ok() is tied to the Test::Builder testing and reporting harness and LectroTest uses a different underlying harness because of all the trials it does. (Maybe I should investigate integration?)

    Anyway, if you want to use Test::Builder-based modules for their testing features and not for their harness features (which is the case when you are using them inside of LectroTest properties), you can (hackishly) redefine Test::Builder's ok() method to simply return the result status without doing anything else.

    Using Test::More for the example:

    use warnings; use strict; use Test::More; use Test::LectroTest; { no warnings; sub Test::Builder::ok { $_[1] ? 1 : 0 } # redefine ok() } Property { ##[ x <- Int( range=>[0,10] ) ]## cmp_ok( $x, '>=', 0, "" ); }, name => "cmp_ok() works with LectroTest";

    Testing it out:

    $ perl pm-lectrotest-testbuilder.pl 1..1 ok 1 - 'cmp_ok() works with LectroTest' (1000 attempts)

    I hope that this helps.

    Cheers,
    Tom

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://426952]
Approved by holli
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-03-19 04:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found