Re: Test::More::is_deeply problems with blessings and stringified refs

2003-02-28 Thread Adrian Howard
True. I usually expose "deep" objects by methods rather than hash 
access, so it's not really a problem for the majority of my code.

Adrian

On Friday, February 28, 2003, at 03:54  pm, [EMAIL PROTECTED] wrote:

On Fri, Feb 28, 2003 at 11:51:07AM +, Adrian Howard wrote:
Option three.

   isa_ok($obj, 'MyClass');
   is_deeply($obj, { foo => 42, bar => 23 });
This is, unfortunately, shallow.  It won't compare objects inside $obj.




Re: STDERR tests in Test::Warn?

2003-02-28 Thread Adrian Howard
Jeez! These people with free time :-) ;-)

On Friday, February 28, 2003, at 04:00  pm, [EMAIL PROTECTED] wrote:

On Fri, Feb 28, 2003 at 11:40:52AM +, Adrian Howard wrote:
I always meant to revisit the idea for Test::Output which was intended
to be a generic FILEHANDLE output testing module. Allows you to do
things like:
[snip]
Yeah, I was thinking Test::Handle myself.  I might code it up while at
the GPW.



Re: Test::Set

2003-02-28 Thread Adrian Howard
Nice.

Comments:

-	I'd prefer is_set rather than is_math_set

-	I'd like shallow comparison options as well as deep ones. Most of the 
time I'm interested in object identity rather than structural equality. 
Maybe have: is_bag, is_set, is_deep_bag, is_deep_set

-	I'm not sure that ignoring duplicates for is_math_set will always be 
the right thing to do. When I've wanted set comparisons duplicates 
would be indicative of an error. Having both options would be nice.

Cheers,

Adrian

On Thursday, February 27, 2003, at 07:36  pm, Fergal Daly wrote:

I've been discussing this with Mr Schwern recently but he's a little
indisposed at the moment so this seemed like a good place for feedback.
Test::More's eq_set() is not a set comparison or a bag comparison but a
strange array comparison where the order of scalars doesn't matter but 
the
order of refs does, except for deeply equalrefs, which can be 
interchanged.

So

perl -MTest::More -e 'print eq_set([ [], {} ], [ {}, [] ])."\n"'

prints 0

Attached is Test::Set which provides true deep set and bag comparisons 
and
bagset.t some tests.

Any comments welcome,

F

--
Do you need someone with lots of Unix sysadmin and/or lots of OO 
software
development experience? Go on, giz a job.
My CV - http://www.fergaldaly.com/cv.html




Re: Test::More::is_deeply problems with blessings and stringified refs

2003-02-28 Thread Adrian Howard
On Thursday, February 27, 2003, at 09:21  pm, Fergal Daly wrote:

On Thursday 27 February 2003 20:54, [EMAIL PROTECTED] wrote:
On Thu, Feb 27, 2003 at 05:32:42PM +, Fergal Daly wrote:
I think that although a test that ignores blessed classes could be 
handy
in some circumstances (ie programming in general), I reckon in the
context of test suites it's a bug.
I am already not yet convinced.  In particular, it makes this sort of 
test
more difficult than it needs be:

is_deeply($obj, { foo => 42, bar => 23 });
Absolutely, but there is currently no way to do this

is_deeply($obj, bless({ foo => 42, bar => 23 }, "MyClass"));

and get a fail if $obj is not in MyClass - as I found out today ;-(

2 solutions spring to mind
[snip]

Option three.

  isa_ok($obj, 'MyClass');
  is_deeply($obj, { foo => 42, bar => 23 });
:-)

Adrian



Re: Test::More::is_deeply problems with blessings and stringified refs

2003-02-28 Thread Adrian Howard
I'd go for feature, not bug. For me is_deeply has always been for 
testing structure. We have isa_ok for checking class identity.

Having one that tested for both might be useful, but I would not change 
the behaviour of is_deeply.

Adrian

On Thursday, February 27, 2003, at 05:32  pm, Fergal Daly wrote:

On Thursday 27 February 2003 16:40, [EMAIL PROTECTED] wrote:
is_deeply() ignores the classes of blessed refs. So

perl -MTest::More=no_plan -e 'is_deeply(bless([], "a"), bless([], 
"b"))'

passes,
Oh.  Not sure if that's a bug or a feature.  Discuss it on perl-qa.
I think that although a test that ignores blessed classes could be 
handy in
some circumstances (ie programming in general), I reckon in the 
context of
test suites it's a bug.

If fixing it makes some tests fail then it means either the tests 
weren't
really correct or a genuine bug has been discovered.

While I'm at it, a definite problem is that a ref and the stringified 
version
of the ref are currently considered equal, so

perl -MTest::More=no_plan -e '$a=[];is_deeply($a, $a."", "should 
fail")'

passes.

The first patch below fixes the second problem. The second patch fixes 
the
first problem (if you think it is a problem) and will only apply 
cleanly
after patch1,

F

--
Do you need someone with lots of Unix sysadmin and/or lots of OO 
software
development experience? Go on, giz a job.
My CV - http://www.fergaldaly.com/cv.html

--- ./lib/Test/More.pm.orig 2002-08-26 17:20:41.0 +0100
+++ ./lib/Test/More.pm  2003-02-21 03:37:56.0 +
@@ -937,7 +937,7 @@
 my($this, $that, $name) = @_;
 my $ok;
