views:

220

answers:

4

What frameworks and tools would you recommend for unit-testing and mock objects in Perl?

I have an existing Perl application, that mainly does database access, reading and writing files. The application is basically a batch job type of application, it reads in bunch of stuff from files and database and writes a bunch of new files and some stuff to database.

The application currently does not have any unit-test, but I'd like refactor application to have good unit tests.

What frameworks and tools would you recommend for unit-testing and mocking objects? For example something similar to Hamcrest and JMock of Java?

Also, are there any good BDD (Behaviour Driven Development) based testing frameworks for Perl?

+3  A: 

It is not a framework, but one of the best testing books is the excellent Perl Testing: A Developer's Notebook which also has recommendations of test frameworks for Perl, e.g. Test::More.

Rob Wells
+4  A: 

In terms of test frameworks, I like to use Test::Class, which lets you set up nice unit test hierarchies in a manner similar to JUnit. The linked documentation gives a pretty good overview, though if you're not already familiar with Perl testing conventions, check out the documentation for Test::Simple and TAP, which is the standard output format for Perl tests.

For mocking, there is Test::Mock::Class, which is useful for setting up mock classes for libraries outside your direct control, like CPAN modules that your application relies on.

There is also the excellent Test::MockDBI which provides special facilities for mocking your database stuff.

friedo
Test::Class is a fantastic tool for object based testing; it's lightweight and works with Test::More and all Test::Builder related unit test tools.
Robert P
+3  A: 

Just to add a little bit about BDD bit because friedo answer I think covers everthing else.

Have a quick look at this Perlmonks discussion Behavior Driven Development: suggested tools for perl?

I think some tools which may point you in right direction:

Also see this SO question: Can you review my Perl rewrite of Cucumber?

Hope some of this helps.

/I3az/

draegtun
+5  A: 

Lately, with MooseX::Declare, I've been using "real objects" as mock objects.

Say you have a database driver that does an interface like this:

role Database {
    requires 'connect';
    requires 'query';
};

Then you have code like this that uses the Database:

class FooPage {
    has 'database' => (
        is       => 'ro',
        does     => 'Database',
        required => 1,
    );

    method get_foo() {
        $self->database->query({ foo => 42 });
    }

    method render_page(Str $user) {
        "Hello, $user.  Here is a foo for you: ". $self->get_foo;
    }
};

Now you want to test this:

use Test::More tests => 2;
use MooseX::Declare;

my $fake_database = class with Database {
    has 'data' => ( is => 'ro', isa => 'HashRef' );
    has 'connected' => ( is => 'rw', isa => 'Bool' );

    method connect() { $self->connected(1) }
    method query(HashRef $query) { $self->data->{$query->{foo}} }
};

my $test_database = $fake_database->name->new(
    data => {
        42 => 'OH HAI',
    },
};

my $foo_page = FooPage->new( database => $test_database );
is $foo_page->get_foo, 'OH HAI', 'got correct foo';
is $foo_page->render_page('jrockway'),
   'Hello, jrockway.  Here is a foo for you: OH HAI',
 'got rendered page';

Notice how you have concise syntax, but the full power of a "real" Moose class as your mock object. Convenient, and infinitely flexible.

(These are just examples... it could also be something much better.)

jrockway
This looks damn cool, but if I was not using Moose already, I would probably skip this.
Robert P