Delete Low Value Tests

| 4 Comments

What's the purpose of a comprehensive test suite for your code?

It's not a trick question. The answer isn't "to get 100% coverage" or "to test every line of code". (The answer oughtn't be "because someone else said so", but if that's the best reason you have, it's better than the others.)

The reason to write and maintain a comprehensive test suite is to give you confidence that your code does what it should do and will continue to do so even as you change and modify and maintain it.

That's obvious and basic and should be a fundamental belief of anyone with a few months of practical experience writing useful tests, right? Yet I'm not sure we take the implications seriously enough.

For example:

use Test::More;

BEGIN { use_ok 'Some::Class' }

my $obj = Some::Class->new( ... );
isa_ok $obj, 'Some::Class';
can_ok $obj, 'some_method';
can_ok $obj, 'another_method';
can_ok $obj, 'still_one_more_method';

...

done_testing();

If those are the only tests you have, they're better than nothing, but if you have other tests that exercise actual useful behavior, delete these tests.

I repeat: delete them. They add little value. They're busywork. They take up space and they cost time.

Just as code has a peculiar inertia as it grows in mass, so does test code. Solving a problem in 10 lines of well-written, concise, and maintainable code is better than solving a problem in 100 lines of well-written, concise, and maintainable code, ceteris paribus.

What's the purpose of a single test predicate? To exercise some behavior of the code in a unique, isolated, and unambiguous fashion to demonstrate that it works as expected and allows you to diagnose any failures as easily as possible.

By example, if you're going to call a method as part of a test, there's little value in testing that that method exists. Call it. If it doesn't exist, you'll get an error message and tests will fail. Likewise, there's little value in using use_ok if you have further tests that require the module to have compiled fully. If you're not careful, your test suite can end up a big pile o' mess, a poorly organized dumping ground for whatever someone thought useful at the time. (It's code. Refactor relentlessly but carefully.)

(The desire for concision of expression in a test suite lies behind the existence of Test::Builder, which allows for the peaceful co-existence of hundreds of testing modules within the same program. Abstractions are possible. They exist. They work, millions of times a day.)

This isn't an excuse to skimp on your tests. By all means write great tests and cover the essential behavior of your programs completely. Do, however, keep in mind that non-essential code is a liability. Feel free to delete unnecessary, repetitive, verbose, low value tests—which neither provide diagnostic assistance nor exercise a unique property of your code.

4 Comments

except that in some cases (example testing that http server is alive) writing an actual test to check that the process is running may give you a clearer error than saying, I know stuff will fail if it isn't. I mean, is it not running or is the port blocked? use tests are of course not a great example of this.

Very true. That's a good example of specific tests helping you diagnose what has gone wrong. I like to use bailout tests when that happens: there's no reason to run more tests when one of the underlying testable assumptions has failed. This is the same reasoning for not using use_ok().

A couple of comments about this. First, I will completely agree that this is useless:

BEGIN { use_ok 'Some::Class' }

I would simply use the module as the above is broken and has been for a long time. If you use the module and the use fails, that's a *good* thing.

Second, I would argue that those can_ok() tests can provide excellent value. I'm writing code right now where I have factory classes for reading/writing data to Facebook, Google Adwords, Bing, etc., and I want to verify the interface. They implement the interface via a role, but a clever programmer could still exclude the get_keywords() method and forget to reimplement it, thus making the can_ok() tests very valuable.

Verifying an interface is very different from checking that you can call something, calling it, then checking that you called it. If you see bugs where people exclude methods from role composition, those tests have value.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

affiliated with ModernPerl.net

Categories

Pages

About this Entry

This page contains a single entry by chromatic published on March 6, 2012 11:27 AM.

Your Test Suite Needs at Least This File was the previous entry in this blog.

Loaded for Werewolf is the next entry in this blog.

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


Sponsored by Blender Recipe Reviews and the Trendshare how to invest guide

Powered by the Perl programming language

what is programming?