-if( !ref $this || !ref $that ) {
+if( !ref $this && !ref $that ) {
 $ok = $Test->is_eq($this, $that, $name);
 }
 else {
@@ -984,8 +984,9 @@
 foreach my $idx (0..$#vals) {
 my $val = $vals[$idx];
 $vals[$idx] = !defined $val ? 'undef' :
-  $val eq $DNE  ? "Does not exist"
-: "'$val'";
+  ref $val ? $val eq $DNE  ? "Does not exist"
+   : $val
+   : "'$val'"
 }
 $out .= "$vars[0] = $vals[0]\n";
@@ -1008,7 +1009,7 @@
 #'#
 sub eq_array  {
 my($a1, $a2) = @_;
-return 1 if $a1 eq $a2;
+return 1 if !ref $a1 and ! ref $a2 and $a1 eq $a2;
 my $ok = 1;
 my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2;
@@ -1034,7 +1035,7 @@
 # Quiet uninitialized value warnings when comparing undefs.
 local $^W = 0;
-if( $e1 eq $e2 ) {
+if( ! ref $e1 and ! ref $e2 and $e1 eq $e2 ) {
 $ok = 1;
 }
 else {
@@ -1083,7 +1084,7 @@
 sub eq_hash {
 my($a1, $a2) = @_;
-return 1 if $a1 eq $a2;
+return 1 if !ref $a1 and ! ref $a2 and $a1 eq $a2;
 my $ok = 1;
 my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2;


--- lib/Test/More.pm.fixed_ref  2003-02-27 17:08:09.0 +
+++ lib/Test/More.pm2003-02-27 17:25:20.0 +
@@ -1035,37 +1035,40 @@
 # Quiet uninitialized value warnings when comparing undefs.
 local $^W = 0;
-if( ! ref $e1 and ! ref $e2 and $e1 eq $e2 ) {
-$ok = 1;
-}
-else {
-if( UNIVERSAL::isa($e1, 'ARRAY') and
-UNIVERSAL::isa($e2, 'ARRAY') )
+if( ref($e1) eq ref($e2)) {
+
+if( !ref($e1)) {
+if ($e1 eq $e2) {
+$ok = 1;
+}
+else {
+push @Data_Stack, { vals => [$e1, $e2] };
+$ok = 0;
+}
+}
+elsif( UNIVERSAL::isa($e1, 'ARRAY') )
 {
 $ok = eq_array($e1, $e2);
 }
-elsif( UNIVERSAL::isa($e1, 'HASH') and
-   UNIVERSAL::isa($e2, 'HASH') )
+elsif( UNIVERSAL::isa($e1, 'HASH') )
 {
 $ok = eq_hash($e1, $e2);
 }
-elsif( UNIVERSAL::isa($e1, 'REF') and
-   UNIVERSAL::isa($e2, 'REF') )
+elsif( UNIVERSAL::isa($e1, 'REF') )
 {
 push @Data_Stack, { type => 'REF', vals => [$e1, $e2] 
};
 $ok = _deep_check($$e1, $$e2);
 pop @Data_Stack if $ok;
 }
-elsif( UNIVERSAL::isa($e1, 'SCALAR') and
-   UNIVERSAL::isa($e2, 'SCALAR') )
+elsif( UNIVERSAL::isa($e1, 'SCALAR') )
 {
 push @Data_Stack, { type => 'REF', vals => [$e1, $e2] 
};
 $ok = _deep_check($$e1, $$e2);
 }
-else {
-push @Data_Stack, { vals => [$e1, $e2] };
-$ok = 0;
-}
+}
+else {
+push @Data_Stack, { vals => [$e1, $e2] };
+$ok = 0;
 }
 }







Re: STDERR tests in Test::Warn?

2003-02-28 Thread Adrian Howard
I'd argue that Test::Warn isn't the right place :-) To me sending 
output to STDERR and warnings are different things.

If added to Test::Warn I'd argue for separate functions. I've had 
situations where warnings were logged, and STDERR was meant for user 
readable output. Having them merged would break some tests of mine (not 
many - I won't be *that* upset if everybody disagrees with me ;-).

I always meant to revisit the idea for Test::Output which was intended 
to be a generic FILEHANDLE output testing module. Allows you to do 
things like:

output_is { hello() } "hello world\n", STDOUT, "hello world";
output_isnt   { hello() } "goodbye",   STDOUT, "not goodbye";
output_unlike { hello() } qr/bye/, STDOUT, "didn't print bye";
output_like   { hello() } qr/hello/,   STDOUT, "printed hello";
like(Test::Output->last, qr/world/, "... and world");
Which (I think) would do all that you need.

(Draft implementation of above at )

However, I'm not really happy with the above API and haven't had the 
time to think about it in any more detail. Suggestions welcome :-)

Cheers,

Adrian

On Thursday, February 27, 2003, at 05:16  pm, [EMAIL PROTECTED] wrote:

As comes up pretty often, people want to trap stuff on STDERR.  I've 
got
adhoc stuff to do that in TieOut.pm, but I've never really found a good
place to put it in a module.

Test::Warn seems like its a good spot.  Warnings and stuff going 
directly
to STDERR are related beasts.  So if Janek wants it, I can patch 
Test::Warn
to trap STDERR was well as normal warnings.

The question is the interface.  Should warning* just trap STDERR like
any other warning or should there be seperate functions?
I'd argue for the former.  First from a DWIM standpoint, and second
because sometimes you'll be getting both warnings and output to STDERR
from the same code (as just happened to me, prompting this train of
thought) and it would be nice to trap both.
The downside is the two streams are mixed and can't be seperated by
the test without unnecessarily complicating the arguments to warning*.
Dunno how important this is, don't think its very.




Re: Graphically depicting coverage vs. test results

2002-12-17 Thread Adrian Howard
Ah. Confusion of vocab. You're talking about the order of the test 
scripts rather than the order of tests run by those scripts. Yes?

I think Tony was talking about the order of tests.

While key test scripts tend to be run earlier in some setups, I'm not 
sure that's it going to be a useful distinction all of the time. There 
are certainly lots of test setups where it's not true for me.

Adrian

On Monday, December 16, 2002, at 11:12  pm, Paul Johnson wrote:

On Mon, Dec 16, 2002 at 04:49:46PM +, Tony Bowden wrote:

On Fri, Dec 13, 2002 at 12:16:53AM +0100, Paul Johnson wrote:

I also had thoughts along the lines of all tests not being equal.
Generally the earlier a test is run, the more important it is.


This isn't necessarily true.

Test::Class, for example, runs tests in alphabetical order ...


Well, yes, I think this is true for most (all?) of Perl's core and CPAN
modules, but a developer is free to impose an order by playing with the
names of the tests, similar to the way things work with rc scripts.

Maybe I should have said that tests for basic functionality should
probably be run before tests for more advanced functionality, as 
happens
in the perl core.

Fortunately, "basic" comes fairly early in the alphabet :-)

--
Paul Johnson - [EMAIL PROTECTED]
http://www.pjcj.net





Re: Changing T::B behavior

2002-11-14 Thread Adrian Howard
On Wednesday, November 13, 2002, at 08:54  pm, Michael G Schwern wrote:
[snip]

I think I'll merge your $Test::Builder::default idea with this.  Have a
stack of Test::Builder objects rather than just the states.  This way you
can do something like the above.  If you add a $tb->copy method which
returns a carbon-copy of $tb then...

$tb->push_state;  # calls $tb->copy and pushes it into the stack
		  # the copy will now be used by default
$tb->pop_state;   # pops the stack and tosses it, restoring the
		  # original.


So what you're proposing is a class-wide "default object" stack,
rather than an object-based state stack - yes?

I have a hinky feeling about these being object methods. Changing the
default object would seem read more naturally to me as a class method:

	Test::Builder->push_default($tb);
	Test::Builder->pop_default


but what if you want to use your own subclass?  Well if you also add a
$tb->state method which return the full internal state it makes it 
possible
for subclasses to copy each other.  So...

$tb->push_state(My::Test::Builder->copy($tb));
...my test code...
$tb->pop_state;

The problem there is the case where you want to override behaviors but 
still
keep state between the two objects.  So things like the test counter and
test details would have to be preserved.  I guess this is what chromatic 
was
talking about when he suggested having only certain parts of the internal
state be a singleton.

Ahhh... that makes sense now.

A specific example:

In Test::Class I would like to override ok() so that it reports
Test::Class->current_method as the default test name. The 'nice' way
of doing this would be to create my own subclass of T::B with an
appropriately overridden ok() method.

However, I still want to allow the user to run non-T::C based tests
before and after the T::C tests.

This means that my custom T::B class will need to share the state of
the T::B object used before and after the test class was run.


So looking at the stuff in reset():

[snip]

We can seperate them out into Test::Builder configuration and test state.

This is test state and would be shared amongst the T::B objects in the
default stack

$Test_Died
$Have_Plan
$No_Plan
$Curr_Test
$Original_Pid
@Test_Results
@Test_Details
$Expected_Tests
$Skip_All

and these are T::B configuration values and wouldn't be shared, though 
they
would be initially copied.

$Level
$Exported_To
$Use_Nums
$No_Header
$No_Ending
the output filehandles

I'm not convinced about the separation between test state and T::B
configuration - what advantage does it give you?

I can see situations where you would want to share all the state, and
situations where you want completely different state - but can't think
of any where you would want to share part of the state.

This is may be lack of imagination on my part :-)

If we have a Test::Builder state() method that returns a
Test::Builder::State object, then we could just supply it as a
constructor argument if we wanted to share state:

So, for my Test::Class example I would do something like this:

	package My::Test::Builder;
	use base qw(Test::Builder);
	sub ok {
		my ($self, $test, $name);
		local $Test::Builder::Level = $Test::Builder::Level+1;
		$name = Test::Class->current_method unless defined($name);
		$self->SUPER::ok($test, $name);
	};

	... later on in Test::Class ...

	sub runtests {
		local $Test::Class::Default = My::Test::Builder->create(
			state => Test::Builder->default->state
		);
		 all tests in method will now use my T::B class ...
	};


So I guess we need several constructors.


If you have explicit access to the state I think you can get away with one 
(and the mangled new(), which is really just there for backwards 
compatibility).

real constructor  - a "normal" constructor


my $new = Test::Builder->create();


singleton constructor - returns a single, default object.  This object
	  	is actually a wrapper around the default object
			stack.


	my $default = Test::Builder->new();		# or ...
	my $default = $Test::Builder::Default;	# or ...
	my $default = Test::Builder->default;

depending on how you want to play with the API. Not really a
constructor - just provides access to the default object created by
Test::Builder.


copy	  	  - copies the state of one object to a new one


use Storable qw(dclone);
my $clone_tb = Test::Builder->create(state => dclone($tb->state));


copy & share state- like copy, but test state is shared between the
   	 	  	original and the copy


my $shared_tb = Test::Builder->create(state => $tb->state);


with those plus the push/pop_stack methods you can pick and choose what 
sort
of state sharing you want.

If we have explicit access to the state - is there any advantage in
having a stack of objects?

Localising $Test::Builder::Default, or saving/restoring T::B->default
would seem to give you all the functionality necessary. (You could
always subclass T::B if you really wa

Re: Test::Builder->level

2002-11-13 Thread Adrian Howard

On Wednesday, November 13, 2002, at 08:37  pm, Michael G Schwern wrote:


On Tue, Nov 12, 2002 at 04:21:38PM +, Adrian Howard wrote:

At YAPC::Europe there was some discussion about Test::Builder->level,
$Test::Builder::Level and the fact that they don't really work well as
implemented.  I know we reached some sort of consensus about how to do 
it
better, but I've forgotten it.

Yet another suggestion to add to the list of possible options.

Most of the time when I need to mess with level, the code that does
the test is sitting in a different package from the one that is
calling the test. How about having it walk up the call stack until it
find a package that differs from the one it was called in?

No nasty messing with numbers and you don't have to fiddle with it
every time you add/remove a sub in the call chain.


ETOOMAGICAL and it makes it impossible to have something like this:

[snip]

Good point.


Of course, there's nothing stopping you from overriding level() to be
magical, once I implement your ideas about being able to change the 
default
object and stack them.

:-)

Adrian




Re: Test::Builder->level

2002-11-13 Thread Adrian Howard

On Monday, November 11, 2002, at 04:10  am, Michael G Schwern wrote:


At YAPC::Europe there was some discussion about Test::Builder->level,
$Test::Builder::Level and the fact that they don't really work well as
implemented.  I know we reached some sort of consensus about how to do it
better, but I've forgotten it.


Yet another suggestion to add to the list of possible options.

Most of the time when I need to mess with level, the code that does
the test is sitting in a different package from the one that is
calling the test. How about having it walk up the call stack until it
find a package that differs from the one it was called in?

No nasty messing with numbers and you don't have to fiddle with it
every time you add/remove a sub in the call chain.

Adrian




Re: And for the mod_perl folks... Test::Builder->reset

2002-11-12 Thread Adrian Howard

On Tuesday, November 12, 2002, at 01:40  am, Michael G Schwern wrote:


On Tue, Nov 12, 2002 at 01:31:43AM +, Mark Fowler wrote:

Test::Builder->new would remain as a singleton.  We'd just provide an
alternate constructor to provide a second object if someone really wants 
it.

You know, that would at the very least tidy up Test::Builder::Tester
somewhat.  It's currently just a bit of a hack...(sssh, I didn't really
say that)

That's two votes.

[snip]

Make that three votes :-) I've been meaning to write a little missive
on why Test::Builder shouldn't be a singleton for some time.

Three reasons why I would like Test::Builder not to be a singleton:


1)  Makes testing tests much easier.

