Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I would like to present a new assertion/testing tool project. Now there's excellent Test::More with a whole ecosystem built around it and a dozen assertion tools (typically optimizing themselves out in prod environment) available on CPAN. So WHY?

RATIONALE

1. It's more or less compatible with Test::More. Actually it aims to be 100% compatible condition-wise and somewhat compatible regarding the test flow, sans black magic like TODO: and SKIP:. (Saner substitutes planned).

2. It has both functional AND object-oriented ("contract") interface. Contracts can be used in production code, say to check user input or plugin module meet requirements. Nesting contracts is possible (that's how subtest is implemented).

3. It's very easy to extend (see below). A Builder is still required, but all it does is wrapping a given condition around for export AND OO-based usage. The internal check logic does NOT depend on it. Writing a custom Contract backend (e.g. outputting XML, or dying after a certain error count) is also possible.

4. Built with testability in mind. Custom tests' failure modes can be easily checked.

5. It's faster. Up to 5x-7x in a synthetic test (see t/speed.t) and up to 30-50% in real life test suite.

I'd rather continue dreaming about the contract feature, if this rant wasn't the last drop.

SYNOPSIS

The test script usage is quite simple (read: ripped off Test::More):

use Test::Refute; is 42, 42, "this holds"; like "foo", qr/bar/, "this fails"; done_testing; # this is mandatory, even if plan declared

Or the object-oriented interface, runs just happily inside production code (on "oks" on STDOUT, no influence on return code etc):

use Test::Refute::Contract; my $c = Test::Refute::Contract->new; $c->is($user_input, 42); $c->like($another_input, qr/f?o?r?m?a?t/); if ($c->is_valid) ...

Or combining best of both worlds:

use Test::Refute qw(no_init); my $c = contract { is $user_input, 42; like $another_input, qr/f?o?r?m?a?t/; }; # analyze $c here ...

SOME PHILOSOPHY

The whole module is built around a somewhat counter-intuitive, but very simple and powerful interface.

$contract->refute( $condition, $explanation );

can be thought of as an assertion turned inside-out. If $condition is false (or null, if we're talking about Java/C++), it is assumed a pass. Everything is fine, no further details needed.

However, if it is true/present, it means that something is wrong, and the condition itself is considered the reason for failure.

This is similar to a program returning zero on successful completion, but different error codes on failure. Or this is like falsifiability concept in modern science. Or, quoting Leo Tolstoy, "All happy families are alike; each unhappy family is unhappy in its own way".

EXTENDING

Given the above, ALL your test procedure should care about is trying hard to find a discrepancy in its input (aka pure function).

Now since we need to keep OO/functional interface parity, there IS a Moose-ish builder module that works as follows:

build_refute my_is => sub { $_[0] ne $_[1] && "$_[0] != $_[1]"; }, args => 2, export => 1; # take 2 to 3 args; export by default

And this is it! A real is() is a tad harder for under handling & output escaping though. More examples can be found in Test::Refute::Basic.

More primitives (talking to the current contract, init/destroy temp stuff etc) are to follow.

Testing your shiny new test is also trivial, no hacks, forks & pipes required.

use Test::Refute; use My::Test::Module; my $c = contract { my_test (...pass); my_test (...fail); # .... }; $c->sign("100101"); note $c->get_tap; done_testing;

CONCLUSION

The project is in deep alpha stage right now, but I hope it evolves into something usable. Looking forward to your support, critique, suggestions, and prior art links.

https://github.com/dallaylaen/assert-refute-perl

In reply to RFC: Test::Refute - extensible unified assertion & testing tool by Dallaylaen

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (3)
As of 2024-04-19 17:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found