Re: ANNOUNCE: Pod::Coverage

2001-08-27 Thread Barrie Slaymaker

On Sun, Aug 26, 2001 at 03:02:16PM +0100, Richard Clamp wrote:
> 
> Caveats, this isn't heading to CPAN today at the testsuite is far from
> comprehensive, and I'd like some feedback before I release it.  That
> and I was due to meet people at the pub an hour ago.

How would I keep it from complaining about undocumented,
internal-use-only helper functions?

- Barrie



Re: ANNOUNCE Pod::Tests is now Test::Inline

2001-08-29 Thread Barrie Slaymaker

On Wed, Aug 29, 2001 at 01:51:48AM -0400, Michael G Schwern wrote:
> 
> First, the syntax for the code examples has changed.  Instead of
> "=also begin/end example" it's "=for example begin/end".  This doesn't
> cause existing POD viewers to choke.

So they just silently throw away all the examples?  I think that's
worse, since nobody can tell that their documentation is damaged.

- Barrie



Proper way to build a mix-in library for Test::More?

2001-12-12 Thread Barrie Slaymaker

I've written a Test::Differences[1] that outputs things like:

not ok 5
# Failed test 5 in blib/lib/Test/Differences.pm at line 221 fail #4 *TODO*
# +-+--+
# | Got | Expected |
# +-+--+
# | a\n | a\n  |
# >x* b\n  <
# | c\n | c\n  |
# >x* d\n  <
# | e\n | e\n  |
# +-+--+

when passed strings, arrays of strings, arrays of hashes, or arrays of
arrays of strings (basically, all the result types DBI's fetchall_...()
methods can return plus whole strings).

I would like to make Test::Differences autodetect Test::More and others
like it so it can extend them "seamlessly" like so:

use Test::More ;
use Test::Differences ;

plan tests => 10 ;

is "a", "a" ;
is_or_diff \@Got1, \@Expected1, "test 2" ;
TODO: {
local $TODO = $why_oh_why ;
is_or_diff \@Got2, \@Expected2, "test 3" ;
}
 
Feedback on the module itself is welcome, but I also want to know what
the preferred way to mix in to Test::Straps supported environments is,
and if there's an equivalent way to "mix in" with Test.pm.  I'm
currently doing it as a hack just to to make it "work", but it needs to
be better integrated.

- Barrie

[1] See http://slaysys.com:81/src/Test-Differences-0.1.tar.gz



Re: Proper way to build a mix-in library for Test::More?

2001-12-12 Thread Barrie Slaymaker

On Wed, Dec 12, 2001 at 08:54:51PM -0500, Michael G Schwern wrote:
> On Wed, Dec 12, 2001 at 04:38:20PM -0500, Barrie Slaymaker wrote:
> > I've written a Test::Differences[1] that outputs things like:
> > 
> > not ok 5
> > # Failed test 5 in blib/lib/Test/Differences.pm at line 221 fail #4 *TODO*
> > # +-+--+
> > # | Got | Expected |
> > # +-+--+
> > # | a\n | a\n  |
> > # >x* b\n  <
> > # | c\n | c\n  |
> > # >x* d\n  <
> > # | e\n | e\n  |
> > # +-+--+
> > 
> > when passed strings, arrays of strings, arrays of hashes, or arrays of
> > arrays of strings (basically, all the result types DBI's fetchall_...()
> > methods can return plus whole strings).
> 
> Oooh, pretty.  Beats the hell out of is_deeply.

Only for "table" structured data.  Since older Data::Dumpers don't sort
hash keys, and I haven't integrated the Data::Dumper like code I have
elsewhere, it isn't generalized to handle all data structures.

> Mind if I steal it? :)

Not at all, but you'll need to steal Algortihm::Diff (and, for the
moment, Text::Diff, but I want to remove that necessity).

> > I would like to make Test::Differences autodetect Test::More and others
> > like it so it can extend them "seamlessly" like so:
> 
> In that case base yourself on Test::Builder and it should all Just
> Work.

Bingo, that should do the trick.

> > and if there's an equivalent way to "mix in" with Test.pm.
> 
> You can use unpublished bits like $Test::ntest.  It should be safe
> since Test.pm is stable (ie. dead).

:) I was hoping you'd say that.  I've done that before for
internal-use-only stuff (read "hacks too embarassing to release" :), so
I'll do it here.

Thanks,

Barrie



CPAN Upload: R/RB/RBS/Test-Differences-0.2.tar.gz

2001-12-13 Thread Barrie Slaymaker

Please feel free to test and suggest :).


NAME
Test::Differences - Test strings and data structures and show
differences if not ok

SYNOPSIS
   use Test ;## Or use Test::More
   use Test::Differences ;

   eq_or_diff $got,  "a\nb\nc\n",   "testing strings" ;  # lines numbered 1...
   eq_or_diff \@got, [qw( a b c )], "testing arrays" ;   # elts numbered 0...

   # Using with DBI-like data structures
   eq_or_diff $sth->fetchall_arrayref, \@exp_arrays ;
   eq_or_diff $sth->fetchall_hashref,  \@exp_hashes ;

   # To force textual or data line numbering
   eq_or_diff_text @got_lines, \@exp_lines ;  # elements numbered 1...
   eq_or_diff_data $foo, $bar ;   # lines numbered 0...

DESCRIPTION
When the code you're testing returns multiple lines or records and
they're just plain wrong, sometimes an equivalent to the Unix "diff"
utility is just what's needed.

eq_or_diff() compare two strings or (limited) data structures and either
emits an ok indication (if they are equal) or a side-by-side diff (if
they differ) like:

not ok 10
# +-+--+
# | Got | Expected |
# +-+--+
# > a   * b<
# +-+--+

These functions assume that you are presenting it with "flat" records,
looking like:

   - scalars composed of record-per-line
   - arrays of scalars,
   - arrays of arrays of scalars,
   - arrays of hashes containing only scalars

