Thread

Posted on Thu Apr 21 03:00:23 2005 by jkeenan1
Problems with Test-Exception's Interface

I work with a number of other Perl hackers on the Phalanx quality assurance project. One of the things we try to do is to move module test suites to the family of modules built on Test::Builder: Test::Simple, Test::More, etc. While working on one such test suite, one of my colleagues tried to use Test::Exception's dies_ok and throws_ok functions. He reported that he couldn't get the hang of them.

Since this colleague is no slouch, I decided to see what was up. Much to my surprise, I couldn't get those two functions to work entirely correctly at first either. I was getting the ok, but I wasn't getting the test description.

I didn't discover the problem until I went back and very closely read the Test::Exception documentation. My fellow phalanx hoplite and I had both assumed that Test::Exception's functions would have interfaces much like Test::More's. Boy, were we wrong.

In Test::More, the syntax is:

ok( return-value-of-function, 'test description');

Note the comma between the function call and the test description. If there is whitespace after 'ok', the parens are optional but customary with or without the whitespace.

In dies_ok, the syntax is:

dies_ok { function-evaluated-within-block} 'test description';

Note the grep/map-like syntax: a block NOT followed by a comma followed by the test description. (White space between function call and block is optional.) But it's only somewhat grep/map-like, since what follows the block is a string, not a list.

Why does Test::Exception use this syntax rather than the one more familiar to Perl testers?

Now, to make things even more annoying, Test::Exception reverts to a more familiar syntax for throws_ok -- but only partially so. In this function, a comma is required between the regex matching the thrown error message and the test description:

throws_ok { function-evaluated-within-block} regex-matching-thrown-error, 'test description';

Note that there's still no comma following the block, but a comma now precedes the test description. Given the absence of a comma between the block and the regex, the comma between the regex and the test description is probably necessary in order to demarcate the two. But this demarcation comes at the cost of stylistic inconsistency with dies_ok.

I found in writing this note that I am strongly tempted to type the Test::Exception functions with trailing parens:

dies_ok()

throws_ok()

... just as I would do for all other non-built-in functions. But this would be an error, since these functions forbid parens and instead require a block as the first 'argument'.

The syntax for these two functions is only modestly cleaner than using 'eval'. We type 'dies_ok' or 'throws_ok' instead of 'eval' (more keystrokes), but don't have to type 'like($@,'. Not a big win, at least not big enough, IMO, to outweigh the idiosyncratic syntax.

Given this idiosyncratic interface, we have decided not to use Test::Exception in our phalanx work, at least not for the time being.

We appreciate the work Adrian has put into Test::Exception and have high hopes for its future development. We would recommend that an alternative interface be provided which more closely follows that established in Test::More. Such an interface would probably look like this:

dies_ok( function-evaluated, 'test description');

and

throws_ok( function-evaluated, regex-matching-thrown-error, 'test description');

Jim Keenan

Direct Responses: 372 | 374 | Write a response
Posted on Thu Apr 21 19:06:25 2005 by adrianh in response to 364
Re: Problems with Test-Exception's Interface

Why does Test::Exception use this syntax rather than the one more familiar to Perl testers?

Because I think it reads more cleanly than having to type "sub" everywhere :-) There's a general rule in Perl that there isn't a comma after passing a block to a subroutine so I don't think that this should be completely unexpected.

Now, to make things even more annoying, Test::Exception reverts to a more familiar syntax for throws_ok -- but only partially so. In this function, a comma is required between the regex matching the thrown error message and the test description

Again, this is just another instance of the general rule in Perl that there isn't a comma following a block. Please complain to Larry :-)

We would recommend that an alternative interface be provided which more closely follows that established in Test::More. Such an interface would probably look like this:

This syntax already exists. Like all subroutines prototyped to take anonymous subroutines as the first argument you can do it explicitly by using () and sub {}. For example:

dies_ok { die "oops" } 'died'; dies_ok( sub { die "oops" }, 'died' ); lives_ok { 1+1 } 'lived'; lives_ok( sub { 1+1 }, 'lived' ); throws_ok { die "oops" } qr/oops/, 'oops thrown'; throws_ok( sub { die "oops" }, qr/oops/, 'oops thrown' ); lives_and { is( 1+1, 2 ) } 'addition works'; lives_and( sub { is( 1+1, 2 ) }, 'addition works' );

Personally I find the block passing prototyped calls much easier to follow - but you can use either syntax if you wish. I'll make this more explicit in the docs.

Direct Responses: 689 | Write a response
Posted on Fri Apr 22 21:21:01 2005 by itub in response to 364
Re: Problems with Test-Exception's Interface
I like the interface of Test::Exception. It can be tricky, though, if you are not familiar with prototypes. You can read all about them at http://search.cpan.org/~NWCLARK/perl-5.8.5/pod/perlsub.pod#Prototypes .
Write a response
Posted on Sat Jul 2 20:45:04 2005 by adrianh in response to 372
Re: Problems with Test-Exception's Interface

I'll make this more explicit in the docs

Which I finally got around to in V0.21. The docs now cover how to call T::E subroutines sans-prototypes.

Write a response