Re: ANNOUNCE: Pod::Coverage
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
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?
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?
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
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]
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]
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]
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]
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::*
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]
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::*
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::*
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
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?
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
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
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
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
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)
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
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
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
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
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
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