Time to play devil's advocate ;-)

I'm not convinced that this new Test::Unit::Assertion::* stuff is
TSTTCPW.  Admittedly this may well be because I'm missing some crucial
advantage it gives ...

What are our goals?  In no particular order:

  1) We would like the option of having the failure reports give us a
     listing of the assertion code that failed.

  2) We would like a nice syntax for matching against regexps.

  3) We (well, I, and maybe Matthew from the sound of it) would like
     some shorthand for string and numeric equality assertions that
     automatically generates a failure message of the form
     "Got `$foo', expected `$bar'".

  4) We would like to be able to create new types of assertion.  We
     were maybe a bit short on examples of this, but fortunately I have
     a very real need for one right now: I'm coding a new dynamic
     graphics generation suite using gimp-Perl, and I need to be able
     to be able to assert that an image generated looks exactly the
     same as one in a given filename (i.e. the fixture is image files).

  5) These assertion extensions must be createable from within
     "user-space" (i.e. outside Test::Unit::*).  In fact, if we satisfy
     requirements 2) and 3), I can't think of a reason why we would
     want to extend *inside* Test::Unit::*.

Hope I haven't missed any.

I'm not entirely convinced of the value of goal 1) -- I would have
thought a decent failure message would be usually be adequate.  If
not, we can always figure out the file and line-number where the
assertion is made, and pass that back to the runner to do as it
pleases with (fire up a viewer at that line etc.).

So, I propose that the following is TSTTCPW:

  - Pass the location (file/line) of failed assertion code to the
    listeners via the add_failure() method.  This is very easy to
    implement, satisfies goal 1), and has the advantages that a) our
    assertion code doesn't get mangled by B::Deparse if we choose to
    view it, and b) we can also choose how much context surrounding
    the code we want to see.  The latter is advantageous for longer
    test_*() methods.

  - Add assert_match() and assert_no_match() methods (except with much
    better names) to T::U::A for regexp matching.  This is trivial to
    do -- I've already done it, give or take -- and satisfies goal 2).

  - Add versions of ok() for string/numeric comparison, defaulting to
    sensible failure messages.  [I'm still dying to know if using eq
    for numeric comparison ever breaks ...]  Again, trivial, and I've
    basically done it already.  This satisfies goal 3).

  - Leave the user to code their own extended assertion techniques
    separately.  We don't have to do anything at all, and it satisfies
    goals 4) and 5).  Here's how I might do it for image comparison:

      package MyAssert::Images;

      sub assert_images_equal {
        my $self = shift;
        my ($image, $filename, $failure_message) = @_;

        # compare $image image object with image saved in $filename
        
        $failure_message ||= "image not equal to image in file $filename";
        $self->fail($failure_message) unless $is_equal;
      }

      
      package My::ImageTestCase;

      use My::ImageGenerator;
      use base qw(MyAssert::Images);

      sub test_button_generator {
        my $self = shift;

        my $button = generate_button( ... );
        $self->assert_images_equal($button, $filename1);

        my $icon = generate_icon( ... );
        $self->assert_images_equal($icon, $filename2);
      }

This is all ridiculously simple, and AFAICS, works.

Now you have to shoot me down in flames and persuade me why your way
is better ;-)

Adam

_______________________________________________
Perlunit-devel mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/perlunit-devel

Reply via email to