If you can have the code you're testing use one object while your
tests use another then testing tests becomes considerably less
baroque.

Some of the tests in Test::Class are quite evil - even with the help
of Test::Builder::Tester (thanks Mark :-). Things like capturing test
headers would be easy if I had access to a completely separate builder
object.


2)  Makes it easy to collect a set of test results and use them as a
meta-test.

For example, for one project I did a few months back I needed to write
some tests in a declarative style (done a bit before Test::ManyParams
was around unfortunately). I didn't want to reimplement the normal
test subroutines, so I went about it by collecting test results.

E.g.:

sub pass_all (&@) {
	my ($sub, $name) = @_;

	Test::Builder->no_ending(1);	# since we mess with current_test 
too much
	my $builder = Test::Builder->new;

	my $old_test = $builder->current_test;
	my $io = IO::File->new_tmpfile or die "bad tmp file ($!)";
	my ($output, $failure_out) = ($builder->output, 
$builder->failure_output);

	eval {
		$builder->output($io);
		$builder->failure_output($io);
		$sub->();
	};
	
	my $exception = $@;
	my $failed = grep {$_ == 0} ($builder->summary)[$old_test .. 
$builder->current_test-1];
	$builder->output($output);
	$builder->failure_output($failure_out);
	$builder->current_test($old_test);
	die $exception if $exception;
	
	$builder->ok(!$failed, $name);
	if ($failed) {
		seek $io, SEEK_SET, 0;
		while (<$io>) {
			next if m/^#\s+Failed test (.*?at line \d+)/;
			chomp;
			s/^((not )?ok)\s+\d+/$1/;
			s/^# //;
			$builder->diag("$_")
		};
	};
};

allows me to do things like:

pass_all {
	ok(1==2, "1==2");
	ok(2==2, "2==2");
} 'maths is hard';

producing

	not ok 2 - maths is hard
	# Failed test (declarative.pl at line 31)
	# not ok - 1==2
	# ok - 2==2

