Writing tests before any other code is one good approach to software development. While it can seem like a pain, it can greatly simplify the development process.

Run test scripts for your application from the root dir of your application like this:

$ prove -l t/
# or to run a specific test
$ prove -l t/name-of-test-script.t

With testing generally the idea is that you want to identify core features and paths. Features means abilities your application claims to have and needs to provide to the user, and path means the sequence through which a user interacts with a feature. As an added bonus this thought process usually helps you simplify the user interface.

The features are what you test, and the paths are how you test them.

Test the core paths with WWW::Mechanize, Test::WWW::Mechanize, or Test::WWW::Mechanize::Catalyst (version 0.35 or newer properly handles redirects on POST requests).

These tests should check for the following things, to identify that the path leads to correct manifestation of the feature:

  • the links work as expected
  • invalid form data is disallowed
  • valid form data gives back results
  • and actions have meaningful results
  • the output is valid HTML

These items are orthogonal, meaning that each test case checks a different one of these qualities, and each of them could fail for different reasons. Don't mash up your test cases. Instead, try to separate the levels - don't test view-specific functionality and controller-specific functionality together. The *behavior* of the application is related to the controller and the way this behavior manifests itself to the user is view-related.

When you're testing controller behavior look for key strings which are unique within the body to make sure input and output are consistent. Don't test the structure of the output if that's not what this test is really checking.

Try to keep the paths simple: no more than 2-3 requests for small features. This makes tests easier to fix if/when they do break and helps with test driven development.

Model Tests

Catalyst generates test stubs as t/model_*.t or t/m_*.t.

These are typically the same kinds of tests you would write for any Perl module/class. They're pretty simple, and independent of your app's actual usage of the model.

Examples of test for your model:

  • STUB

View Tests

Catalyst generates test stubs as t/view_*.t or t/v_*.t.

These tests are usually in one of two varieties. The first is unit tests for your view controllers (e.g. Catalyst::View::Foo - the generic class), which can be unit test like, checking that they process view things the right way. The second variety is tests for your templates: see that some simple inputs to the templates gives the right output, and that the templates all generate valid HTML (or whatever), and make have no errors. View tests are generally pretty simple.

Examples of test for your views:

  • STUB

Controller Tests

Catalyst generates test stubs as t/controller_*.t or t/c_*.t.

These tests usually test the actions themselves. They are typically written with Test::WWW::Mechanize, although in theory they could be tested independently of the views. Doing that is likely not worth the effort, and in general the "web" tests for the app check that the controllers behave correctly anyway.

Examples of test for your controller:

  • STUB

Note on customizing your test application

If you want to use a different database during testing, or you want the test app to use simplified templates, you might need to hack at your application's config.

Just add:

use MyApp;
my $config = MyApp->config;

to the test suite, and then you can hack at the config settings as much as you like.

See Also

DebugSample for information about using the debugger. The combination of Test Harness, and interactive debugger is very powerful.