Test::Class versus Modern Perl OO

| 1 Comment

Three and a half years ago, my colleague Ovid wrote a series about organizing test suites with Test::Class. I've happily used Test::Class for years, for projects where reusability of test suites increased my confidence in the correctness of the code and reduced duplication in my work.

Test::Class works best when you can organize the structure of your test suite along the lines of your classes under test.

One drawback of Test::Class I've noticed lately is that it follows the so-called classical Perl style of object orientation, rather than the modern style. (The primary distinction I make between classical Perl OO and modern Perl OO is the degree of formalism in the structure of the OO system. In other words, an OO system that doesn't encourage or at least permit the use of roles is in no way a modern OO system.)

The problem is Test::Class's use of function attributes:

sub test_some_predicate :Tests {
    my $self = shift;
    ok $self->some_method, 'some_method() should return a true value';

While it's possible to use something like Role::Basic to provide roles of test assertions you can apply to your test classes, the amount of work necessary to convince Test::Class that these composed methods are part of the assertion framework is more work than I want to do.

The problem is that, in the absence of a well-defined Perl 5 metaobject protocol, Test::Class had to build its own mechanism and that mechanism turns out not to have been reusable enough with a modern Perl object system.

That's not the fault of the authors (who could have predicted this need to such a degree?), but it's another criticism of Perl 5's attributes mechanism which is tied too closely to Perl 5's rather ad hoc compilation model, which translated syntax into policy with too little regard for the user-defined semantics attached to extension syntax. To rephrase in another fashion, Perl 5's syntactic extension mechanisms work well enough within their compile-time lexical scope, but woe to you if you want to reuse them outside of that compile-time lexical scope. Perl's already moved well on by now.

I've used Test::Routine very productively in another project and may indeed migrate the test suite to the latter. In the mean time, the test suite (nascent though it may be after a week of work) does suffer a little bit of duplication and near duplication, ironically enough. A dose of multiple inheritance might solve the problem, but at some point a good designer has to ask whether the amount of abstraction required in a test suite is worth the result. Simplicity of debugging is a concern which outweighs many others.

1 Comment

Test::Class fails tests on Win32, btw.
Meaningless fail, but you will still have your module install fail, find out why, look on the test output, understand that it is insignificant, force install it, and then retry installing the original module.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide



About this Entry

This page contains a single entry by chromatic published on October 13, 2012 2:12 PM.

Emulating Dynamic Scope with Lexical Destruction was the previous entry in this blog.

Disabling Perl with an Environment Variable is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by the Perl programming language

what is programming?