While this works, it's not nice (and some related subs were worse).
Having to mess with no_ending because we're rewinding the current_test
number and "running" more tests than we end up reporting I find
especially nasty.

It would all be simpler if I could have had another Test::Builder object
for the tests that I was examining.


3)	Subclassing Test::Builder would be useful.

For example, I would like to make the default name for tests run under
Test::Class to be the name of the method enclosing the test.

With Test::Builder as a singleton my only option is something evil
like using Hook::LexWrap to wrap the Test::Builder ok() method. If I
can make and use a Test::Builder subclass all I need to do is override
ok() in the subclass.


How should it work? Straw man:

my $builder = Test::Builder->default
	Return the default test builder object, creating a new one if
	necessary.

Test::Builder->default($new)
	Set a new default builder object

$Test::Builder::Default
	Tied scalar that returns/sets the default test builder object

Test::Builder->new
Returns the tied scalar $Test::Builder::Default. That way we can
change the default of existing Test::Builder based modules that
initialise a single builder object at compile time.

Test::Builder->create
	Really create a new Test::Builder object.

This would allow me to rewrite pass_all() something like this:

sub pass_all (&@) {
	my ($sub, $name) = @_;

	my $io = IO::File->new_tmpfile or die "bad tmp file ($!)";

	my $failed;
	{
		local $Test::Builder::Default = Test::Builder->create;
		$Test::Builder::Default->output($io);
		$Test::Builder::Default->failure_output($io);
		$sub->();
		$failed = grep {$_ == 0} $Test::Builder::Default->summary;
	};

	my $builder = Test::Builder->default;
	$builder->ok(!$failed, $name);

	if ($failed) {
		seek $io, SEEK_SET, 0;
		while (<$io>) {
			next if m/^#\s+Failed test (.*?at line \d+)/;
			chomp;
			s/^((not )?ok)\s+\d+/$1/;
			s/^# //;
			$builder->diag("$_")
		};
	};
};

Which I think is much nicer! Hopefully this make sense and sleep
depravation isn't making me talk nonsense again ;-)

Cheers,

Adrian



Re: callbacks at the end of Test::More ?

2002-11-12 Thread Adrian Howard
On Saturday, October 26, 2002, at 04:22  pm, Nicholas Clark wrote:
[snip]

However, I'd like to be able to cleanly print out my random number seed to
STDERR (or whatever Test::Builder's correct name for this is) if it 
believes
that any tests have failed, and I can't see a clean way to do this.
When I was experimenting with this idea at work I hacked things by having 
an
END block that checked $?, and if it was non-zero printing out the seed.
However, this doesn' seem to be a good idea for production code.
[snip]

Belated response... but the END block solution doesn't seem that nasty to 
me. What problems do you see for production code?

You might want to have a chat to Janek Schleicher since his 
Test::ManyParams also sets the pseudo-random seed. It would be nice if 
your modules could play nice together :-)

Cheers,

Adrian

PS Or you could use Test::Class and stick the print in the DESTROY method 
for the class :-)



Test::Class - comments wanted

2002-10-13 Thread Adrian Howard

Hi all,

There's been a new version of Test::Class coming 'real soon' for a few
months now :-)

Amongst the bug fixes and extensions I've been considering a couple of
changes that I'm not 100% on and would appreciate any comments /
feedback / abuse on offer... it's late so apologies if this makes little 
sense.

Currently, if you don't specify the number of tests for a test method
it assumes the method will run a single test. You can also specify the
number of tests explicitly, or say 'no_plan' if it runs an arbitrary
number of tests.

For example:

sub one_test: Test  { ok(1==1) };
sub another_test: Test(1)   { ok(1==1) };
sub two_tests   : Test(2)   { ok(1==1); ok(2==2) };
sub n_tests : Test(no_plan) { ok(1==1) while rand(100) > 5 };

Test::Class methods that manipulate the number of tests take and
return integers or the string 'no_plan', for example:

die "undetermined # tests" if $Tests->num_tests eq 'no_plan';

I'm considering two changes.
a)  Test methods default to an arbitrary number of tests.
b)  Use undef rather than 'no_plan'

This gives us:

sub one_test: Test(1)   { ok(1==1) };
sub two_tests   : Test(2)   { ok(1==1); ok(2==2) };
sub n_tests : Test  { ok(1==1) while rand(100) > 5 
};
sub n_more_tests: Test(undef)   { ok(1==1) while rand(100) > 5 };

and

die "undetermined # tests" unless $Tests->num_tests;

Why change:

-   Seems more "perlish"... compare and contrast:
my $foo;sub foo : Test{};
my $foo = undef;sub foo : Test(undef) {};
my $foo = 1;sub foo : Test(1) {};
my $foo = 2;sub foo : Test(2) {};

-   The 'no_plan' in Test::Class isn't the same concept as the 'no_plan' 
in Test::Builder... some people have found the identical naming confusing.

-   "undef" seems a nice shorthand for "undefined number of tests"

-   No more messy "eq 'no_plan'"

-   Makes it simpler for people who prefer the 'no_plan' style of testing

-   Typing "(1)" isn't too much effort and makes the # tests explicit.

-   In hindsight, having a 1 test default was probably a hangover from 
JUnit thinking... I never really considered any alternatives.

Reasons not to change:

-   I have to go back and re-write the Test::Class::Tutorial I've mostly 
finished writing... g...

-   I think that a test suite with a known number of tests is a Good 
Thing. Making the default number of tests for a method undetermined runs 
against the grain a bit.

-   It's not backwards compatible

Opinions?

(Oh yes, I just noticed when reading over my Test::Class mail to compose 
this message that  Mr Schwern said in one of his e-mails on Test::Class

> Make no_plan the default?  Works for Test::Inline.

guess I should have paid more attention ;-)

Cheers,

Adrian




Re: Test::Class weirdness

2002-10-10 Thread Adrian Howard

Hi all,

On Thursday, October 10, 2002, at 05:04  pm, Tony Bowden wrote:
[snip]
>   use Test::Class;
>   use UNIVERSAL::require;
>
>   my @tests = qw( Example::Test Another::Test );
>   foreach my $class (@tests) {
> $class->require or die "Can't require $class";
>   }
>   Test::Class->runtests(@tests);
>
> However this keeps dying with "cannot test anonymous subs". A
> cursory delve into the innards of Test::Class implies that perhaps
> Attribute::Handlers is getting confused somewhere. But I'm not sure
> what's going on here really ...
[snip]

Think I've figured it out.

If you stick your loop inside a BEGIN {} block I think you'll find that it 
works as you expect.

The attribute handler in Test::Class is set to run as a CHECK block (the 
default provided by Attribute::Handlers). Since you don't require the 
module until runtime the handler gets confused.

I'm running A::H 0.78 - and in my case it just skips running the 
handler... so no test methods get defined and nothing gets run.

I am guessing that you're running an earlier version of A::H and that's 
why it's passing ANON as the symbol to the Test::Class handler, hence the 
confusing error message.

Hopefully that makes some vague sort of sense!

Now I need to figure out if:
(a) this is a bug or a lack of documentation on my part
(b) if/how it can be fixed :-)

