Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Monday February 16, 2009
07:48 AM

Explaining explain()

[ #38491 ]

On the Perl-QA list, Gabor Szabo pointed out a problem with the testing toolchain. Test::Most is advertised as a drop-in replacement for Test::More, which is was.

The problem is that Test::More has also added my explain function. explain is very handy in tests because it lets you do this:

explain $some_data;

It's like diag(), but only outputs when the tests are run in verbose mode. Thus, if you do make test, you won't see a bunch of irrelevant information dumped to the terminal. Further, it automatically calls Data::Dumper::Dumper() on references so programmers no longer curse when they see this:

# ARRAY(0x80631d0)

It's a very handy tool in testing, but Schwern was concerned that it was doing too much. What if you want to automatically expand the references, even when you're not in verbose mode? There's a great argument for this:

isa_ok $some_object, "Some::Class" or diag explain $some_object;

If there's a failure, you might want to see it right away. So in Test::More, explain just formats the data and you have to call one of the following:

diag explain $some_data;   # always appears
note explain $some_data;   # only appears in verbose mode

That covers everything. I felt that a simple explain $some_data was the common case and I wanted to optimize for that. Schwern argued that it was trying to do too much and wanted the separation of concerns. That's a very reasonable argument, but what Schwern and I both missed was what Gabor pointed out. It breaks the Test::Simple to Test::More to Test::Most upgrade path. The functions behave differently and Test::Most is no longer a drop in replacement.

So let's take this to its logical conclusion (with apologies to Schwern for this fun :)

diag() formats your data and outputs it to the diagnostic filehandle (typically STDERR). But wait! It's doing too much and we should separate the formatting from the displaying. Since we can't just print it (we need to make sure it goes to the correct handle), we do this:

output diag explain $some_data;

Oh, that fails. Because output() doesn't know if it's outputting TAP or diagnostics, we need this:

output diagnostics diag explain $some_data;

Shove a few colons in there and we can call this a DSL!

However, what we really want is respect. We want this from the Java programmers. So with some Acme::Dot love, we can do this:

Tests.output.diagnostics.diag.explain($some_data);

Now those Java programmers are going to take us seriously!

I want explain $some_data; to just work.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • … I thought the title of this entry was “Everything explain()”. The reality was a bit of a let-down. :-)

  • Something that is lost in the caricature is that by Test::Most::explain() wrapping up output and dumping you can not use explain() to output as part of a normal failure. I like to do this:

    is_deeply $have, $want or diag explain $have;

    Test::Most thinks the opposite use case is important, it's the equivalent of "note explain". If you read the docs for explain() in Test::More and Test::Most it's pretty clear we have different ideas about how it's to be used. I could have just decided which one the user get

    • You're absolutely right that my solution is not as flexible. But ...

      Years ago I worked at a company where we made revenue projections for a particular industry. Industry executives could log on and when they saw what they were trying to project, they had a "weighting" factor that they could enter and the numbers would be adjusted with that. For the sake of argument, we'll say that number defaulted to 12, but based on the executive's knowledge of what they were offering, they would adjust that up or down.

      • Yes, inertia driving design is bad. What does it have to do with this?

        • The vice president argued for a suboptimal solution because that's how things are now. Though I've got other reasons for wanting explain() to function the way it does, part of the reason to keep it the same is because that's how things are now.

          • I think it's the "But..." that made me think it was an accusation that Test::More's explain() is the result of Design by Inertia... which doesn't make any sense since Test::More can't "do it the way it was always done" for something that didn't exist. Design by Inertia would have been to do what Test::Most does.

            Are you considering changing explain() in Test::Most?

            • I wasn't planning on changing explain() in Test::Most. From what I can tell, it's now used widely enough that I'm not keen on breaking backwards-compatibility without a strong reason.

      • PS That was at R*****k, right?

      • I had a job like that. A huge commericial real estate company wanted to have all sorts of fancy graphs about prices and market conditions, but they didn't know how to do it themselves.

        It turns out prices had nothing to do with the market. They just increased monotonically. They lost interest in showing customers market data after that.

        In that case, I'd change the number back to 12, but insert a +3 somewhere else. :)