Data of these types are flattened in to single strings which are then
compared for differences. Differently data structures can be compared,
as long as they flatten identically. Hashes are presented in columnar
format with the first line having the titles.

All other data structures are run through Data::Dumper first. This is a
bit dangerous, see the LIMITATIONS entry elsewhere in this document. On
newer Data::Dumpers (after perl5.6.1), hash keys will be sorted. If you
have embedded code refs, Data::Dumper cannot tell if they are different.

All nonprintable characters (including "\n" or "\r\n") are converted to
escape codes ("\n", "\0x00"), since nonprinting characters can make
identical looking strings different. This is especially true when
comparing things on platforms like Win32 where "\n" and "\r\n" usually
look identical when "perl" prints them. On "\n"-ary systems, a text file
missing "\n" on the last line can ruin your whole day and make you go
blind. This can be a bit ugly, but, hey, these are failing tests were
talking about here, not hand-typeset epic poems.

"eq_or_diff()" starts counting records at 0 unless you pass it two text
strings:

   eq_or_diff $a, $b, $name ;   ## First line is line number 1
   eq_or_diff @a, @b, $name ;   ## First element is element 0
   eq_or_diff $a, @b, $name ;   ## First line/element is element 0

If you want to force a first record number of 0, use "eq_or_diff_data".
If you want to force a first record number of 1, use "eq_or_diff_text".
I chose to offer two additional functions instead of passing in an
options hash because it's clearer and simpler this way. YMMV.

LIMITATIONS
Uses Data::Dumper for complex data structures (like hashes :), which can
lead to some problems on older perls. Expect this to change as time
permits.

This module "mixes in" with Test.pm or any of the test libraries based
on Test::Builder (Test::Simple, Test::More, etc). It does this by
peeking to see whether Test.pm or Test/Builder.pm is in %INC, so if you
are not using one of those, it will print a warning and play dumb by not
emitting test numbers (or incrementing them). If you are using one of
these, it should interoperate nicely.

Exports all 3 functions by default (and by design). Use

use Test::Differences () ;

to suppress this behavior if you don't like the namespace pollution.

At this time, each data structure is flattened independantly, which
looks goofy if one goes through Data::Dumper and the other doesn't.

AUTHOR
Barrie Slaymaker <[EMAIL PROTECTED]>

LICENSE
Copyright 2001 Barrie Slaymaker, All Rights Reserved.

You may use this software under the terms of the GNU public license, any
version, or the Artistic license.




v0.3 [Was: CPAN Upload: R/RB/RBS/Test-Differences-0.2.tar.gz]

2001-12-14 Thread Barrie Slaymaker

Thanks both for the testing & bugfixes.  Here's the escaping portion of
changes from 0.2 to 0.3, does this seem better?