Hope this helps.

Cheers,

Adrian




Re: Test::Class weirdness

2002-10-10 Thread Adrian Howard

On Thursday, October 10, 2002, at 05:04  pm, Tony Bowden wrote:

[snip]
> I hate this sort of duplication, so I tried for a while to eliminate it,
> mostly through an approach like:
>
>   use Test::Class;
>   use UNIVERSAL::require;
>
>   my @tests = qw( Example::Test Another::Test );
>   foreach my $class (@tests) {
> $class->require or die "Can't require $class";
>   }
>   Test::Class->runtests(@tests);
>
> However this keeps dying with "cannot test anonymous subs". A
> cursory delve into the innards of Test::Class implies that perhaps
> Attribute::Handlers is getting confused somewhere. But I'm not sure
> what's going on here really ...
>
> Anyone shed any light?
[snip]

Can't shed any light yet... However, here's another way of doing what you 
want that does work :-)

 my @TEST_CLASSES;

 BEGIN {
@TEST_CLASSES = qw(
Example::Test
Another::Test
);
foreach my $class (@TEST_CLASSES) {
eval "use $class";
die "$@" if $@;
};
 };

 Test::Class->runtests( @TEST_CLASSES );

Can you pass on the version # of Attribute::Handlers & UNIVERSAL::require 
you're using - since it's failing silently for me, rather than giving the 
error... will investigate further.

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  www.quietstars.com




Re: Add Test::Harness 2.x Prerequisite to Test::Simple?

2002-08-26 Thread Adrian Howard


On Monday, August 26, 2002, at 08:22  am, Michael G Schwern wrote:

> On Mon, Aug 26, 2002 at 12:48:45AM +0100, Adrian Howard wrote:
>> I've added a patch to Test::Exception (should have spotted that... 
>> *bad*
>> Adrian :-). It should be hitting CPAN in the next few minutes.
>
> You shouldn't need it, but it can't hurt.
>
Ah well... I needed to fix the prototypes anyway :-)

Adrian




Re: Add Test::Harness 2.x Prerequisite to Test::Simple?

2002-08-25 Thread Adrian Howard


On Saturday, August 24, 2002, at 11:08  pm, chromatic wrote:

> I've been using Test::Exception on a project and am very glad to have 
> it.  I
> ran into a small issue trying to install it, though: it has TODO tests, 
> but
> those failed as the existing version of Test::Harness (1.26 or so) did 
> not
> understand them.
>
> Since TODO tests are a feature of Test::More, perhaps it would be 
> correct to
> mark Test::Harness 2.x as a prerequisite for the Test::Simple bundle.  
> I almost
> sent Adrian a patch doing this for Test::Exception, but it seems that
> Test::Simple is the best place to handle this.

I've added a patch to Test::Exception (should have spotted that... *bad*
Adrian :-). It should be hitting CPAN in the next few minutes.

I guess it's punishment for using TODO tests as a quick way to test
failing tests.

Can anybody give me a definitive version of when TODO tests started
working in Test::Harness? From the Changes file I'm currently assuming
everything after Test::Harness 2.03 inclusive should be okay.

Personally, I would tend towards leaving the prerequisites to
Test::Builder alone. I think I'm right in saying that everything
except TODO tests work fine with the earlier Test::Harness, so it
seems unhelpful to prevent people using the rest of the distribution.

Maybe throw out a warning that TODO tests won't work on the
Test::Builder install if the latest Test::Harness isn't installed?

Cheers,

Adrian




Re: Testing failure in Test::Builder-based modules

2002-08-03 Thread Adrian Howard

On Saturday, August 3, 2002, at 09:56  pm, Andy Lester wrote:

> I'm adding some tests to Test::HTML::Lint, and one of the things that I
> want to check for is that "html_ok(undef)" fails.  Remember that
> html_ok() is a T::B-based module.
[snip]

Take a look at Test::Builder::Tester. Something like this should do
the trick:

   use Test::Builder::Tester tests => 4;
   use Test::HTML::Lint;
   use Test::More;

   BEGIN { use_ok( 'Test::HTML::Lint' ); }

   my $chunk = "This is a fine chunk of code";

   test_out("not ok 2");
   html_ok(undef);
   test_test("undef should fail");

   html_ok( '' );  # Blank is OK
   html_ok( $chunk );

Or, if you prefer, you could go all retro and use Test and IO::File. For 
example:

   use strict;
   use Test;
   use Test::Builder;
   use Fcntl;
   use IO::File;
   use Test::HTML::Lint;

   plan tests => 2;

   my $io = IO::File->new_tmpfile or die "couldn't create tmp file 
($!)\n";
   my $Test = Test::Builder->new;
   $Test->output($io);
   $Test->failure_output($io);
   $Test->expected_tests(1);
   html_ok(undef);

   seek $io, SEEK_SET, 0;
   while (my $actual = <$io>) {
  chomp($actual);
  my $expected=; chomp($expected);
  ok($actual, $expected);
   };

   __DATA__
   1..1
   not ok 1

> I see two problems with this approach:
>
> * It's not really a TODO item.
>
> * If html_ok(undef) unexpectedly succeeds, the results aren't really
> obvious:
[snip]

Personally, I just use TODO, unless I need to check the diagnostic
message output. In that case I use Test::Builder::Tester, unless I
need to check the plan output. In that case, I use Test and IO::File
:-)

Hope this helps.

Cheers,

Adrian




Re: RFC: Test::Warn

2002-07-08 Thread Adrian Howard


On Monday, July 1, 2002, at 03:21  pm, Janek Schleicher wrote:

> Hello!
>
> On Sun, 30 Jun 2002, Adrian Howard wrote:
>
>> Nothing like it AFAIK - sounds useful. I've got places where I'm doing
>> this sort of thing, but I slurp up STDERR rather than wrapping
>> SIG{__WARN__} (which I assume is what you're planning?)
>
> I wanted to use SIG{__WARN__},
> but if I know some code where it makes problem,
> perhaps I'll use another implementation.
>
> Both ways can be problematic,
> as SIG{__WARN__} can be overwritten and
> STDERR could be changed internally.

Personally, I think it should be wrapping SIG{__WARN__}, or the name
should be changed to something like Test::STDERR with stderr_like,
etc.

If you want to go the latter route I did a quick 'n' dirty
Test::Output module for capturing stuff sent to filehandles, allowing
you to do:

   output_is { hello() } "hello world\n", STDOUT, "hello world";
   output_isnt   { hello() } "goodbye",   STDOUT, "not goodbye";
   output_unlike { hello() } qr/bye/, STDOUT, "didn't print bye";
   output_like   { hello() } qr/hello/,   STDOUT, "printed hello";
   like(Test::Output->last, qr/world/, "... and world");

I'm not entirely happy with implementation or API, but I've not had
the spare time to give it any thought. The code's at
<http://www.quietstars.com/perl/> if you're interested ;-)

There is a useful difference between the production of a warning, and
the way the app chooses to handle the warning. If I choose to send my
warnings off to syslog by changing SIG{__WARN__} I should still be
able to test for the warnings with warn_like, etc.

[snip]
>> Maybe warn_like or warning_like instead of warns_ok (so it's like
>> Test::More's "like")?
>
> Great idea.
> (In fact I took your Test::Exception module as pattern,
>  so I only translated dies_ok to warns_ok :-) )

My fault :-) In hindsight I should have done a separate throws_like and 
throws_isa.

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  www.quietstars.com




