How can I use Test::More and friends to automatically test inherited behavior?

138 views Asked by At

Context:

Say I have a few modules that inherit from each other (using old-school inheritance with base and parent, not Moose or similar). Foo::Bar inherits Foo, and Foo::Bar::Baz inherits Foo::Bar. All of these modules have test suites written with Test::More. The test suite for a child class only tests the methods that it implements. Child classes do not necessarily override all methods in their parents, though they may add new methods that their parent does not have.

Question:

Is there some testing framework, technique, or Test::More feature with which I can write tests that will not only test subclass-specific behavior, but will also then run test suites for any inherited behavior/parent classes as well? Basically, I'm looking for something that allows me to write tests for the unique/special behavior of a subclass, but will also test and make sure that the subclass behaves in tests the same way that its parent class(es) are expected to.

What I've tried:

I've written a very simple test harness with a generator method that builds an instance of a string-specified module and runs tests against it depending on what type of module was requested (there's a central hash that keeps track of subclass/superclass hierarchy), but this seems crude. I'm assuming that (like most things I need to do in Perl), someone else has already done this in a much more elegant and robust way.

1

There are 1 answers

0
Mike Monkiewicz On BEST ANSWER

What you're looking for is Test::Class.

You can make a test class for Foo::Bar, which I would probably call Test::Foo::Bar. This Perl module will use Test::Class as its base class. But instead of testing Foo::Bar directly, access it through a method:

sub class {'Foo::Bar'}

This allows us to override it later.

Then you make a new test class, Test::Foo::Bar::Baz which inherits from Test::Foo::Bar. By doing this, you've automatically inherited all the tests you wrote for the parent class. Of course you'll need to override class():

sub class {'Foo::Bar::Baz'}

Voila! You're now running all your tests from Test::Foo::Bar on Foo::Bar::Baz, and you're free to override or make new tests to your heart's content.

Chromatic has a thorough example on his blog: Resuing Test Code with Test::Class

And you're right about test harnesses already existing. A mixture of Test::Class, Test::Harness, and prove should take care of your needs, and there's very little reason to write your own.