[Catalyst] Testing controller which require login.
bobtfish at bobtfish.net
Fri May 15 11:09:29 GMT 2009
Louis Erickson wrote:
> Just today I spent time writing up some documentation patches you pointed
> out I could contribute on my blog. I'm going to try and keep adding
> things where I can.
Applied in another thread - keep up the good work :)
> Random question about that... if I have diffs to send to the list, are
> they preferred as part of the body or an attachment to the message so line
> wrap and such don't mangle them?
Attachment definitely best.
Alternatively, feel free to turn up on irc and get a commit bit so you
can just commit stuff, that's highly encouraged for docs :)
>> Well volunteered in advance. ;_)
> Where would these best go? The Catalyst dev wiki? I actually ask this
> about several different parts, now that I think of it.
Yeah, I have a feeling that some of it should go in Catalyst::Test, and
possibly Test::WWW::Mechanize::Catalyst, and some in Catalyst::Manual..
However throwing things onto the wiki as a 'work in progress', or if
don't think they're generally applicable to the manual is also great :)
>> Technique 1:
>>> I can't tell if Catalyst::Test supports cookies. Does it? Or do I need to
>>> use WWW::Mechanize::Catalyst for that?
>> It doesn't support cookies per-se, but it's not hard to handle this yourself.
>> For a nice neat example against the tutorial of testing login, see:
> I see this is checking the request header after the request is run. To be
> able to generate a login cookie, I'd have to generate a cookie string, and
> add it to the request. The documentation says the request only supports
> setting the host value, so I couldn't do that. Am I missing something?
Yes, I think you are.. For more complex cases, I use
HTTP::Request::Common to get a $req object, which I can then poke with
So I make my login request, extract the cookie value, then stick that
back into the Cookie header for each subsequent request.
> It looks like that would be reasonably straightforward, by adding
> code to Catalyst::Test::_customize_request to handle the cookies.
> Would that be a worthwhile change? I'm not sure. It might just be better
> to tell someone who needs that to use a different test method, such as
> Mechanize. Myself, I think I'd rather change test harnesses than support
> the new code.
Yeah, it'd be nice to have some basic cookie handling with
Catalyst::Test, so that you could ask it to keep and send back cookies
it was given.
If you'd be prepared to work on that, that would be super!
>> Technique 3:
>>> 2> Use the mock user in config to set a user who is logged in.
> Considering my test environment already uses a separate configuration
> file, telling the authentication system to use a class like this would be
> straightforward. This is probably the least work for me, but only because
> I already have the tests already using a different configuration.
> Can a test get to Catalyst's configuration at run time, to change what
> users is mocked in by the authentication module, or would a class it can
> fiddle with like this be required. Can I reach TestApp->config() from
It can't if you're running the tests remotely, but if you're within the
same process (the default if you're just using Catalyst::Test), then sure!
I'd probably use package variables as shown before, so you just say:
$My::Mock::User::id = 'fred'; within your test script...
> I'm not sure how those cookies are serialized and if it's going to be a
> pain to get the libraries to let me do it from a different place.
> This would be one of my later choices. It's really a special case of
> fixtures - it's just data to load before tests. This is time-sensitive
> data which must be calculated, so I can't just store one.
Exactly :) And again, if your TestApp is in the same process as the
tests, then you _can_ just call methods on TestApp-> without a request
context / with a fake context.
I'm sure it would involve a bit of poking and prodding, but would be
fairly easy to do..
I'd really like to see this as a tutorial / how-to documentation somewhere..
> It does let you test a bunch of other useful things - redirects, etc -
> that people might well benefit from seeing how to do.
> Where would the best place for an elaboration of this technique be? A
> cookbook entry in Catalyst::Test, so it is easily found? A page on the
> Catalyst dev wiki?
I think some short notes in Catalyst::Test itself, and extending the
'Testing' section in Catalyst::Manual would probably be best.
> 3 does sound more maintainable to me; the user is simply by the test
> script and you don't have to mess about with faking a login/logout and
> depending on cookies or whatever.
> I don't know how difficult it would be to implement 5 cleanly for every
> session store, and for every authentication system. I'm not sure it's
> authenticator just checks the headers doesn't it, and the mocked user
> would work there, never bothering to check.
Ah yes - 5 is going to be auth/session/store dependent. I was really
only suggesting that if you use this technique, then you write a how-to
for your combination :)
> That doesn't mean general access to the stored session from a test script
> might not be useful, but I'm not sure it's generally useful. Or am I
> misunderstanding how Catalyst stores the cookies... I thought they just
> went in to the session.
The cookie value is basically the key by which the session is
stored/retrieved, so (given cookies are being used), creating / getting
/ setting sessions in a test should be fairly easy to arrange in a
generic way, no matter what your session storage backend.
> I just looked at the existing authentication plugins, hoping one of the
> current ones would allow this without new code. I don't see one that can
> do so by itself. Catalyst::Authentication::User::Mock, perhaps? Or am I
> missing something?
No, I think that you'd need a new class, and that's the class name I was
thinking of. :)
> Of course, I can always do both, and use #4 to test those parts, and then
> a simple mock user to test the rest. It might make tests faster.
Exactly - use the most appropriate tool for the job to get coverage of
the sections of your codebase which you care about, forget the rest. :)
Testing things like complex expiry policies etc with 'real' http
requests is going to be a huge pain in the ass - I wouldn't even bother,
and just whip up tests for that sort of stuff with Test::MockObject.
> The idea, though, of adding a controller at test-time, is brilliant. If
> it gets written down, will it be horribly abused? =)
Probably, but as long as you're careful to point out that you're giving
people a loaded gun, then it's their problem and we can stand back and
laugh if they pull the trigger whilst it's aimed at any body parts.
> Where would this idea best be described? Catalyst dev Wiki? Blog entry?
Yes, both :)
> Thank you again for this rich response.
No problem, thank you for volunteering to expand and write down some of
my rambling stream of consciousness..
More information about the Catalyst