Fwd: Test::Class... comments?

2002-06-16 Thread Adrian Howard

Oops... forgot to CC to group. Adrian.

Begin forwarded message:

> From: Adrian Howard <[EMAIL PROTECTED]>
> Date: Sun Jun 16, 2002  08:25:37  pm Europe/London
> To: Michael G Schwern <[EMAIL PROTECTED]>
> Subject: Re: Test::Class... comments?
>
> On Sunday, June 16, 2002, at 09:07  am, Michael G Schwern wrote:
>
>> On Sun, Jun 16, 2002 at 12:14:59AM +0100, Adrian Howard wrote:
>>> 0)  Do other people find this vaguely sane? Even  possibly 
>>> useful?
>>
>> Yes!  xUnit with a Perl spin is something I've wanted for a long time.
> [snip]
>
> Not just me then. Good :-)
>
>>> 3)  The fact that num_method_tests() uses the class it was called 
>>> from,
>>> rather that the one it was applied to, seems kind of gnarly. However,
>>> it did seem the neatest solution to the inheritance problem mentioned
>>> in the documentation. How offensive do people find this, and is there
>>> a better solution?
>>
>> I don't quite follow the problem.  Could you clarify?
>
> Rather contrived illustration follows:
>
> Consider a test method that runs a variable number of test:
>
> package Base::Test;
> use base qw(Test::Class);
> use Test::More;
>
> sub foo : Test(no_plan) {
> my $self = shift;
> my $objects = $self->{objects};
> isa_ok($_, 'Foo') foreach @$objects;
> };
>
> Doing:
>
> Base::Test->new(objects => [Foo->new, Foo->new])->runtests;
>
> gives us
>
> ok 1 - The object isa Foo
> ok 2 - The object isa Foo
> 1..2
>
> This works fine, but since having a predetermined number of tests is a
> Good Thing we want to let Test::Class know how many tests the method
> should run. Since we don't know this until the test object is created we
> override new() and set the number of tests then.
>
> sub new {
> my $class = shift;
> my $self = $class->SUPER::new(@_);
> my $num_objects = @{$self->{objects}};
> $self->num_method_tests('foo', $num_objects);
> diag("Base::Test foo in $self now runs $num_objects tests");
> return($self);
> };
>
> which will give us something like
>
> # Base::Test foo in Base::Test=HASH(0x11734) now runs 2 tests
> 1..2
> ok 1 - The object isa Foo
> ok 2 - The object isa Foo
>
> Now, consider what happens when we extend check_fooness in a subclass:
>
> package Another::Test;
> use base qw(Base::Test);
> use Test::More;
>
> # add one more test to the expected # of tests for foo
> sub foo : Test(+1) {
> my $self = shift;
> $self->SUPER::foo;
> ok(1==1, 'pointless test');
> };
>
> What we want to happen is for Test::Class to figure out that the total
> number of tests that foo() should run in Another::Test is the number of
> objects in $self->{objects}, plus one.
>
> Test::Class does manage this so:
>
> Another::Test->new(objects => [Foo->new, Foo->new])->runtests;
>
> will give us
>
> # Base::Test foo in Another::Test=HASH(0x1174c) now runs 2 tests
> 1..3
> ok 1 - The object isa Foo
> ok 2 - The object isa Foo
> ok 3 - pointless test
>
> Now, the way I do this at the moment is have num_method_tests() walk up
> the callstack until it finds a package that also isa Test::Class (in 
> this
> case Base::Test) and then assume that is the class containing the method
> whose # tests it should alter.
>
> While this works, it just seems a trifle evil. When I coded it my
> thoughts went something like "Gosh. That's a greasy hack... must fix
> that later". When later eventually came around the other solutions I
> came up with seemed even worse.
>
> I just have a sneaking feeling that there's a more elegant (for some
> definition of "elegant") way of handling changing the number of tests
> for test methods that will cope with inheritance nicely.
>
> Make sense?
>
> Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  www.quietstars.com
>




Test::Class... comments?

2002-06-15 Thread Adrian Howard

Hi all,

I finally found a spare couple of days to clean up the APIs and write
some docs for the class based testing code I mentioned several months
ago when I was annoying the group with Test::Exception.

The resulting Test::Class module can be found at:

 http://www.quietstars.com/perl/

It allows you to create xUnit style testing classes using the
Test::Builder based modules, for example:

  package Example::Test;
  use base qw(Test::Class);
  use Test::More;

  # setup methods are run before every test method.
  sub make_fixture : Test(setup) {
  my $array = [1, 2];
  shift->{test_array} = $array;
  diag("array = (@$array) before test(s)");
  };

  # a test method that runs 1 test
  sub test_push : Test {
  my $array = shift->{test_array};
  push @$array, 3;
  is_deeply($array, [1, 2, 3], 'push worked');
  };

  # a test method that runs 4 tests
  sub test_pop : Test(4) {
  my $array = shift->{test_array};
  is(pop @$array, 2, 'pop = 2');
  is(pop @$array, 1, 'pop = 1');
  is_deeply($array, [], 'array empty');
  is(pop @$array, undef, 'pop = undef');
  };

  # teardown methods are run after every test method.
  sub teardown : Test(teardown) {
  my $array = shift->{test_array};
  diag("array = (@$array) after test(s)");
  };

You run the tests like this:

  Example::Test->runtests;

Why another module instead of Test::Unit or Test::SimpleUnit?

-   Test::SimpleUnit, while cute, was too simple for my needs. I
 needed to inherit tests to remove code duplication. Also didn't
 mix with Test::Builder and was therefore a harder target for
 refactoring existing *.t scripts and modules. (I also have
 AnAversionToStudlyCaps in perl :-)

-   Test::Unit is a pretty straight port of JUnit into perl. This
 gives you good things (familiarity for JUnit users, separate
 TestRunners, etc.) and bad things (hard to refactor existing *.t
 scripts since they have such a different underlying mechanism,
 *lots* of new modules to learn, etc.)

My main goal in writing Test::Class was, of course, to make testing my
code easier. Looking at the result of refactoring my tests, that
turned out to be:

 1)  Having the minimal of new features beyond Test::More et al.
 2)  Making it as easy as possible to refactor from *.t scripts to
 Test::Class classes.
 3)  Be pretty easy to get your head around if you are already
 familiar with xUnit style testing.

I've tried very hard to make it easy to refactor *.t scripts into
Test::Class classes. You don't have to switch to a different assertion
style for the tests. You don't have to re-write an entire script into
a Test::Class in one go. Etc.

A few specific questions:

0)  Do other people find this vaguely sane? Even  possibly useful?

1)  Is Test::Class the right name?

Other names that have been considered during development have been
Class::Test, Test::Attribute, Attribute::Test and Test::Case.

