Just A Summary

Piers Cawley Practices Punditry

Test::Class::Sugar 0.3, no, 0.4

Posted by Piers Cawley Thu, 05 Nov 2009 02:12:00 GMT

tap tap… Is this thing on?

So, I recently noticed that Test::Class 0.33 got released, which means that Test::Class::Sugar no longer needs to depend on a development release, and I also noticed that it was embarrassingly easy to throw Test::Class::Sugar into an infinite loop by forgetting which way the >> goes when you want to specify the number of subtests in a test method.

So, I’ve done a quick fix of the infinite loop problem as well and uploaded version 0.3 to PAUSE, so now you can write your tests like:

testclass exercises ClassUnderTest {
    test creation of the class under test {
        lives_and {
            isa_ok ClassUnderTest->new, $test->subject;
        }
    }
    ...
}

without having to jump through the hoops of downloading a development version of Test::Class or worry about accidental infinite loops…

Next up, fix the syntax to either allow both << and >> as test count specifiers, or come up with a more memorable way of separating the count from the test name.

Update:

Shortly after I released 0.3, Joel Bernstein asked if I’d be interested in a topic branch to make Test::Class::Sugar work with perl 5.8.

“Of course!” I said.

One day later, there it was. Thank you to Joel and to his employers, NET-A-PORTER for sponsoring his work. So now, Test::Class::Sugar 0.4 is winging its way to CPAN and now I have no excuse for not using it at work.

Test::Class::Sugar released 2

Posted by Piers Cawley Mon, 06 Apr 2009 05:15:00 GMT

I’ve just pushed the second version of Test::Class::Sugar (first discussed here). It’s pretty much as discussed in the original article, but after some discussion with David Wheeler, I’ve dropped the +uses clause from the testclass declaration in favour of less DWIMmy (and thus easier to explain behaviour).

I’ve also introduced a defaults argument at use time. The only working default in this release is one which lets you specify the prefix used to derive the test class name from the class/module under test. I’ve documented a couple of extra and so far unimplemented defaults as well.

Have a play, you might like it.

Thinking about the virtues 3

Posted by Piers Cawley Sun, 15 Mar 2009 02:19:00 GMT

I got a bit of stick on IRC last night for some of the choices I’d made when I was writing Test::Class::Sugar, in particular because one of the prerequisites is chromatic’s handy and opinionated Modern::Perl module. The ‘controversial’ aspect of Modern::Perl is that, when you use it, your code won’t run on any Perl before Perl 5, version 10.

The thing is, I don’t care about older perls any more. Version 10 features like ~~ and // are too convenient to fart about writing circumlocutions just to run on a version of Perl that I have no intention of ever using again.

Actually, that’s not quite true, those version 10 features are too convenient for me to fart about working around their absence. If you think that a module I write is useful enough that you want it to work on version 8, then of course I’ll accept your patch. But don’t be surprised if, when I start adding new features, I break the backward compatibility.

Also, on the happy day that version 10.1 escapes the pumpking patch, I’ll be setting that as my minimum perl version even if chromatic doesn’t bump the version number in Modern::Perl.

It’s all about the virtues

Your context is different from mine. I’m writing in Perl again for my own amusement more than anything. There are developments in modern Perl – tools like Moose and Devel::Declare – that I think are exciting and important. The Announcements project I started was as much about playing with the new tools as it was about trying to write something of wider utility. Test::Class::Sugar arose as a direct result of attempting to write Announcements and the desire to write test classes without hoopage. My principle drive then, is impatience to get Test::Class::Sugar to the point where I can get back to writing Announcements.

But then laziness and hubris kick in. So the code needs some polish. The parser and the code generator need to be disentangled, I need to get Adrian Howard to apply the little patch I had to make to Test::Class. Laziness demands I document it.

Impatience tells me to lean on the features of modern perl – that way I can get back to being a user of the new library as quickly as possible. Laziness tells me that I’m not going to need backwards compatibilty. Hubris tells me my work is good enough that someone who does will like it enough to send me a patch.

Everybody wins.

Magic vs Mundane: Keeping them apart

Posted by Piers Cawley Fri, 13 Mar 2009 08:40:00 GMT

In which your correspondent does magical battle with the guts of Perl and emerges bloodied, but unbowed with a useful principle to code by.

Skip to the conclusion if you’re uncomfortable with the guts of the Perl runtime

Test::Class had me tearing my hair out earlier. There I was, happily transforming

test something {
  ok 1;
};