There's also a test script for the escaping now :).  I'd love to test
characters for codepoints > 0xff, but they're borken / unsupported in
all released perls, I think.  Other replies below.

   -sub _decontrol {
   -$_ =~ s/\n/\\n/g;
   -$_ =~ s/\r/\\r/g;
   -$_ =~ s/\t/\\t/g;
   -$_ =~ s{
   -([^[:print:]])
   -}{
   -my $codepoint = ord $1;
   -$codepoint <= 0xFF
   -? sprintf "\0x%02x", $codepoint
   -: sprintf "\0x{%04x}", $codepoint
   -
   +my %escapes = map {
   +( eval qq{"$_"} => $_ )
   +} (
   +map( sprintf( "\\x%02x", $_ ), ( 0, 27..31, 128..255 ) ),
   +("\\cA".."\\cZ"),
   +"\\t", "\\n", "\\r", "\\f", "\\b", "\\a", "\\e"
   +) ;
   +
   +sub _escape($) {
   +my $s = shift ;
   +$s =~ s{([^\040-\177])}{
   +   exists $escapes{$1}
   +   ? $escapes{$1}
   +   : sprintf( "\\x{%04x}", ord $1 ) ;
}ge;

   -$_;
   +$s;
}


v0.3 is headed to CPAN.  Ask your local grocer for it today!

On Fri, Dec 14, 2001 at 02:45:47PM +0900, Tatsuhiko Miyagawa wrote:
> On Fri, 14 Dec 2001 00:35:35 -0500
> Michael G Schwern <[EMAIL PROTECTED]> wrote:
> 
> > > Well, why not globally overrides Test::More's is, is_deeply etc?
> > 
> > You change the semantics of is() by doing that, potentially causing
> > confusion.
> 
> Changing the semantics is your responsibility. So it should be
> safe when forced via optional arguments of use().

The possible confusion that could result from changing the behavior of
is() in a subtle way is bad.

I don't see much advantage to changing the behavior of is_deeply, and
eq_or_diff is nit much more typing.

You are quite free to do either in your own scripts, I think.  Something
like:

use Test::More qw( plan );
use Test::Differences;

sub is{ goto &eq_or_diff }
sub is_deeply { goto &eq_or_diff_data }

should do it (untested :), and is sufficiently big and unusual that it
serves as an eye catching warning to the reader that something odd is
happening here.

> > $a = [qw(a b c)];
> > $b = [qw(a b c)];
> > is( $a, $b );
> > 
> > In Test::More, that test fails.  If you replace it eq_or_diff() it
> > passes. 
> 
> Maybe eq_or_diff_text().

The only difference between the three functions is whether they count
lines / records / elements from 0 (eq_diff_data) or 1 (eq_diff_text).
eq_or_diff_text will treat the "a"s as being line 1 instead of record /
element 0.  eq_or_diff_data treats the "a"s as being in record / elt 0.
eq_or_diff tries to DWIM it.

All three eq_or_diff... functions compare the topology of nested
structures using shallow equality like is_deeply().  None use deep
equality like is() does. 

I'm probably being confusing with all these "deep"s.  I'm using the term
deep/shallow equality in the CS sense here: deep equality means that two
objects are actually the same object; shallow equality means that two
objects have equal "value" but may be two different ones.

> > is_deeply() could probably be replaced, though.  However, I
> > don't see much benefit.
> 
> IMHO Test::Differences' benefit is its mix-in nature. Changing
> each is_deeply() to eq_or_diff_data() hand by hand "if not ok" 
> seems a little hassle to me.

Why is it more effort than doing something like:

perl -ipe 's/is_deeply/eq_or_diff' t/*.t

?

- Barrie



Re: v0.3 [Was: CPAN Upload: R/RB/RBS/Test-Differences-0.2.tar.gz]

2001-12-15 Thread Barrie Slaymaker


Now I see what you're after with the -M approach, thanks for the
example.

On Sat, Dec 15, 2001 at 07:54:17PM +0900, Tatsuhiko Miyagawa wrote:
> Two cases for using Test::*
> 
> 1) Testing our application (for paying work)
> 
> it's good to use T::D in the first place.

We're agreed here :).

> 2) Testing my CPAN module
> 
> I don't like letting go Test::More for it ;)

You can still have Test::More.  Do you mean you don't want the extra
dependency like:

PREREQ_PM => {
"Test::More" => 0,
"Test::Differences" => 0,
}
?

I can understand that :) since CPAN is/seems a non-started for a
significant number of folks (I have a Win32 system that it's
nonfuncitonal on; haven't debugged it yet).

How about having Test::More use eq_or_diff_data() in is_deeply() if it
cane eval "use Test::Differences;" and use it's current routine if it
can't?  That's as seamless as you can get.

- Barrie



Re: v0.3 [Was: CPAN Upload: R/RB/RBS/Test-Differences-0.2.tar.gz]

2001-12-15 Thread Barrie Slaymaker

On Sat, Dec 15, 2001 at 01:56:19AM -0500, Michael G Schwern wrote:
> On Sat, Dec 15, 2001 at 02:41:13AM -0500, Barrie Slaymaker wrote:
> > There's also a test script for the escaping now :).  I'd love to test
> > characters for codepoints > 0xff, but they're borken / unsupported in
> > all released perls, I think.
> 
> Broken is such an ugly word.  "Experimental" :)

:)

> 5.6.1's unicode implementation should be usable enough for your
> purposes.  You might want to have a file full of Unicode tests that
> only runs if you've got a Perl >= 5.6.1

Well, when trying to descape chr( 0x0100 ) and chr( 0xfffd ) without
"use utf8", I get:

   not ok 12
   # Test 12 got: '\xc4\x80' (t/00escape.t at line 23)
   #Expected: '\x{0100}'
   not ok 13
   # Test 13 got: '\xef\xbf\xbd' (t/00escape.t at line 24)
   #Expected: '\x{fffd}'

When I "use utf8" in Differences.pm and try to escape chr( 0xff ), I get:

   ok 10
   Malformed UTF-8 character (byte 0xff) in substitution (s///) at
   blib/lib/Test/Differences.pm line 216.
   Malformed UTF-8 character (byte 0xff) in ord at
   blib/lib/Test/Differences.pm line 216.
   Segmentation fault (core dumped)

The core dump is speaking to me.  When I channel it, a low, demented
voice (well, more demented than normal) comes from me saying "DON'T USE
UTF8 HERE".  So I just don't test for that and I don't "use utf8".  I
haven't had time to poke and prod at it to see if I can work around it.

Here's a small demo of the "Malformed" error on chr(0xff) from test 11:

   $ perl -le '  print join ",", map sprintf( "%02x", ord), chr( 0xff ) =~ 
/([\000])/'

   $ perl -le 'use utf8; print join ",", map sprintf( "%02x", ord), chr( 0xff ) =~ 
/([\000])/'
   Malformed UTF-8 character (byte 0xff) in pattern match (m//) at -e line 1.

It really seems to be matching against


And here's a one liner for the core dump:

   $ perl -le 'use utf8; ( $s = chr( 0xff )) =~ s/([^\000])/sprintf "f"/e'
   Malformed UTF-8 character (byte 0xff) in substitution (s///) at -e line 216.
   Segmentation fault (core dumped)

Throwing a split at it seems to be better than a regexp if I use utf8:

   $ perl -le 'use utf8; print join ",", map sprintf( "%02x", ord), ( split //, chr( 
0xff ) . chr( 0x100 ) . chr( 0xfffd ) . chr( 0x ) )'
   Malformed UTF-8 character (character 0x) in ord at -e line 1.  ff,100,fffd,00

but horks if I don't:

   $ perl -le 'print join ",", map sprintf( "%02x", ord), ( split //, chr( 0xff ) . 
chr( 0x100 ) . chr( 0xfffd ) . chr( 0x ) )'
   Malformed UTF-8 character (unexpected non-continuation byte 0x00 after start byte 
0xc3) in ord at -e line 1.
   Malformed UTF-8 character (unexpected continuation byte 0xbf) in ord at -e line 1.
   Malformed UTF-8 character (unexpected non-continuation byte 0x00 after start byte 
0xc4) in ord at -e line 1.
   Malformed UTF-8 character (unexpected continuation byte 0x80) in ord at -e line 1.
   Malformed UTF-8 character (unexpected non-continuation byte 0x00 after start byte 
0xef) in ord at -e line 1.
   Malformed UTF-8 character (unexpected continuation byte 0xbf) in ord at -e line 1.
   Malformed UTF-8 character (unexpected continuation byte 0xbd) in ord at -e line 1.
   Malformed UTF-8 character (unexpected non-continuation byte 0x00 after start byte 
0xef) in ord at -e line 1.
   Malformed UTF-8 character (unexpected continuation byte 0xbf) in ord at -e line 1.
   Malformed UTF-8 character (unexpected continuation byte 0xbf) in ord at -e line 1.
   00,00,00,00,00,00,00,00,00,00

I'll need to dig in to this a bit more with unpack, etc. I guess, unless
somebody who knows and loves 5.6's utf8-ness can see some happy place
I'm missing.

For reference, the regex causing the grief in the first place is:

   sub _escape($) {
   my $s = shift ;
   $s =~ s{([^\040-\177])}{
   exists $escapes{$1}
   ? $escapes{$1}
   : sprintf( "\\x{%04x}", ord $1 ) ;
   }ge;

   $s;
   }

If anyone can see a good way to walk this string byte by byte on older
perls and do either that or get automatic adjustments to utf8 mode to
work on 5.6.1, I'll be quite grateful.

- Barrie



Re: v0.3 [Was: CPAN Upload: R/RB/RBS/Test-Differences-0.2.tar.gz]

2001-12-15 Thread Barrie Slaymaker

On Sat, Dec 15, 2001 at 01:18:23PM -0500, Michael G Schwern wrote:
> On Sat, Dec 15, 2001 at 10:52:07AM -0700, chromatic wrote:
> > On Sat, 15 Dec 2001 07:10:33 -0700, Barrie Slaymaker wrote:
> > 
> > > How about having Test::More use eq_or_diff_data() in is_deeply() if it cane
> > > eval "use Test::Differences;" and use it's current routine if it can't? That's
> > > as seamless as you can get.
> > 
> > Wild idea:
> > 
> > How about splitting out the error-reporting, with a nice default in
> > Test::Builder or wherever, using optional modules if possible?
> > 
> > use Test::More
> > tests => 100,
> > report => Test::Differences;
> 
> The two modules can already work together in the same script.  So, if
> you have Test::Differences, which has superior complex data structure
> handling, why are you calling is_deeply() in the first place?

The reason I was suggesting an automatic remapping of is_deeply() to be
eq_or_diff_data() inside Test::More is so that you can write a script
that only uses Test::More, but if you install Test::Differences, you get
the fancier output.

This would address Tatsuhiko Miyagawa's issue of wanting to minimize the
prerequisites (and thus the hassle) for CPANed modules, yet leverage
Test::Differences when needed.

A snippet of code is worth a kiloword, so this is what I mean.  First,
rename sub is_deeply to sub _is_deeply in More.pm, then something like:

eval <<'EOCODE1' || eval <<'EOCODE2' ;
require Test::Differences;
sub is_deeply {
goto &eq_or_diff_data;
}
1;
EOCODE1
sub is_deeply {
goto &_is_deeply
}
EOCODE2

or equivalent is what I mean.

Seems very DWIMmerly to me, but YMMV, of course :).

Whether or not you want to alter Test::More's API to offer pluggable
reporting modules is another question; I'm not deeply concerned about
that.

- Barrie



emitting messages in Test::*

2001-12-19 Thread Barrie Slaymaker

I noticed that Test::Builder offers the ability to emit messages with
s/^/# /mg, which is very nice.  Can/should this capability be exposed
via Test::Simple, Test::More, etc?

Sometimes it's nice to explain what to do about a test failure that may
be an intermittent failure, or to warn that they should upgrade an
optional prerequisite if one is too old, etc.

Right now I just print "# ...\n", but that seems hackish when put in the
same test scripts as the nice, shiny, new testing APIs.

- Barrie



Re: v0.3 [Was: CPAN Upload: R/RB/RBS/Test-Differences-0.2.tar.gz]

2001-12-19 Thread Barrie Slaymaker

On Mon, Dec 17, 2001 at 04:10:30PM +0900, Tatsuhiko Miyagawa wrote:
> On Sat, 15 Dec 2001 09:10:33 -0500
> Barrie Slaymaker <[EMAIL PROTECTED]> wrote:
> 
> > Now I see what you're after with the -M approach, thanks for the
> > example.
> 
> Cool.
> 
> > I can understand that :) since CPAN is/seems a non-started for a
> > significant number of folks (I have a Win32 system that it's
> > nonfuncitonal on; haven't debugged it yet).
> 
> I think Test::Differences is mainly for module developpers,

We'll have to agree to disagree; I'd rather get test failure reports
with more explanatory test output than less explanatory output.  As
Schwern points out, there's always the t/lib/Test/Differences.pm, use
lib "t/lib"; approach if you want to make their lives easier.  That's a
bit more work on your part (ie keeping up with Test::Difference
releases), and I can't blame anyone for not wanting more work :).

> not for module users, thus the necessity for Test::Differences would
> be better optional in distributing modules.

I don't want to get in the business of overloading every future Test::*
module's ok() (from Test.pm) and is_deeply() (from Test::More)
equivalent.  So I going to have to suggest that you do something like
(tested):

use Test;
eval "use Test::Differences";

sub my_ok {
goto &eq_or_diff if defined &eq_or_diff;
goto &ok;
}

plan tests => 1;

my_ok "a", "b";

That preserves line number reportage and gives you the flexibility you
desire without the maint. hassle of tracking Test::Differences'
releases.

I've added this to the docs, thanks for pointing out the need.

- Barrie



Re: [PATCH] Re: emitting messages in Test::*

2001-12-19 Thread Barrie Slaymaker

On Wed, Dec 19, 2001 at 12:20:35PM -0700, chromatic wrote:
> On Wed, 19 Dec 2001 05:12:05 -0700, Michael G Schwern wrote:
> 
> > Its been on the TODO list to toss a diag() into Test::More.
> > 
> > ok( ... ) || diag(...);
> > 
> > for some reason I keep putting it off.
> > 
> > Test::Simple won't get one, it would double the size of the API! ;)
>  
> Something like this?  diffing against a directory tree is odd... there must be
> a better way.

diff -Naur old-dir new-dir works here, but only if both directory trees
are pristine.

Now that I've got Diff::Text out the door (though a bugfix release is
headed out soon), perhaps a program that uses File::Find and Diff::Text
while ignoring binary files, things matching MANIFEST.SKIP, and editor
droppings wouldn't be a bad thing.  Oh, for a mass injection of free
time...

Looks nice to me (not that I have anything to do with Schwern's modules
:), but I think it needs to be in Test::More instead of Test::Simple.

- Barrie



Re: [PATCH] Re: emitting messages in Test::*

2001-12-21 Thread Barrie Slaymaker

On Wed, Dec 19, 2001 at 04:11:00PM -0500, Barrie Slaymaker wrote:
> 
> Looks nice to me (not that I have anything to do with Schwern's modules
> :), but I think it needs to be in Test::More instead of Test::Simple.

Sorry, misread the patch (gah, need a vacation).

- Barrie



Fwd: CPAN Upload: R/RB/RBS/Test-Differences-0.411.tar.gz

2001-12-21 Thread Barrie Slaymaker

This fixes a bug or two and improves readability by removing the middle
column of indexes if and only if it is identical to the first column and
by performing selective whitespace excaping to highlight differences in
whitespace (see below).

- Barrie

t/99example1..3
not ok 1 - differences in text
# Failed test ((eval 2) at line 14)
# +---+++
# | Ln|Got |Expected|
# +---+++
# |  1|this is line 1  |this is line 1  |
# *  2|this is line 2  |this is line b  *
# |  3|this is line 3  |this is line 3  |
# +---+++
not ok 2 - differences in whitespace
# Failed test ((eval 2) at line 20)
# +---+--+--+
# | Ln|Got   |Expected  |
# +---+--+--+
# |  1|indented  |indented  |
# *  2|indented  |\tindented*
# |  3|indented  |indented  |
# +---+--+--+
not ok 3
# Failed test ((eval 2) at line 22)
# ++-++
# | Elt|Got  |Expected|
# ++-++
# *   0|bless( [ |[   *
# *   1|  'Move along, nothing to see here'  |  'Dry, humorless message'  *
# *   2|], 'Test::Builder' ) |]   *
# ++-++
# Looks like you failed 3 tests of 3.



Re: Alternative code review ideas?

2002-01-30 Thread Barrie Slaymaker

On Wed, Jan 30, 2002 at 02:24:59AM +0900, Tatsuhiko Miyagawa wrote:
> Recently I've been doing this with two ways:
> 
> 1) Unit testing for "Model/Control" classes

*nod*

> 2) Acceptance Testing with Live HTTP, DB Server
> 
> We've acomplished with following tools:
> 
> * shell script, to setup/teardown local database

If anyone's interested, I automated this for MySQL using a bit of XML,
source is at 

   http://slaysys.com:81/src/DBML-0.1.tar.gz

No other database drivers have I written, but it's written to be
pluggable.

I'd be glad to collaborate and grow/rewrite that.  Found it quite handy
to write a module test for DBI query wrapper objects with

DBML->deploy( $initial_db_schema, mode => "test" );

to create a complete DB instance from scratch with extra test data in
addition to normal seed data.

> Writing tests with these tools is a little messy. I think I should
> use HTTP::TestEngine / RoboWeb or something like that to reduce my
> work. But I've not given a shot to 'em.

Looking forward to doing that too meself, one day...

- Barrie



[ANNOUNCE] Test-Differences 0.43

2002-05-13 Thread Barrie Slaymaker

As part of a much more detailed email about some cool code he's writing,
Yves Orton <[EMAIL PROTECTED]> wrote (in part):
> 
> my ($ar,$x,$y)=([]);
> $ar->[0]=\$ar->[1];
> $ar->[1]=\$ar->[0];
> $x=\$y;
> $y=\$x;
> 
> Test::Differences::eq_or_diff($ar,[$x,$y]);
> 
> Outputs:
> 
> not ok 1
> # Failed test (D:\Perl\Scratch\tmbug.pl at line 12)
> # ++---+---+
> # | Elt|Got|Expected   |
> # ++---+---+
> # *   0|SCALAR(0x1abf1b8)  |SCALAR(0x1de7d18)  *
> # *   1|SCALAR(0x1abf1f4)  |SCALAR(0x1bb9864)  *
> # ++---+---+
> 
> Oops, it didn't recognize that this is a complex data structure.  Never 
> mind, we can work around this by wrapping the two items in anonymous hashes:

And so Test::Differences 0.43 was born.  If you're using
Test::Differences to compare complex data structures, 0.43 fixes this
serious bug.

- Barrie



[ANNOUNCE] Test-Differences-0.45, Text-Diff-0.34

2002-07-14 Thread Barrie Slaymaker

Test-Differences-45 is now out with the below patch.

Also: I released a new Text::Diff, 0.35 (which Test-Differences-0.45
requires) that fixes and improves the escaping logic so that "\t" and
"\\t" are escaped properly ("\\t" was not being escaped properly) when
escaping.

Escaping (still) is only done in Table style diffs, which is used by
Test::Differences, and is done to highlight differences in whitespace.
Escaping harms readability, so it is normally only done when whitespace
differs:

   +--+--+--+
   |  |demo_ws_A.txt |demo_ws_B.txt |
   |  |Fri Dec 21 08:36:32 2001  |Fri Dec 21 08:36:50 2001  |
   +--+--+--+
   | 1|identical |identical |
   * 2|spaced in |also spaced in*
   * 3|embedded space|embeddedtab   *
   | 4|identical |identical |
   * 5|spaced in |\ttabbed in   *
   * 6|trailing spaces\s\s\n |trailing tabs\t\t\n   *
   | 7|identical |identical |
   * 8|lf line\n |crlf line\r\n *
   * 9|embedded ws   |embedded\tws  *
   +--+--+--+

I plan to add an AUTOESCAPE => 1 option for unified, context, and
oldstyle diffs to allow this behavior to be enabled there, but that
takes more tuits than I have at the moment.

- Barrie

On Sat, Jul 13, 2002 at 08:37:29PM +0400, Ilya Martynov wrote:
> 
> Barrie,
> 
> I've noticed that you use wrong Data::Dumper variables. See patch for
> fix.
> 
> diff -u -r Test-Differences-0.43-orig/Differences.pm 
>Test-Differences-0.43/Differences.pm
> --- Test-Differences-0.43-orig/Differences.pm   Sat Jul 13 20:34:11 2002
> +++ Test-Differences-0.43/Differences.pmSat Jul 13 20:34:31 2002
> @@ -322,11 +322,11 @@
>  if ( $dump_it ) {
> require Data::Dumper;
> local $Data::Dumper::Indent= 1;
> -   local $Data::Dumper::SortKeys  = 1;
> +   local $Data::Dumper::Sortkeys  = 1;
> local $Data::Dumper::Purity= 0;
> local $Data::Dumper::Terse = 1;
> -   local $Data::Dumper::DeepCopy  = 1;
> -   local $Data::Dumper::QuoteKeys = 0;
> +   local $Data::Dumper::Deepcopy  = 1;
> +   local $Data::Dumper::Quotekeys = 0;
>  @vals = map
> [ split /^/, Data::Dumper::Dumper( $_ ) ],
> @vals;
> 
> 
> -- 
> Ilya Martynov (http://martynov.org/)
> 



Test::Verbose && tv

2002-09-11 Thread Barrie Slaymaker

I've uploaded an alpha of this as Test-Verbose-0.000_1.tar.gz.  It's a
perl script (bin/tv) that wraps around a module (Test::Verbose).
Comments?

- Barrie

NAME
   tv - Run 'make TEST_VERBOSE=1' on one or more test files

SYNOPSIS
   $ tv t/foo.t ## make TEST_VERBOSE=1 TEST_FILES=t/foo.t
   $ tv Foo.pm  ## Run all t/*.t test scripts for Foo.pm
   $ tv t/foo.t t/bar.t ## make TEST_VERBOSE=1 "TEST_FILES=t/foo.t t/bar.t"
   $ tv t/* ## Run all test scripts in t
   $ tv lib ## Test all modules in lib

DESCRIPTION
Given one or more test scripts, Perl source code files, directories
containing them, or Perl package names, tv tries to select and run the
appropriate test scripts using "make test TEST_VERBOSE=1 TEST_FILES=..."
where the "..." are the selected test scripts.

This is especially useful in an editor when mapped to a key that saves
and runs tv on the current file or just as shorthand for a frequent but
laborious make incantation.

  Test scripts

When a test script is given as a parameter, it is selected, so

tv t/foo.t

and

tv t/*.t

do the obvious things.

When something other than a test script (a file whose name ends in ".t")
is specified, source files and test scripts are scanned to figure out
what test scripts to run.

  Source Files

If a source file name (or directory hierarchy of them) is given, then
those files and all test scripts are scanned, and any test scripts
pertaining to the named source files and any packages it defines are
selected. This allows

tv Foo.pm
tv lib/Bar/Bash.pm
cd lib/Bar; tv Bash.pm

to DWIM (see the upcoming description of how tv finds the main project
directory to see how that last one DWIMs).

  Packages

If a package name is given, then all source files and test scripts
mentioned are scanned as well as all source files in the main project
directory and its lib/ and t/ subdirectories are scanned, then any test
scripts pertaining to the named packages are selected. This allows

tv Foo

to work.

  Untestable items

It is a fatal error if a named item cannot be tested. In this case,
nothing is tested and tv prints a messages to STDERR and exits with a
non-zero exit code.

  Finding the main project directory

The main project directory is found by looking for "./t", "../t",
"../../t" and so on until a directory containing a "t" directory is
found.

  Code Scanner Details

In source files, things that look like "package" statements and some
special POD are used to infer what test scripts to run. In test scripts,
some other special POD and things that look like "use" or "require"
statements are used to infer what files and packages are being tested.
This is only performed if something other than a test script (or
directory hierarchy containing test scripts and no source files) are
given.

The special POD to be used in source files is:

=for test_script foo.t bar.t

and for test scripts is

=for file Foo.pm lib/Bar.pm

and

=for package Foo

The "=for" paragraphs may span more than one line and define whitespace
separated lists of items. The filenames in the "=for file" directive
must be relative to the main project directory and not contain ".."
names.

The scanning for "use", "require", and "package" statements is quite
naive, but usually sufficient. Things like POD documentation and
multiline strings can fool the scanners, but this is not usually a
problem.

OPTIONS
-n, --dry-run, --just-print, --recon
    Print out the make command but don't run it.

-h, -?, --help
Print out full help text (this page).

See Test::Verbose for details.

COPYRIGHT
Copyright 2002, R. Barrie Slaymaker, Jr.  All Rights Reserved.

LICENSE
You may use this under the terms of any of the BSD, Artistic, or GPL
licenses.

AUTHOR
Barrie Slaymaker <[EMAIL PROTECTED]>




Re: Help spreading Test

2002-09-19 Thread Barrie Slaymaker

On Fri, Sep 13, 2002 at 07:22:04AM -0700, David Wheeler wrote:
> On Friday, September 13, 2002, at 06:25  AM, Johan Vromans wrote:
> 
> >Tchk. I think it's quite nice and powerful to be able to download an
> >arbitrary module's .tar.gz and get it going with the simple "perl
> >Makefile.PL; make all test; sudo make install".
> 
> It seems to me that very few modules work this way any more -- most of 
> them have dependencies.

And ExtUtils::AutoInstall is meant to help module authors address that
issue.  I'm with Johan here: don't make the non-CPAN users suffer unduly.

- Barrie



[ANNOUNCE] tv (Test::Verbose 0.001)

2002-10-24 Thread Barrie Slaymaker
New! Improved! As Seen On TV!!

ahem.

tv is a command bundled with Test::Verbose that puts an easier, smarter
interface around the ExtUtils testing system.

Aside from easing debugging access (see below), the main use of tv is to
run test scripts in verbose mode, either by naming them or by naming a
source file, like Foo.pm, and letting tv find the appropriate test
scripts to run.  This means you can run something like

 :!tv %
 
from your vi flavored editor to test the file your currently editing,
whether it's a test script or a Perl module. (note: gvim, at least,
replaces the % with the path to the current buffer's filename).

http://search.cpan.org/author/RBS/Test-Verbose/bin/tv

It's been many years since I used emacs much, but

  M-x eval-expression RET
  (defun tv-buffer() (interactive "*") (shell-command (concat "tv " 
buffer-file-name)))RET
  M-x global-set-key
  C-x t tv-buffer RET

seems to map the Cx-t command to run the tv command appropriately.
Thanks to for helping me figure that out.

When passed the name of a perl source module, tv will run it through
podchecker andperl -Ilib -cw $module_name   before running the "make
test" for it.  The former is to prevent POD errors, the latter gives you
immediate feedback because "make test" can take a while to build blib on
larger distributions.  Yes, the -Ilib assumes that you keep all modules
under lib as I do (there are several reasons to do that, tv's just
adding one more :).  tv can be patched in the future  to make that more
flexible.

Anyway, tv allows you to run test scripts explicitly:

 $ tv t/foo.t # make test TEST_VERBOSE=1 TEST_FILES=t/foo.t
 $ tv t/foo.t t/bar.t # make test TEST_VERBOSE=1 "TEST_FILES=t/foo.t t/bar.t"
 $ tv t/* # Run all test scripts in t

or based on a module:

 $ tv lib/Foo.pm  # Run all t/*.t test scripts for Foo.pm
 $ tv lib # Test all modules in lib

When passed a name like *.pm or *.pl, tv looks at the "use" and
"require" lines in the test scripts to figure which to run.  If this
scanning is insufficient, it also supports a POD directive in the source
file (Foo.pm, say):

 =for test_scripts t/foo.t

and in the test scripts

 =for file lib/Foo.pm # in honk.t lets  tv Foo.pm  find honk.t

 =for package Foo::Baz# in woof.t lets  tv Blah.pm  find woof.t
  # if Blah.pm declares package Foo::Baz

So far there's no way to defeat the scan, either by disabling it or
partially cancelling it out, but that can be added if necessary.

To run things in the debugger:
 
 $ tv -d t/foo.t  # turn on the debugger in NonStop mode
 $ tv -dd t/foo.t # turn on the debugger and stop (like perl -d)

(the -d is meant to be used in conjuction with $DB::single=1 or your
friendly neighborhood interrupt key, since you usually want to stop in
the code under test, not in the test suite).

If it can't find any tests, 

 $ tv --ext-utils # Don't use make, use ExtUtils::Command::MM directly

We now return you to your regularly scheduled broadcast.

- Barrie



Graphically depicting coverage vs. test results

2002-12-10 Thread Barrie Slaymaker
Here's an interesting way of depicting the statements that are likely
to have cause test failures:

http://www.cc.gatech.edu/aristotle/Tools/tarantula/

Tarantula displays each source code statement using color models
that reflect its relative success rate of its execution by the test
suite. Roughly, statements that are executed by a failed test case
become more red, and statements that are executed by a passed test
case become more green.

- Barrie



[RFC] Module::Husbandry

2002-12-20 Thread Barrie Slaymaker
Part of QA is defining best practices.  I've been encoding a few
operations I use a lot when writing new perl module distributions in to
script form to make my code and POD more consistent.  Here's a
prerelease of them:

http://users.telerama.com/~rbs/src/Module-Husbandry-0.0001.tar.gz

and the README is below.

Feedback?

Thanks,

Barrie


README for Module::Husbandry

ALPHA CODE ALERT: This code is alpha; the API and behaviors are
likely to change.  This release is for evaluation and feedback;
see the TODO file for some ideas of where this might go.

A module and a set of wrapper scripts that let me manage perl
distributions a bit more easily.  There are more to come; the current
crop is:

newpmdist  Creates a new distribution tree and populates it
newpm  Creates a new module in a distribution
mvpm   Renames a module and all occurences of its module name
   and path:

   s{Foo::Bar}{Foo::Bat}g;
   s{lib/Foo/Bar.pm}{lib/Foo/Bat.pm}g;
   s{t/Foo-Bar.t}{t/Foo-Bat.t}g;

To use the new* scripts, you need a ~/.newpm/ directory with appropriate
templates (see below).  mvpm just makes some rash assumptions (also see
below) about your directory structure and test script naming convention.

Here are the usages:

newpmdist Foo-Bar## Create Foo-Bar/ and populate it
newpmdist Foo::Bar   ## as above


newpm Foo::Bar   ## Create lib/Foo/Bar.pm and t/Foo-Bar.t
newpm lib/Foo/Bar.pm ## Create lib/Foo/Bar.pm and t/Foo-Bar.t
newpm lib/Foo/Bar.pod## Create lib/Foo/Bar.pod only

newpm Foo::Bar Foo::Bar  ## as above, but for multiple modules


mvpm From::Module   To::Module# Use module names
mvpm lib/From/Module.pm lib/To/Module.pm  # or paths from main project dir
mvpm lib/From/Module.pm To::Module# or mix and match

mvpm -r FromTo# move dir tree (TODO)
mvpm -r lib/Fromlib/To# move dir tree (TODO)

As you can see, each can take a module name, if that's the way you
work, or a file or directory name.  Using file or directory names lets
you take advantage of your shell's autocompletion and history features.
For instance:

$ newpm lib/Fundingulus/Maximus.pm
$ edit !$

can be typed in a lot fewer keystrokes than

$ newpm Fundingulus::Maximus
$ edit lib/Fundingulus/Maximus.pm

newpmdist and newpm use a set of templates to instantiate new files.
These are stored (for now) in ~/.newpm:

$ cd ~/.newpm && find .
.
./Template.t
./Template.pm
./skel
./skel/MANIFEST.SKIP
./skel/Makefile.PL
./skel/t
./skel/CHANGES

This means that you control what files are populated how.  Some
example files (those) are in newpm_example_dir/ in the source tarball.

ASSumptions
===

These tools make the assumption that you use a working directory
structure like:

Foo-Bar/
lib/
Foo/
Bar.pm
Bah.pm
Bat.pm
Zed.pm
t/...

and not the Foo-Bar/Bar.pm style promulgates by h2xs.  This layout
(storing all .pm and .pod files under lib/) is more consistent and
flexible than storing the .pm and .pod files in the main directory,
but may not be to your liking.  Patches welcome :).

One side effect of this is that XS modules are may not be
well supported.

newpm and mvpm also create and check for test suites named after the
module like so:

Foo   t/Foo.t
Foo::Bar  t/Foo-Bar.t

.  This is also arbitrary, and even I don't really like it that
much, but it's the easiest way I could think of to be able to make
and rename test files automatically.


Example
===

Here's an example newpmdist invocation.  Towards the end, newpmdist
also does a newpm, so you can get a feel for what that's like (all lines
but the first are emitted by newpmdist):

$ newpmdist Foo-Bar
newpmdist$ mkdir -p Foo-Bar
newpmdist$ chdir Foo-Bar
newpmdist$ install Makefile.PL
newpmdist$ install MANIFEST.SKIP
newpmdist$ install CHANGES
newpmdist$ install lib/Foo/Bar.pm
newpmdist$ mkdir -p lib/Foo
newpmdist$ install t/Foo-Bar.t
newpmdist$ mkdir -p t
newpmdist/usr/local/bin/perl Makefile
Checking if your kit is complete...
Looks good
Writing Makefile for Foo::Bar
newpmdist$ chdir ..

Here's what things look like after all that:

$ cd Foo-Bar
$ find .
.
./Makefile.PL
./MANIFEST
./MANIFEST.SKIP
./CHANGES
./lib
./lib/Foo
./lib/Foo/Bar.pm
./t
./t/Foo-Bar.t
./Makefile
$ perl Makefile.PL
Writing Makefile for Foo::Bar
$ make distcheck
/usr/local/bin/perl "-MExtUtils::Manifest=fullcheck" -e fullcheck
$ make test
cp lib/Foo/Bar.pm blib/lib/Foo/Bar.pm
PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" 
"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t

Re: [RFC] Module::Husbandry

2002-12-20 Thread Barrie Slaymaker
On Fri, Dec 20, 2002 at 08:17:16AM -0500, darren chamberlain wrote:
> * Barrie Slaymaker <[EMAIL PROTECTED]> [2002-12-20 04:05]:
> > Part of QA is defining best practices.  I've been encoding a few
> > operations I use a lot when writing new perl module distributions in
> > to script form to make my code and POD more consistent.
> 
> This is great.  I keep meaning to do something like this myself, get
> about halfway there, and then end up doing something else.  Good work.

Me too.  I finally got snorked at it and pushed it over the top.

> I'd use something like _skeleton.pm and _skeleton.t for
> [the template files]

Good point.  >>TODO

Probably "default.pm.template" or something.  I specifically resisted
the urge to use TT2, it's a cheesy s/<%...%>// thing, but I'd like to
make the templating system pluggable so folks can use their own, in
which case the final extension can be used to select it:

default.pm.tt2
apache.pm.mason

or something.

>   - the ability to choose different Template.pm

Good idea >>TODO.

I also want to be able to load a template and have it declare
(implicitly or explicitly) options so you could take the same template
and make it insert extra code, like default.pm would normally
instantiate a simple module, but could be cajoled in to instantiating as
a class (ie with new() and some POD for methods, perhaps an @ISA chunk
or whatever):

$ newpm Foo::Bar --class --isa=Camel::Jockey

I've kludged code to peer in to TT2 templates to get at [%META%]
declarations (it does not allow this by default AFAICS, surprisingly, I
had to grovel through the template object's guts for meta info), and
this has proven to be a useful way to let a template declare features or
request certain preprocessing functions, like options parsing :).

> Overall, it looks very good.  When's the release party?  :)

This is it, bub ;).  The URI I gave was to a real, live tarball.  I'll
at least fold in your ideas before it leaves alpha status.  Probably
over the holidays.

- Barrie



Re: [RFC] Module::Husbandry

2002-12-20 Thread Barrie Slaymaker
On Fri, Dec 20, 2002 at 09:12:09AM -0500, darren chamberlain wrote:
> * Barrie Slaymaker <[EMAIL PROTECTED]> [2002-12-20 08:52]:
> > I've kludged code to peer in to TT2 templates to get at [%META%]
> > declarations (it does not allow this by default AFAICS, surprisingly,
> > I had to grovel through the template object's guts for meta info), and
> > this has proven to be a useful way to let a template declare features
> > or request certain preprocessing functions, like options parsing :).
> 
> Oh, that's a pretty straightforward (though completely undocumented) one:

heh, it's not straightforward if it's undocumented.  Yessirree, that's
my motto.

> You can call:
> 
>   my $foo = $d->foo();
> 
> and get 'bar'.

Thanks for the tip, that's a beaut I'll use.  Any chance of you sending
a docs patch to the TT2 folks?

- Barrie



[OT] TT2 docs

2002-12-20 Thread Barrie Slaymaker
On Fri, Dec 20, 2002 at 09:54:50AM -0500, darren chamberlain wrote:
> 
> The docs for Template::Provider state:
> 
>   fetch($name)

fetch()ing's the easy part.  Even *I* got that far long ago.  It's the
fact that you can coax metadata out of the template objects with
AUTOLOADed methods that I didn't see in the docs (not that I've seen
every bit of the docs, but it didn't leap out at me).

I also have not yet tried to see what happens if you go to fetch
metadata that a template doesn't happen to declare.

- Barrie