So I've been threatening for a while now to overhaul Test.pm to fix
skip(), add in todo() and named tests.  I decided it might be easier
to start with a clean slate first, see what comes up and then retrofit
back onto Test.

I've come up with a theoretical test interface, not too much different
to Test.pm, but with some minor changes.  I'm not happy with it yet,
mostly with function names.  I've attached the man page here, its not
yet complete but the basics should be obvious.

The rough bits, mostly its names and ways to avoid proliferation of
specialty functions, switches and options.

expect().  This works like Test's ok, it compares two arguments to see
if they're the same (basically).  Its less flexible than ok() but can
report failures better.  A few problems.  expect() does an eq check.
What if you want ne?  What if you want ==?  !=?  lt?  I could have a
proliferation of expect_ne, expect_lt, etc... but it seems less than
worth the trouble.  I could be accomplished fairly easily with an
autoloader, but that will still pollute the testing namespace.

expect also accepts a qr// style regex.  I dumped the ok($this,
'/foo/') magic of Test.pm's ok because it generates a special case.
What if you said expect($this, $that) and $that happened to look like
a regex?  But even having qr specially processed violates this.  I
could have an expect_qr (or expect_re), but again, seems less than
worth the trouble.

I'd like todo() tests to be able to be written so you just change the
subroutine name and delete the $why part.  This will rapidly get
annoying if there's lots of expect() routines.  Even todo_expect()
seems too much to me.

todo_eval() requires some explaination.  Often an unimplemented
feature will die horribly if you try to use it.  Simplest example is
C<$obj->unimplemented_method>.  In this case you should wrap the test
in an eval block, and this requires the test is passed in as a
subroutine reference.  In keeping with avoiding special cases, todo()
shouldn't treat a subroutine reference as being anything but true (to
mirror ok()'s interface), so it means you need a new function.
todo_eval().

Anyhow, any comments welcome.


=head1 NAME

Testing - yet another framework for writing test scripts

=head1 SYNOPSIS

  use Testing;

  # Test setup
  BEGIN { plan tests => $Num_Tests }
  # or
  BEGIN { noplan }
  # or
  BEGIN { skipall }


  # Various ways to say "ok"
  ok($this eq $that, $test_name);

  expect($this, $that,    $test_name);
  expect($this, qr/that/, $test_name);

  skip($why, $test_name);

  todo($why, {$this eq $that}, $test_name);
  todo_expect($why, $this, $that, $test_name);
  todo_eval($why, sub { $this->that }, $test_name);


  # Utility comparison functions.
  eqarray(\@this, \@that);
  eqhash(\%this, \%that);
  eqset(\@this, \@that);


=head1 DESCRIPTION

This module takes some of the drudgery out of writing test scripts by
providing utility functions and handing the numbering and output
formatting for you.

So instead of writing:

  print $this eq $that ? "ok 1\n" : "not ok 1\n";

You can say:

  ok( $this eq $that );


=head2 Test names

By convention, each test is assigned a number in order.  This is
largely done automatically for you.  However, its often very useful to
assign a name to each test.  Which would you rather see:

  ok 4
  not ok 5
  ok 6

or

  ok 4 - basic multi-variable
  not ok 5 - simple exponential
  ok 6 - force == mass * acceleration

The later gives you some idea of what failed.  It also makes it easier
to find the test in your script, simply search for "simple
exponential".

All test functions take a name argument.  Its optional, but highly
suggested that you use it.


=head2 I'm ok, you're not ok.

The basic purpose of this module is to print out either "ok #" or "not
ok #" depending on if a given test succeeded or failed.  Everything
else is just gravy.

=over 4

=item B<ok>

  ok($this eq $that);
  ok($this eq $that, $test_name);

This simply evaluates any expression (C<$this eq $that> is just a
simple example) and uses that to determine if the test succeeded or
failed.  A true expression passes, a false one fails.  Very simple.

For example:

    ok( $exp{9} == 81,                   'simple exponential' );
    ok( Film->can('db_Main'),            'set_db()' );
    ok( $p->tests == 4,                  'saw tests' );
    ok( !grep !defined $_, @items,      'items populated' );

=back


=head2 Comparision functions

Not everything is a simple eq check or regex.  There are times you
need to see if two arrays are equivalent, for instance.  For these
instances, Testing provides a handful of useful functions.

=over 4

=item B<eqarray>

  eqarray(\@this, \@that);

Checks if two arrays are equivalent.  This is a deep check, so
multi-level structures are handled correctly.

=item B<eqhash>

  eqhash(\%this, \%that);

Determines if the two hashes contain the same keys and values.

=item B<eqset>

  eqset(\@this, \@that);

Similar to eqarray(), except the order of the elements is B<not>
important.  This is again a deep check and the irrelevancy of order
applies to all levels.

=back


=head1 BUGS and CAVEATS

Other than that there's no code?

None of the function names are set in stone just yet.


=head1 AUTHOR

Michael G Schwern <[EMAIL PROTECTED]> with much inspiration from
Joshua Pritikin's Test module.


=head1 HISTORY

This is a case of convergent evolution with Joshua Pritikin's Test
module.  I was actually largely unware of its existance when I'd first
written my own ok() routines.  This module exists because I can't
figure out how to easily wedge test names into Test's interface (along
with a few other problems).


=head1 SEE ALSO

L<Test> for a similar testing module.  L<Test::Harness> for details on
how your test results are interpreted by Perl.

L<Test::Unit> describes a very featureful unit testing interface.
L<Pod::Tests> shows the idea of embedded testing.

=cut

1;



-- 

Michael G. Schwern   <[EMAIL PROTECTED]>    http://www.pobox.com/~schwern/
Perl6 Quality Assurance     <[EMAIL PROTECTED]>       Kwalitee Is Job One
Sometimes these hairstyles are exaggerated beyond the laws of physics
          - Unknown narrator speaking about Anime

Reply via email to