into something very like1:

*test_something = 
  Sub::Name::subname(
      'test_something' 
    => sub : Test { ok 1 }
  );

through the magic of Devel::Declare, but Test::Class didn’t seem to be playing fair. Instead of letting my tests run happily, it was complaining that it:

cannot test anonymous subs – you probably loaded a Test::Class too late (after the CHECK block was run). See ‘A NOTE ON LOADING TEST CLASSES’ in perldoc Test::Class for more details

The thing is, I wasn’t loading Test::Class too late. The problem is that, at the point I applied the Test attribute to my sub, the sub didn’t have a name and, because of the constraints you’re operating under when you’re using Devel::Declare to do code transformation, there was no obvious way to give it a name in time.

Incompatible magics

The trouble is, Test::Class does what it does through the magic of compile time code attributes, and, further, it relies on the fact that if a perl subroutine that gets inserted into the symbol table like this:

sub has_a_name {...}

Then, when you get hold of a reference to that code by other means (say, in the subroutine that handles the setting of an attribute, that code ref knows its own name. However, if a subroutine that ends up in the symbol table like this:

*anonymous_ref = sub {...};

Doesn’t know its name, unless you take advantage of the Sub::Name module.

So, in my generated code, I was giving my coderef a name, but it was happening to late. At the point that Test::Class::Test method was seeing the coderef, the coderef was anonymous.

My magic and Test::Class’s magic were incompatible.

The thing is, both sorts of magic are really just sugar for some pretty mundane donkey work. Test::Class does what it does through attributes because no flesh and blood programmer in their right mind would want to write something like this every time they wanted to write a test method:

sub test_something {
  ...
}
__PACKAGE__->mark_as_special_method('test_something', 'test', '3');

In fact, mark_as_special_method doesn’t even exist as its own subroutine. The code that marks a method as special is just part of the body of the Test attribute handler.

Conclusion

Which brings me neatly to my conclusion.

When you’re designing a module that does anything magical, consider starting with a mundane core API that handles the business side of things. Then layer your magic on top of that API. Then document the API and the magic. Obviously the magic bits go up front in the docs, and the API goes in its own section (or even podfile) down at the bottom, where only eejits like me, who want their magic to work slightly different to yours, will bother reading it.

Obviously, I’m motivated by an issue I’m having with a particular module from CPAN, but the principle of separating the magic and the mundane is applicable everywhere. It’s called Separation of Concerns, or The Single Responsiblity Pattern. I call it a Just Story.

You’ll find the pattern in well designed websites that are using unobtrusive javascript to wave an AJAX wand over the site. You’ll see it woven through books like The Structure and Interpretation of Computer Programmers – where it’s called an Abstraction Barrier.

Patches sent

It turns out to be very easy to add mark_as_special_method (though I actually wrote it as ‘add_testinfo’ in the patch) to Test::Class. It’s about as straightforward an Extract Method refactoring as I’ve ever done – even without automated tools, I managed not to fuck it up. There’s a patch in Adrian Howard’s inbox, and I’m hopeful that it’ll be applied soon.


1 Not exactly – that’s the result of calling the shadowed test subroutine which was the result of the code transformation.

Check out the osfameron fork of Devel::Declare for the beginnings of some decent documentation which explains what’s going on.

Writing parsers for fun and convenience 4

Posted by Piers Cawley Wed, 11 Mar 2009 22:29:00 GMT

One aspect of coming back to Perl for ‘recreational’ programming is that if, like me, you’ve declared war on @_ and boilerplate code, then testing can be somewhat trying. The Perl testing framework that best fits my head is Test::Class, which is an excellent Perlish implementation of xUnit style testing. If you’re unfamiliar with the, library, Ovid is writing what’s shaping up to be an excellent series of introductory articles about it at http://www.modernperlbooks.com/.

The problem I’m having with Test::Class at the moment is that I can’t write:

use MooseX::Declare
class Test::Person
  extends Test::Class
{
  use Test::Most;

  method class_under_test {'Person'}
  
  method startup : Test(startup => 1) {
    use_ok $test->class_under_test
  }

  ...
}

Test::Class is doing too much in its initialization phase, and relies too heavily on code attributes, for it to play well with MooseX::Declare. Drat.

On reflection though, this might be a good thing, because maybe MooseX::Declare isn’t really what’s needed. What I’d like to write is something like:

use ...;

testclass Test::Person
  exercises Person
{
  startup class under test should be usable (1 test) {
    use_ok $test->class_under_test
  }
}

And have the library ‘…’ expand the testclass declaration into something that looks like the first code snippet. After all, if MooseX::Declare can work without source filters, it should be possible to come up with something nicely declarative for specifying test classes.

Obviously, there’s nothing on CPAN that does this yet though. So I went fossicking through MooseX::Declare to see how it works1 and discovered thing of Lovecraftian beauty that is…

Devel::Declare

Devel::Declare is possibly the most hostilely documented library I’ve ever come across. Its documentation only begins to make sense when you already understand enough about how it works that you don’t really need the docs. What it does is to let you declare your own Perl keywords. You could, for instance use it to introduce given/when into versions of Perl that don’t have it yet. You declare your keywords and associate them with parsers. When, during its compilation phase, perl hits one of your keywords in the right context, it hands off to your parser which can then do what the hell it likes in the way of code transformation, before handing control back to Perl, which then parses the transformed code as if that was what was there all along.

So, to want to transform that testclass syntax I just pulled out of my ass into a real Test::Class package, I just need to write an appropriate parser and code generator, perform the appropriate Devel::Declare incantations, and I’m laughing.

Making progress

So far, I’ve got to the point where I have a working testclass keyword, but nothing yet for the ‘inner’ bits (setup, test, teardown, etc). I can write:

testclass Test::Person
  exercises Person
{
  ...
}

testclass Test::Person::Employee
  extends Test::Person
  exercises Person
{
  ...
}

and, as I write this, I’m realising that the syntax I’d cooked up for using extra test helper modules:

testclass AnotherTest
  helpers -More, -Exception, Carp
{
  # use Test::More;
  # use Test::Exception;
  # use Carp;

  ...
}

would probably read better as:

testclass AnotherTest
  +uses Carp
{
  # use Test::Most;
  # use Carp;

  ...
}

and also that I want this:

testclass exercises Person {
  ...
}

to build me a Test::Person class.

What’s still blowing my mind about Devel::Declare’s possibilities is that I’m no longer constrained to writing a Domain Specific Pidgin which works by building a tower of proxy objects and weird evaluation contexts to produce something that’s legal code in the host language, but which has the feel of another language. With Devel::Declare, I control the horizontal and the vertical until I choose to hand control back to Perl. Right now that means my error reporting is disgracefully bad, but it also means that I can roll a syntax that makes sense without worrying about how I’m going to get perl to parse it.

One of the things I find frustrating about writing RSpec specifications is that describe and it both want to be first class keywords – it feels like you should be able to write:

describe SomeClass, "in some context"
  before each
    # set things up
  end
 
  it "should do something or another"
    ...
  end
end

But, because RSpec works by taking advantage of Ruby’s block magic, you have to write:

describe SomeClass, "in some context" do
  before :each do 
    # set things up
  end

  it "should do something or another" do 
    ...
  end
end

I definitely prefer the version without the extraneous dos and the gratuitious : before each in the before declaration. Does anyone feel like writing devel/declare.rb?

Show us the code!

If you want to see the current state of my Test::Class::Sugar art, the place to look is http://www.github.com/pdcawley/test-class-sugar. At the time of writing it relies on http://www.github.com/rafl/devel-declare and doesn’t have anything so useful as documentation, a Makefile.PL or even any tests beyond the collection of code samples that is t/initial.t. Expect all those when and if I push it to CPAN.

Caveats

Yes, I know that this sort of metasyntactic abstraction is trivial in a Lisp. I just happen to like syntax, okay?

Update 20090312

use Test::Class::Sugar

testclass exercises Foo 
    +uses -Warn
{
    ...
}

Now generates

{
  package Test::Foo;
  use base qw/Test::Class/;
  use Test::Most;
  use Test::Warn

  ...
}

So that’s one hurdle jumped. And I now know how to write the various method helpers and, when I get the appropriately shaped tuits, I shall actually write the damned things.

Then all I have to do is document it.

And write up a proposal about it for YAPC::Europe.

Update 20090314

I now know what a plan looks like:

test with multiple assertions &lt;&lt; 3 {...}

And, more importantly, I’ve implemented, and documented everything and am almost good to cut a 0.001 distribution. I need a few ducks up on CPAN, but once that’s done, we’re good and I can get on with parameterizing some of the assumptions that are hard coded at the moment.

1 Something I swore blind I wasn’t going to do in my London.pm presentation. Seems my word isn’t to be trusted…



Just A Summary