[Catalyst] Unit Testing
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