I avoided variants on Unit since:

 a)  there are already Test::Unit and Test::SimpleUnit and adding
 another one would confuse the world even more.

 b)  I also tend to use it for acceptance/functional tests

However, not having Unit in the name means that people looking for
perlish xUnit testing aren't going to find it :-) Suggestions before I
throw it at CPAN are welcome.

2)  You can have multiple setup/teardown methods. This fell out of the
implementation, rather than being a deliberate design decision, but it
has proved surprisingly useful (e.g. have one teardown method to clean
up resources, another to check that class invarients still hold). Is
there some reason why this is evil?

3)  The fact that num_method_tests() uses the class it was called from,
rather that the one it was applied to, seems kind of gnarly. However,
it did seem the neatest solution to the inheritance problem mentioned
in the documentation. How offensive do people find this, and is there
a better solution?

The obvious alternative (you supply the package of the method you want
to affect) makes refactoring harder since you have to remember to
update the package name.

Anyway comments/niggles/abuse welcome.

Cheers,

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  www.quietstars.com




Re: Pondering Test::Depend

2002-06-09 Thread Adrian Howard


On Sunday, June 9, 2002, at 02:59  am, chromatic wrote:

> On Saturday 08 June 2002 17:32, Adrian Howard wrote:
>
>> I eventually just bit the bullet and started writing more functional
>> tests. This (of course)  had the usual affect of writing more tests ---
>> it made development faster.
>
> What would one of these functional tests look like?

I was probably unclear in my previous message. By "function tests" I 
meant a separate script running tests with real objects, not a different 
kind of test calls in an existing *.t script.

Make sense?

>  I usually end up with a
> few tests per function with names similar to:
>
>  - save() should croak() without an 'id' parameter
>  - ... and should return false if serialization fails
>  - ... or true if it succeeds
>
> I'll probably also have several other tests that don't exercise save()'s
> effective interface.  They're not so important for dependency tracking, 
> so
> I'll ignore them for now.
>
> My current thinking is that marking the interface tests as special is 
> just
> about the only way to track them reliably:
>
>   $foo->{_store} = $mock;
>   $mock->set_series( 'serialize', 0, 1 );
>
>   eval { $foo->save() };
>   dlike( @$, qr/No id provided!/, 'save() should croak()...' );
>
>   my $result = $foo->save( 77 );
>   dok( ! $result, '... and should return false...' );
>   dok( $foo->save( 88 ), '... or true...' );
>
> ... where dlike() and dok() are Test::Depend wrappers around 
> Test::More's
> like() and ok().
>
> Test::Depend will save the names and results away and compare them at 
> the end
> of the test suite's run.
>
> There, that's my handwaving magic in a nutshell.  I'm not thrilled with 
> the
> dopey names, but haven't a better idea at the moment.

I still think that it'll help less than you think ;-) but, how about 
something like:

ok(whatever, 'a non-interface test');
track {
eval { $foo->save() };
like( @$, qr/No id provided!/, 'save() should croak()...' );

my $result = $foo->save( 77 );
ok( ! $result, '... and should return false...' );
ok( $foo->save( 88 ), '... or true...' );
};
ok(whatever, 'another non-interface test');

Since AFAIK every Test::Builder based test boils down to 
Test::Builder::ok you could implement like this:

  use Test::Builder;
  use Hook::LexWrap;

  my $Test = Test::Builder->new;

  sub track (&) {
 my $sub = shift;
 # code this evil may encourage young Mr Schwern to
 # implement the details method in Test::Builder :-)
 my $temp_tracking = wrap 'Test::Builder::ok', post => sub {
 my ($ok, $name) = @_[1..2];
 my $test = $Test->current_test;
 # you would want to stick it in a DB rather than...
 $Test->diag(
 "tracking test $test in $0 named '$name' which "
 . ($ok ? 'passed' : 'failed')
 );
 };
 eval &$sub;
  };

This would have the advantage of not having to overwrite all present & 
future test functions.

Cheers,

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  www.quietstars.com




Re: Pondering Test::Depend

2002-06-08 Thread Adrian Howard

On Saturday, June 8, 2002, at 07:12  pm, chromatic wrote:

> On Saturday 08 June 2002 11:02, Michael G Schwern wrote:
[snip]
>> In reality, if Bar.pm changes in an incompatible way Foo.pm's own tests
>> should fail and that should cover you.
>
> Not in a strict isolation testing environment, where I don't want to 
> use the
> real Bar.pm when testing Foo.pm.
>
> Maybe I'm being too strict about my isolation, but it's had good 
> results for
> me so far.

[This message has became a bit of a ramble... apologies in advance :-) ]

I played with something a bit like the proposed Test::Depend, but I 
abandoned it after a while since it didn't help me in the way I had 
expected. Don't know if this will help the discussion but what I did was 
roughly as follows...

-   Have all of my mock objects stick their class, the method names 
they were
called with, and $0 into a database. So you have a bunch of rows like:

MockFoo openBar/t/bar.t
MockFoo close   Bar/t/bar.t


-   Manually maintain a mapping from MockFoo to the real class hierarchy
that implemented Foo (this could probably have been automated if I 
could
have been bothered to think about it :-)

-   Have a test for each module that compared an MD5 hash of each 
method in the   module (got by extracting 'sub method_name {  }' 
string from the .pm)
to the hash from the last run, and throw out some warnings on the tests
that used the mocked version of the same method if it had changed (or
vanished).

My hope was that this would help me in refactoring code. I wouldn't have 
to keep track of what modules use what methods, so I could be more 
confidant in making changes.

This fell down in three ways. Two minor, one major.

#1: Minor problem - Didn't work for AUTOLOAD methods, generated 
methods,
etc.

#2: Minor problem - False negatives when changes were not in 
method_name,
but something other private method of Foo that method_name called.

These were not really issues for me, probably because of my personal 
coding style, so I didn't get a lot of false negative/positives.

Test::Depend will cope better with these problems since it looks at the 
test results of the module as a whole. This should give an excellent 
indication of semantic change (at the expense of it being module, rather 
than method, specific).

Test::Depend also involves less work in implementing the unit tests 
since you don't have to mess with the mocks.

However, it doesn't help with:

#3: Major problem - You have to check the warnings manually!

I found that, once you have a moderately complex system, it's hard to 
determine whether changes you are being warned about are going to be an 
issue (beyond simple things like method renaming). I spent too much time 
looking at the code, and usually ended up writing a functional test to 
make sure that I wasn't missing something.

I eventually just bit the bullet and started writing more functional 
tests. This (of course)  had the usual affect of writing more tests --- 
it made development faster.

Worry about making a non-compatible change to a class? Not me. I just do

% make test >& functional1.txt

make the change, then repeat

% make test >&! functional2.txt ; diff functional1.txt functional2.txt

until the only difference I see is the time the tests took.

While this involves some repetition of the unit tests it does help track 
things like changing APIs. If you change Foo in some non-compatible way 
you get the following little pattern:

