Organizing Perl Test Files

As the Testing section of the Modern Perl book tries to explain, Perl tests are just Perl code. Sure, the libraries built on top of Test::Builder extend your testing toolbox by providing new functions to help you write tests, but tests are just code.

The first implication of that statement is that, if you know how to write code, you can write tests.

The second implication of that statement—one which takes longer to realize—is that test code has maintenance costs just like code code does.

I like using Test::Class and Test::Routine when they make sense, but some tests are easier to write when they start with a little less ceremony. (I also like to refine and reorganize my tests when better organization suggests itself.) In those cases, I start with something simpler:

#!/usr/bin/env perl

use Modern::Perl '2013';

use Test::More;

use lib 't/lib';

exit main( @ARGV );

sub main {
    my @args  = @_;


    return 0;

Every set of test assertions I can collect into a named group is a function. (You can even use Test::More subtests if you like.) When a function gets too long—when I can come up with a new name for a subset of the behavior under test—it's time for a new function.

(I write exit main( @ARGV ); as the first non-pragma line of the program so that there are no order-of-initialization concerns from Perl's compile-time/run-time distinctions. If that means nothing to you, carry on; it's a subtle thing that almost never causes problems.)

Grouping everything under functions also has the benefit of reminding other developers that it's okay to write more functions. For example, if every test for every action in a controller ought to verify access permissions, it's easy to write a helper function to set up an environment with and without access permissions to test both ways. (Some of these test functions get promoted to project-specific test libraries.)

I suspect that the discipline of writing test files as if they were code, not just scripts, is that it provides a subtle pressure to continue to write tests as if it were code, with all of the discipline and factoring and maintenance work that implies. It's easier to take something a little messy and make it a lot messier, but for me at least it's nice to start with something clean and leave it at least that clean. (This is probably why dishes pile up in my office when the dishwasher needs to be emptied.)

Please note that these test names do not necessarily correspond to individual methods or functional units within the code under test. That is, just because I might have a method called analyze_country_performance_metrics(), I don't have a single test function to test that method. I might have several. I might have none (if other code tests it adequately). Each test function tests a single, coherent, nameable feature, like "editing a user account with invalid data" or "exporting person search to CSV".

This is subtle, but it's important. Think in terms of features you can discuss with end users. (Perhaps that means I find Test::Class and its friends more useful for unit-style testing.) This helps you navigate your way through the test suite and your issue tracker by giving everyone canonical names to describe tests.

A little structure is valuable. It's easy to set up and to maintain. Yes, there's a little bit of duplication in calling functions and declaring them, but the benefit of navigation and nomenclature outweigh that many times over. The specific structure of your test files doesn't matter as much as that structure exists and you take advantage of it.

(It also lets you run test functions individually as you're fixing bugs or adding features, but the mechanics of that are the subject of another post.)

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 May 6, 2013 6:00 AM.

SEO Tips for Perl Advocacy was the previous entry in this blog.

Running Named Perl Tests from Prove 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?