Five Test::More features you might not be using yet

I've been using Test::More for so long that I sometimes forget about new features that have been added in the last couple years. If you're like me and would like a refresher, here's a list of five useful features that you might want to start using. Unless otherwise noted, you will need at least version 0.88 of Test::More.

1. done_testing instead of no_plan

If you don't know how many tests you are going to run (or don't want to keep count yourself), you used to have to specify 'no_plan' at the start of your tests. That can lead to surprises if your tests exit prematurely. Instead, put the done_testing function at the end of your tests. This ensures that all tests actually run.

use strict; use warnings;
use Test::More 0.88;

ok(1, "first test");
ok(1, "second test");

done_testing;

2. new_ok for object creation

You used to have to create an object and then call isa_ok on it. Now those two can be combined with new_ok. It will also let you pass arguments in an arrayref to be used in the call to new.

use strict; use warnings;
use Test::More 0.88;

require Foo;
my $obj = new_ok("Foo");
# ... use $obj in testing ...

done_testing();

Changed "require_ok" to "require" per Ovid's comment, below.

3. Add diagnostics only in verbose testing

The old diag function always prints to stderr. Particularly for debugging notes, that can clutter up the output when run under a harness. You can now use the note() function to add diagnostics that are only seen in verbose output.

use strict; use warnings;
use Test::More 0.88;

note("Testing on perl $]");
ok(1, "first test");

done_testing();

4. Explain data structures in diagnostics

I often find myself wanting to dump a data structure in diagnostics, and wind up loading Data::Dumper to do that. Now Test::More can do that for you with the explain() function. The output is a string that you can pass to diag or note.

use strict; use warnings;
use Test::More 0.88;

my $want = { pi => 3.14, e => 2.72, i => -1 };
my $have = get_data();

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

done_testing();

5. Encapsulate related tests in a subtest (0.96)

use strict; use warnings;
use Test::More 0.96;

pass("First test");

subtest 'An example subtest' => sub {
  pass("This is a subtest");
  pass("So is this");
};

pass("Third test");

done_testing();

Subtests can have their own plan, but if they don't have one, Test::More acts like there was an implicit done_testing at the end of the code reference. That means you don't have to keep count of tests in a subtest and things still work safely.

You can use a 'skip_all' plan in a subtest, too, which is a useful way of constructing a SKIP block without having to count how many tests are being skipped the way you would with the skip() function.

use strict; use warnings;
use Test::More 0.96;

pass("First test");

subtest 'Like a SKIP block' => sub {
  plan 'skip_all' unless $required_condition;
  pass("This is a subtest");
  # ... many more tests that you don't have to count ...
};

pass("Third test");

done_testing();
This entry was posted in perl programming, toolchain and tagged , . Bookmark the permalink. Both comments and trackbacks are currently closed.

11 Comments

  1. Posted February 8, 2011 at 12:13 am | Permalink

    Never knew about subtest.

    ++

  2. Posted February 8, 2011 at 4:55 am | Permalink

    Great article. However, don't use "require_ok". Just require the module. Using 'require_ok' means that if the code fails to compile you'll have partially compiled byte-code in memory and subsequent tests will still run. This can lead to very mysterious subsequent test failures and bug hunting if you don't notice that it's the 'require_ok' which failed. Just "require Foo" like normal and if that fails, not only will your test program fail as expected, it won't even attempt to run any more tests.

    "use_ok", "use ok" and "require_ok" should die. They don't contribute anything.

    • Posted February 8, 2011 at 6:20 am | Permalink

      That's a good point. I think my usual pattern these days is to have one test file to see if everything compiles (which dzil gives me for free) and then I generally just use/require what I need.

      I've updated the example, since require_ok isn't what the article is about anyway.

    • Abigail
      Posted November 7, 2011 at 2:56 pm | Permalink

      I typically use use_ok in the first test file to be run. As in

      foreach my $pkg (@MODULES_IN_PACKAGE) {
      use_ok ($pkg) or BAIL_OUT ("Loading '$pkg' failed");
      }

      this has the advantage that if one of the modules fails to compile, the other tests aren't attempted.

      • Posted November 7, 2011 at 7:45 pm | Permalink

        I would recommend require_ok() for that, as use_ok() calls import(), but too late for exporting symbols and might have unexpected side effects. For a compile-only test for code you know doesn't have issues with a call to import(), it's perfectly fine to have use_ok(), but I wouldn't use it for boilerplate "does this compile?" testing.

  3. Posted February 8, 2011 at 10:02 pm | Permalink

    Thanks, I also never use subtests, but plan to organize my tests into subtests.

    • Posted November 6, 2011 at 3:58 pm | Permalink

      One of the really handy things about subtests is that you can use them to significantly speed up your test suite. So for instance, where one might have a $controller/$action.t structure for a webapp tests, $controller.t with subtests per action is sure to be much faster as it will be compiling less.

  4. Posted February 9, 2011 at 11:47 am | Permalink

    Great article David, short and concise, but it will have a huge impact on our current test base.

    Keep up the good work,

    jonasbn

  5. Posted November 6, 2011 at 3:59 pm | Permalink

    I love the note() feature, never knew about that one!

  6. yko
    Posted November 6, 2011 at 4:42 pm | Permalink

    Did not know about explain(), thanks

  7. kd
    Posted January 11, 2013 at 7:03 am | Permalink

    Nice article, and I never knew about subtests. The usage of pass() is obscure. So I wrote some code that demonstrates it a little better:


    use strict; use warnings;
    use Test::More 0.96;

    subtest 'An example subtest' => sub {
    is( 1,1, 'one is one');
    is( 1,!1, 'one is not one');
    };

    subtest 'something' => sub {
    is (0 == '', "zero is undef");
    is ('' == 0, "undef is zero");
    };

    done_testing();

One Trackback

© 2009-2014 David Golden All Rights Reserved