- Tests show that Bar's functional tests fail, but unit tests succeed.
- Update MockFoo so that Bar's unit tests fail the same way
- Fix Bar.pm so that all tests pass.

I don't run the functional tests as often as the unit tests so I don't 
lose a lot of speed. It doesn't involve a lot of duplicate code since I 
keep most of my tests in classes that allow me to swap mock/live objects 
by subclassing and/or configuration options.

Once I started writing decent functional tests, my hack to track changed 
methods suddenly ceased being useful. I think you may find the same 
thing occurring with Test::Depend - it will just encourage you to write 
more functional tests ;-)

Cheers,

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  www.quietstars.com




Re: Test::Exception... comments?

2002-04-12 Thread Adrian Howard

on 11/4/02 2:37 am, Curt Sampson at [EMAIL PROTECTED] wrote:

> On Tue, 9 Apr 2002, Michael G Schwern wrote:
> 
>>> I'm not sure exactly what the purpose of this is; your test will
>>> still fail if it dies even when not in a lives_ok block, right?
>> 
>> It'll fail and take the whole rest of the test program with it.  Some
>> testing systems like to abort the test script on failure.  Perl's
>> doesn't.
> 
> I'm not entirely sure I buy this, since the framework seems perfectly
> happy to tell me that something is wrong whether I complete all
> the tests in a script or not. But it's hardly a point worth arguing.
[snip]

Arguing anyway just for the sake of it :-)

My motivation was testing code that threw a lot of exceptions to signify
error conditions... so you had variations on things like:

my @test_cases = (
[1,2,3] => [3,2,1],
["foo"] => ["oof"],
);

while (@test_cases) {
my ($test_args, $test_results) = (shift @test_cases, shift @test_cases);
my @results;
lives_ok {@results = $foo->method(@$test_args) }
"method(@$test_args) succeeded";
is_deeply(\@results, $test_results,
"method(@$test_args) = (@$test_results)");
};

The sequence of tests was stateless --- one test failing didn't invalidate
the other test cases. Running them all rather than exiting the test script
after a single failure seems to be a Good Thing.

It helped with my debugging anyway ;-)

Cheers,

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  http://www.quietstars.com/





Re: Test::Exception... comments?

2002-04-11 Thread Adrian Howard

on 10/4/02 11:10 pm, Michael G Schwern at [EMAIL PROTECTED] wrote:

> On Wed, Apr 10, 2002 at 10:57:09PM +0100, Adrian Howard wrote:
>> Hmmm... All seems sensible. Patch attached for Builder.pm that adds a
>> _may_be_regex method. Okay?
> 
> Except it should be public (if Test::Exception wants to use it) and
> documented and tested. :)

Mea culpa... I shall go thrash myself soundly



Patch with test & docs attached.

Okay now :-)

Adrian
--
Adrian Howard  <[EMAIL PROTECTED]>
phone: 01929 550720  fax: 0870 131 3033  http://www.quietstars.com/





Re: Test::Exception... comments?

2002-04-10 Thread Adrian Howard

Hi,

Hmmm... All seems sensible. Patch attached for Builder.pm that adds a
_may_be_regex method. Okay?

New version of Test::Exception at <http://www.quietstars.com/perl/>.

Anything else :-)

Cheers,

Adrian

on 10/4/02 4:00 pm, Michael G Schwern at [EMAIL PROTECTED] wrote:

> On Wed, Apr 10, 2002 at 11:03:27AM +0100, Mark Fowler wrote:
>> On Tue, 9 Apr 2002, Adrian Howard wrote:
>> 
>>> Any comments before I throw it at CPAN? Sound vaguely sane?
>> 
>> throws_ok can take either a class name or a Regexp ref as an argument to
>> compare against.  With earlier versions of perl you can't use the qr//
>> operator, so you can't pass regex.  Maybe it would be possible to take a
>> leaf out of Test::Builder's book for this:
>> 
>> # Check if it looks like '/foo/'
>> elsif( my($re, $opts) = $regex =~ m{^ /(.*)/ (\w*) $ }sx ) {
>> $usable_regex = "(?$opts)$re";
>> }
> 
> You could even tear that out of Test::Builder->like and into it's own
> Test::Builder->may_be_regex method so you don't have to duplicate
> code.
> 

--
e. [EMAIL PROTECTED], t. 01929 550720, f. 0870 131 3033




Re: Test::Exception... comments?

2002-04-09 Thread Adrian Howard

on 9/4/02 10:16 pm, Michael G Schwern at [EMAIL PROTECTED] wrote:
[snip]
> You probably want to guarantee that $@ will be how it died so you can do:
> 
> dies_ok { div(1,0) } 'div by zero';
> like( $@, qr/^Illegal division by zero/ );
> 
> Even though you can use throws_ok(), the dies_ok() + $@ combo is more
> flexible more processing than just a regex needs to be done on $@.
[snip]

Good idea. Done.

Fixed a couple of other silly mistakes. New code at
 if anybody wants to play.

Cheers,

Adrian
--
e. [EMAIL PROTECTED], t. 01929 550720, f. 0870 131 3033




Test::Exception... comments?

2002-04-09 Thread Adrian Howard

Hi all,

I've been refactoring a bunch of old tests with Test::More and some
convenience routines for testing exceptions dropped out (along with some
class base testing and mock object modules which still need cleaning up into
something sane.)

dies_ok BLOCK TEST_NAME
Tests to see that BLOCK exits by dying, rather than by exiting
normally. For example:

dies_ok { div(1, 0) } 'divide by zero detected';

lives_ok BLOCK TEST_NAME
Tests to see that BLOCK exits normally, and doesn't die. For
example:

lives_ok { $file = read_file('test.txt') } 'file read';

throws_ok BLOCK REGEX, TEST_NAME
throws_ok BLOCK CLASS, TEST_NAME
Tests to see that BLOCK throws a specific exception.

In the first form the test passes if the stringified exception
matches the give regular expression. For example:

throws_ok {
read_file('test.txt')
} qr/No such file/, 'no file';

In the second form the test passes if the exception is of the same
class as the one supplied, or a subclass of that class. For example:

throws_ok {$foo->bar} "Error::Simple", 'simple error';

(you can find the code at
 if you want to
play)

Any comments before I throw it at CPAN? Sound vaguely sane?

Cheers,

Adrian




Re: Test::More::diag()

2001-12-10 Thread Adrian Howard

Hi,

Newbie with Test::More --- and loving it :-)

on 10/12/01 12:04 pm, Michael G Schwern at [EMAIL PROTECTED] wrote:

> Its been on the Test::More todo list to have a blessed way to do:
> 
> print STDOUT "# here's some extra info\n";
> 
> I'm planning on using diag().
> 
> ok( $foo == $bar ) || diag 'blah blah';
> 
> it has nice mnemonics with:
> 
> open(FOO, "bar") || die 'blah blah';
> 
> "ok or diag" "open or die"
> 
> Thoughts?

Little to short for my tastes my first expansion was "diagonal" rather
than "diagnostic".

How about "comment" ?

Adrian
--
e. [EMAIL PROTECTED], t. 01929 550720, f. 0870 131 3033