[Catalyst] Unit Testing

John Romkey romkey at apocalypse.org
Sun Apr 20 04:50:59 BST 2008

On Apr 19, 2008, at 10:51 PM, Yao Wang wrote:
> Hi Everybody,
> Recently, i am looking for some modules for unit testing. I have  
> seen Catalyst::Test, Test::WWW::Mechanize::Catalyst etc, i think  
> they are the testing tools for application, not for unit testing.  
> When i do the unit testing, i need to pass $c and some other params  
> to the methods right ? But how can i create $c for testing ?
> So can anybody tell me how to create this kind of $c ?


Here's what I'd suggest:

Structure your application so that all the real work is done in a set  
of modules which Catalyst then calls to do the work. Use Catalyst as a  
wrapper to interface your application to the web. Catalyst documents  
refer to this as the "business logic" of your application. The  
application itself will have no dependencies on Catalyst and can be  
tested independently of it. The application wrapped in Catalyst can be  
tested using the testing tools you mentioned above.

I suspect that most Catalyst users build their applications so that  
the controllers do too much work. I certainly did, and I'm gradually  
rewriting mine to move most of the work into the model. Where before  
my controllers would interact directly with the database, now they ask  
the model to do it for them. The model is now the heart of the  
application; it does all the work and Catalyst only glues it to the  
web. You could discard Catalyst and build a command-line interface  
using the same model, or build some other kind of interface and not  
have to change the model at all.

Suppose you need to be able to create a user account for your web  
site. You probably want to do a variety of tests on the account  
information... does an account already exist with that email address?  
Is the password strong or weak? Does the account name use any  
prohibited words in it? And if the account is acceptable you need to  
write at least one record, possibly more, into a database.

The way I originally wrote my controller, the controller itself did  
all that itself. The way I've rewritten it, my business logic model  
does it for me. The controller has an action in it which handles the  
account creation request. That action gathers the necessary  
information from the request, performs any web-related validation on  
it (at least making sure all the needed parameters are there) and then  
calls the model to create the account. If there's an error, it reports  
the error back to the user.

Now if you want a command-line utility to create an account, you just  
write a Perl script which gets its arguments from the command-line and  
calls the same business logic.

Then you can write unit tests that completely bypass Catalyst and call  
the business logic to confirm that it properly creates an account, or  
properly rejects an account with a bad password or unacceptable word  
in its name. And you can write Catalyst tests to confirm that Catalyst  
correctly maps web actions into the business logic.

This is all a bit more work than might seem necessary at first, but if  
your application evolves at all you'll probably find that modularizing  
it in this manner really helps make it more understandable and  
maintainable in the long term, as well as making it more testable.
	- john romkey

More information about the Catalyst mailing list