Pull deployment info out
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Deployment.pod
CommitLineData
01b62b15 1=head1 NAME
2
3Catalyst::Manual::Deployment - Deploying Catalyst
4
5=head1
6
7=head1 mod_perl
8
9L<Catalyst::Manual::Deployment::Apache::mod_perl>
10
11=head1 FastCGI
12
13=head2 Apache
14
15L<Catalyst::Manual::Deployment::Apache::FastCGI>
16
17
18=head2 mod_perl Deployment
19
20mod_perl is not the best solution for many applications, but we'll list some
21pros and cons so you can decide for yourself. The other (recommended)
22deployment option is FastCGI, for which see below.
23
24=head3 Pros
25
26=head4 Speed
27
28mod_perl is fast and your app will be loaded in memory
29within each Apache process.
30
31=head4 Shared memory for multiple apps
32
33If you need to run several Catalyst apps on the same server, mod_perl will
34share the memory for common modules.
35
36=head3 Cons
37
38=head4 Memory usage
39
40Since your application is fully loaded in memory, every Apache process will
41be rather large. This means a large Apache process will be tied up while
42serving static files, large files, or dealing with slow clients. For this
43reason, it is best to run a two-tiered web architecture with a lightweight
44frontend server passing dynamic requests to a large backend mod_perl
45server.
46
47=head4 Reloading
48
49Any changes made to the core code of your app require a full Apache restart.
50Catalyst does not support Apache::Reload or StatINC. This is another good
51reason to run a frontend web server where you can set up an
52C<ErrorDocument 502> page to report that your app is down for maintenance.
53
54=head4 Cannot run multiple versions of the same app
55
56It is not possible to run two different versions of the same application in
57the same Apache instance because the namespaces will collide.
58
59=head4 Cannot run different versions of libraries.
60
61If you have two different applications which run on the same machine,
62which need two different versions of a library then the only way to do
63this is to have per-vhost perl interpreters (with different library paths).
64This is entirely possible, but nullifies all the memory sharing benefits that
65you get from having multiple applications sharing the same interpreter.
66
67=head4 Setup
68
69Now that we have that out of the way, let's talk about setting up mod_perl
70to run a Catalyst app.
71
72=head4 1. Install Catalyst::Engine::Apache
73
74You should install the latest versions of both Catalyst and
75Catalyst::Engine::Apache. The Apache engines were separated from the
76Catalyst core in version 5.50 to allow for updates to the engine without
77requiring a new Catalyst release.
78
79=head4 2. Install Apache with mod_perl
80
81Both Apache 1.3 and Apache 2 are supported, although Apache 2 is highly
82recommended. With Apache 2, make sure you are using the prefork MPM and not
83the worker MPM. The reason for this is that many Perl modules are not
84thread-safe and may have problems running within the threaded worker
85environment. Catalyst is thread-safe however, so if you know what you're
86doing, you may be able to run using worker.
87
88In Debian, the following commands should get you going.
89
90 apt-get install apache2-mpm-prefork
91 apt-get install libapache2-mod-perl2
92
93=head4 3. Configure your application
94
95Every Catalyst application will automagically become a mod_perl handler
96when run within mod_perl. This makes the configuration extremely easy.
97Here is a basic Apache 2 configuration.
98
99 PerlSwitches -I/var/www/MyApp/lib
100 PerlModule MyApp
101
102 <Location />
103 SetHandler modperl
104 PerlResponseHandler MyApp
105 </Location>
106
107The most important line here is C<PerlModule MyApp>. This causes mod_perl
108to preload your entire application into shared memory, including all of your
109controller, model, and view classes and configuration. If you have -Debug
110mode enabled, you will see the startup output scroll by when you first
111start Apache.
112
113For an example Apache 1.3 configuration, please see the documentation for
114L<Catalyst::Engine::Apache::MP13>.
115
116=head3 Test It
117
118That's it, your app is now a full-fledged mod_perl application! Try it out
119by going to http://your.server.com/.
120
121=head3 Other Options
122
123=head4 Non-root location
124
125You may not always want to run your app at the root of your server or virtual
126host. In this case, it's a simple change to run at any non-root location
127of your choice.
128
129 <Location /myapp>
130 SetHandler modperl
131 PerlResponseHandler MyApp
132 </Location>
133
134When running this way, it is best to make use of the C<uri_for> method in
135Catalyst for constructing correct links.
136
137=head4 Static file handling
138
139Static files can be served directly by Apache for a performance boost.
140
141 DocumentRoot /var/www/MyApp/root
142 <Location /static>
143 SetHandler default-handler
144 </Location>
145
146This will let all files within root/static be handled directly by Apache. In
147a two-tiered setup, the frontend server should handle static files.
148The configuration to do this on the frontend will vary.
149
150The same is accomplished in lighttpd with the following snippet:
151
152 $HTTP["url"] !~ "^/(?:img/|static/|css/|favicon.ico$)" {
153 fastcgi.server = (
154 "" => (
155 "MyApp" => (
156 "socket" => "/tmp/myapp.socket",
157 "check-local" => "disable",
158 )
159 )
160 )
161 }
162
163Which serves everything in the img, static, css directories
164statically, as well as the favicon file.
165
166Note the path of the application needs to be stated explicitly in the
167web server configuration for both these recipes.
168
169=head2 Catalyst on shared hosting
170
171So, you want to put your Catalyst app out there for the whole world to
172see, but you don't want to break the bank. There is an answer - if you
173can get shared hosting with FastCGI and a shell, you can install your
174Catalyst app in a local directory on your shared host. First, run
175
176 perl -MCPAN -e shell
177
178and go through the standard CPAN configuration process. Then exit out
179without installing anything. Next, open your .bashrc and add
180
181 export PATH=$HOME/local/bin:$HOME/local/script:$PATH
182 perlversion=`perl -v | grep 'built for' | awk '{print $4}' | sed -e 's/v//;'`
183 export PERL5LIB=$HOME/local/share/perl/$perlversion:$HOME/local/lib/perl/$perlversion:$HOME/local/lib:$PERL5LIB
184
185and log out, then back in again (or run C<". .bashrc"> if you
186prefer). Finally, edit C<.cpan/CPAN/MyConfig.pm> and add
187
188 'make_install_arg' => qq[SITEPREFIX=$ENV{HOME}/local],
189 'makepl_arg' => qq[INSTALLDIRS=site install_base=$ENV{HOME}/local],
190
191Now you can install the modules you need using CPAN as normal; they
192will be installed into your local directory, and perl will pick them
193up. Finally, change directory into the root of your virtual host and
194symlink your application's script directory in:
195
196 cd path/to/mydomain.com
197 ln -s ~/lib/MyApp/script script
198
199And add the following lines to your .htaccess file (assuming the server
200is setup to handle .pl as fcgi - you may need to rename the script to
201myapp_fastcgi.fcgi and/or use a SetHandler directive):
202
203 RewriteEngine On
204 RewriteCond %{REQUEST_URI} !^/?script/myapp_fastcgi.pl
205 RewriteRule ^(.*)$ script/myapp_fastcgi.pl/$1 [PT,L]
206
207Now C<http://mydomain.com/> should now Just Work. Congratulations, now
208you can tell your friends about your new website (or in our case, tell
209the client it's time to pay the invoice :) )
210
211=head2 FastCGI Deployment
212
213FastCGI is a high-performance extension to CGI. It is suitable
214for production environments.
215
216=head3 Pros
217
218=head4 Speed
219
220FastCGI performs equally as well as mod_perl. Don't let the 'CGI' fool you;
221your app runs as multiple persistent processes ready to receive connections
222from the web server.
223
224=head4 App Server
225
226When using external FastCGI servers, your application runs as a standalone
227application server. It may be restarted independently from the web server.
228This allows for a more robust environment and faster reload times when
229pushing new app changes. The frontend server can even be configured to
230display a friendly "down for maintenance" page while the application is
231restarting.
232
233=head4 Load-balancing
234
235You can launch your application on multiple backend servers and allow the
236frontend web server to load-balance between all of them. And of course, if
237one goes down, your app continues to run fine.
238
239=head4 Multiple versions of the same app
240
241Each FastCGI application is a separate process, so you can run different
242versions of the same app on a single server.
243
244=head4 Can run with threaded Apache
245
246Since your app is not running inside of Apache, the faster mpm_worker module
247can be used without worrying about the thread safety of your application.
248
249=head3 Cons
250
251You may have to disable mod_deflate. If you experience page hangs with
252mod_fastcgi then remove deflate.load and deflate.conf from mods-enabled/
253
254=head4 More complex environment
255
256With FastCGI, there are more things to monitor and more processes running
257than when using mod_perl.
258
259=head3 Setup
260
261=head4 1. Install Apache with mod_fastcgi
262
263mod_fastcgi for Apache is a third party module, and can be found at
264L<http://www.fastcgi.com/>. It is also packaged in many distributions,
265for example, libapache2-mod-fastcgi in Debian. You will also need to install
266the L<FCGI> module from cpan.
267
268Important Note! If you experience difficulty properly rendering pages,
269try disabling Apache's mod_deflate (Deflate Module), e.g. 'a2dismod deflate'.
270
271=head4 2. Configure your application
272
273 # Serve static content directly
274 DocumentRoot /var/www/MyApp/root
275 Alias /static /var/www/MyApp/root/static
276
277 FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -processes 3
278 Alias /myapp/ /var/www/MyApp/script/myapp_fastcgi.pl/
279
280 # Or, run at the root
281 Alias / /var/www/MyApp/script/myapp_fastcgi.pl/
282
283The above commands will launch 3 app processes and make the app available at
284/myapp/
285
286=head3 Standalone server mode
287
288While not as easy as the previous method, running your app as an external
289server gives you much more flexibility.
290
291First, launch your app as a standalone server listening on a socket.
292
293 script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5 -p /tmp/myapp.pid -d
294
295You can also listen on a TCP port if your web server is not on the same
296machine.
297
298 script/myapp_fastcgi.pl -l :8080 -n 5 -p /tmp/myapp.pid -d
299
300You will probably want to write an init script to handle starting/stopping
301of the app using the pid file.
302
303Now, we simply configure Apache to connect to the running server.
304
305 # 502 is a Bad Gateway error, and will occur if the backend server is down
306 # This allows us to display a friendly static page that says "down for
307 # maintenance"
308 Alias /_errors /var/www/MyApp/root/error-pages
309 ErrorDocument 502 /_errors/502.html
310
311 FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
312 Alias /myapp/ /tmp/myapp.fcgi/
313
314 # Or, run at the root
315 Alias / /tmp/myapp.fcgi/
316
317=head3 More Info
318
319L<Catalyst::Engine::FastCGI>.
320
321=head2 Development server deployment
322
323The development server is a mini web server written in perl. If you
324expect a low number of hits or you don't need mod_perl/FastCGI speed,
325you could use the development server as the application server with a
326lightweight proxy web server at the front. However, consider using
327L<Catalyst::Engine::HTTP::Prefork> for this kind of deployment instead, since
328it can better handle multiple concurrent requests without forking, or can
329prefork a set number of servers for improved performance.
330
331=head3 Pros
332
333As this is an application server setup, the pros are the same as
334FastCGI (with the exception of speed).
335It is also:
336
337=head4 Simple
338
339The development server is what you create your code on, so if it works
340here, it should work in production!
341
342=head3 Cons
343
344=head4 Speed
345
346Not as fast as mod_perl or FastCGI. Needs to fork for each request
347that comes in - make sure static files are served by the web server to
348save forking.
349
350=head3 Setup
351
352=head4 Start up the development server
353
354 script/myapp_server.pl -p 8080 -k -f -pidfile=/tmp/myapp.pid
355
356You will probably want to write an init script to handle stop/starting
357the app using the pid file.
358
359=head4 Configuring Apache
360
361Make sure mod_proxy is enabled and add:
362
363 # Serve static content directly
364 DocumentRoot /var/www/MyApp/root
365 Alias /static /var/www/MyApp/root/static
366
367 ProxyRequests Off
368 <Proxy *>
369 Order deny,allow
370 Allow from all
371 </Proxy>
372
373 # Need to specifically stop these paths from being passed to proxy
374 ProxyPass /static !
375 ProxyPass /favicon.ico !
376
377 ProxyPass / http://localhost:8080/
378 ProxyPassReverse / http://localhost:8080/
379
380 # This is optional if you'd like to show a custom error page
381 # if the proxy is not available
382 ErrorDocument 502 /static/error_pages/http502.html
383
384You can wrap the above within a VirtualHost container if you want
385different apps served on the same host.
386
387=head2 Quick deployment: Building PAR Packages
388
389You have an application running on your development box, but then you
390have to quickly move it to another one for
391demonstration/deployment/testing...
392
393PAR packages can save you from a lot of trouble here. They are usual Zip
394files that contain a blib tree; you can even include all prereqs and a
395perl interpreter by setting a few flags!
396
397=head3 Follow these few points to try it out!
398
3991. Install Catalyst and PAR 0.89 (or later)
400
401 % perl -MCPAN -e 'install Catalyst'
402 ...
403 % perl -MCPAN -e 'install PAR'
404 ...
405
4062. Create a application
407
408 % catalyst.pl MyApp
409 ...
410 % cd MyApp
411
412Recent versions of Catalyst (5.62 and up) include
413L<Module::Install::Catalyst>, which simplifies the process greatly. From the shell in your application directory:
414
415 % perl Makefile.PL
416 % make catalyst_par
417
418You can customise the PAR creation process by special "catalyst_par_*" commands
419available from L<Module::Install::Catalyst>. You can add these commands in your
420Makefile.PL just before the line containing "catalyst;"
421
422 #Makefile.PL example with extra PAR options
423 use inc::Module::Install;
424
425 name 'MyApp';
426 all_from 'lib\MyApp.pm';
427
428 requires 'Catalyst::Runtime' => '5.80005';
429 <snip>
430 ...
431 <snip>
432
433 catalyst_par_core(1); # bundle perl core modules in the resulting PAR
434 catalyst_par_multiarch(1); # build a multi-architecture PAR file
435 catalyst_par_classes(qw/
436 Some::Additional::Module
437 Some::Other::Module
438 /); # specify additional modules you want to be included into PAR
439 catalyst;
440
441 install_script glob('script/*.pl');
442 auto_install;
443 WriteAll;
444
445Congratulations! Your package "myapp.par" is ready, the following
446steps are just optional.
447
4483. Test your PAR package with "parl" (no typo)
449
450 % parl myapp.par
451 Usage:
452 [parl] myapp[.par] [script] [arguments]
453
454 Examples:
455 parl myapp.par myapp_server.pl -r
456 myapp myapp_cgi.pl
457
458 Available scripts:
459 myapp_cgi.pl
460 myapp_create.pl
461 myapp_fastcgi.pl
462 myapp_server.pl
463 myapp_test.pl
464
465 % parl myapp.par myapp_server.pl
466 You can connect to your server at http://localhost:3000
467
468Yes, this nifty little starter application gets automatically included.
469You can also use "catalyst_par_script('myapp_server.pl')" to set a
470default script to execute.
471
4726. Want to create a binary that includes the Perl interpreter?
473
474 % pp -o myapp myapp.par
475 % ./myapp myapp_server.pl
476 You can connect to your server at http://localhost:3000
477
478=head2 Serving static content
479
480Serving static content in Catalyst used to be somewhat tricky; the use
481of L<Catalyst::Plugin::Static::Simple> makes everything much easier.
482This plugin will automatically serve your static content during development,
483but allows you to easily switch to Apache (or other server) in a
484production environment.
485
486=head3 Introduction to Static::Simple
487
488Static::Simple is a plugin that will help to serve static content for your
489application. By default, it will serve most types of files, excluding some
490standard Template Toolkit extensions, out of your B<root> file directory. All
491files are served by path, so if B<images/me.jpg> is requested, then
492B<root/images/me.jpg> is found and served.
493
494=head3 Usage
495
496Using the plugin is as simple as setting your use line in MyApp.pm to include:
497
498 use Catalyst qw/Static::Simple/;
499
500and already files will be served.
501
502=head3 Configuring
503
504Static content is best served from a single directory within your root
505directory. Having many different directories such as C<root/css> and
506C<root/images> requires more code to manage, because you must separately
507identify each static directory--if you decide to add a C<root/js>
508directory, you'll need to change your code to account for it. In
509contrast, keeping all static directories as subdirectories of a main
510C<root/static> directory makes things much easier to manage. Here's an
511example of a typical root directory structure:
512
513 root/
514 root/content.tt
515 root/controller/stuff.tt
516 root/header.tt
517 root/static/
518 root/static/css/main.css
519 root/static/images/logo.jpg
520 root/static/js/code.js
521
522
523All static content lives under C<root/static>, with everything else being
524Template Toolkit files.
525
526=over 4
527
528=item Include Path
529
530You may of course want to change the default locations, and make
531Static::Simple look somewhere else, this is as easy as:
532
533 MyApp->config->{static}->{include_path} = [
534 MyApp->config->{root},
535 '/path/to/my/files'
536 ];
537
538When you override include_path, it will not automatically append the
539normal root path, so you need to add it yourself if you still want
540it. These will be searched in order given, and the first matching file
541served.
542
543=item Static directories
544
545If you want to force some directories to be only static, you can set
546them using paths relative to the root dir, or regular expressions:
547
548 MyApp->config->{static}->{dirs} = [
549 'static',
550 qr/^(images|css)/,
551 ];
552
553=item File extensions
554
555By default, the following extensions are not served (that is, they will
556be processed by Catalyst): B<tmpl, tt, tt2, html, xhtml>. This list can
557be replaced easily:
558
559 MyApp->config->{static}->{ignore_extensions} = [
560 qw/tmpl tt tt2 html xhtml/
561 ];
562
563=item Ignoring directories
564
565Entire directories can be ignored. If used with include_path,
566directories relative to the include_path dirs will also be ignored:
567
568 MyApp->config->{static}->{ignore_dirs} = [ qw/tmpl css/ ];
569
570=back
571
572=head3 More information
573
574L<http://search.cpan.org/dist/Catalyst-Plugin-Static-Simple/>
575
576=head3 Serving manually with the Static plugin with HTTP::Daemon (myapp_server.pl)
577
578In some situations you might want to control things more directly,
579using L<Catalyst::Plugin::Static>.
580
581In your main application class (MyApp.pm), load the plugin:
582
583 use Catalyst qw/-Debug FormValidator Static OtherPlugin/;
584
585You will also need to make sure your end method does I<not> forward
586static content to the view, perhaps like this:
587
588 sub end : Private {
589 my ( $self, $c ) = @_;
590
591 $c->forward( 'MyApp::View::TT' )
592 unless ( $c->res->body || !$c->stash->{template} );
593 }
594
595This code will only forward to the view if a template has been
596previously defined by a controller and if there is not already data in
597C<$c-E<gt>res-E<gt>body>.
598
599Next, create a controller to handle requests for the /static path. Use
600the Helper to save time. This command will create a stub controller as
601C<lib/MyApp/Controller/Static.pm>.
602
603 $ script/myapp_create.pl controller Static
604
605Edit the file and add the following methods:
606
607 # serve all files under /static as static files
608 sub default : Path('/static') {
609 my ( $self, $c ) = @_;
610
611 # Optional, allow the browser to cache the content
612 $c->res->headers->header( 'Cache-Control' => 'max-age=86400' );
613
614 $c->serve_static; # from Catalyst::Plugin::Static
615 }
616
617 # also handle requests for /favicon.ico
618 sub favicon : Path('/favicon.ico') {
619 my ( $self, $c ) = @_;
620
621 $c->serve_static;
622 }
623
624You can also define a different icon for the browser to use instead of
625favicon.ico by using this in your HTML header:
626
627 <link rel="icon" href="/static/myapp.ico" type="image/x-icon" />
628
629=head3 Common problems with the Static plugin
630
631The Static plugin makes use of the C<shared-mime-info> package to
632automatically determine MIME types. This package is notoriously
633difficult to install, especially on win32 and OS X. For OS X the easiest
634path might be to install Fink, then use C<apt-get install
635shared-mime-info>. Restart the server, and everything should be fine.
636
637Make sure you are using the latest version (>= 0.16) for best
638results. If you are having errors serving CSS files, or if they get
639served as text/plain instead of text/css, you may have an outdated
640shared-mime-info version. You may also wish to simply use the following
641code in your Static controller:
642
643 if ($c->req->path =~ /css$/i) {
644 $c->serve_static( "text/css" );
645 } else {
646 $c->serve_static;
647 }
648
649=head3 Serving Static Files with Apache
650
651When using Apache, you can bypass Catalyst and any Static
652plugins/controllers controller by intercepting requests for the
653C<root/static> path at the server level. All that is required is to
654define a DocumentRoot and add a separate Location block for your static
655content. Here is a complete config for this application under mod_perl
6561.x:
657
658 <Perl>
659 use lib qw(/var/www/MyApp/lib);
660 </Perl>
661 PerlModule MyApp
662
663 <VirtualHost *>
664 ServerName myapp.example.com
665 DocumentRoot /var/www/MyApp/root
666 <Location />
667 SetHandler perl-script
668 PerlHandler MyApp
669 </Location>
670 <LocationMatch "/(static|favicon.ico)">
671 SetHandler default-handler
672 </LocationMatch>
673 </VirtualHost>
674
675And here's a simpler example that'll get you started:
676
677 Alias /static/ "/my/static/files/"
678 <Location "/static">
679 SetHandler none
680 </Location>
681
682=head2 Caching
683
684Catalyst makes it easy to employ several different types of caching to
685speed up your applications.
686
687=head3 Cache Plugins
688
689There are three wrapper plugins around common CPAN cache modules:
690Cache::FastMmap, Cache::FileCache, and Cache::Memcached. These can be
691used to cache the result of slow operations.
692
693The Catalyst Advent Calendar uses the FileCache plugin to cache the
694rendered XHTML version of the source POD document. This is an ideal
695application for a cache because the source document changes
696infrequently but may be viewed many times.
697
698 use Catalyst qw/Cache::FileCache/;
699
700 ...
701
702 use File::stat;
703 sub render_pod : Local {
704 my ( self, $c ) = @_;
705
706 # the cache is keyed on the filename and the modification time
707 # to check for updates to the file.
708 my $file = $c->path_to( 'root', '2005', '11.pod' );
709 my $mtime = ( stat $file )->mtime;
710
711 my $cached_pod = $c->cache->get("$file $mtime");
712 if ( !$cached_pod ) {
713 $cached_pod = do_slow_pod_rendering();
714 # cache the result for 12 hours
715 $c->cache->set( "$file $mtime", $cached_pod, '12h' );
716 }
717 $c->stash->{pod} = $cached_pod;
718 }
719
720We could actually cache the result forever, but using a value such as 12 hours
721allows old entries to be automatically expired when they are no longer needed.
722
723=head3 Page Caching
724
725Another method of caching is to cache the entire HTML page. While this is
726traditionally handled by a front-end proxy server like Squid, the Catalyst
727PageCache plugin makes it trivial to cache the entire output from
728frequently-used or slow actions.
729
730Many sites have a busy content-filled front page that might look something
731like this. It probably takes a while to process, and will do the exact same
732thing for every single user who views the page.
733
734 sub front_page : Path('/') {
735 my ( $self, $c ) = @_;
736
737 $c->forward( 'get_news_articles' );
738 $c->forward( 'build_lots_of_boxes' );
739 $c->forward( 'more_slow_stuff' );
740
741 $c->stash->{template} = 'index.tt';
742 }
743
744We can add the PageCache plugin to speed things up.
745
746 use Catalyst qw/Cache::FileCache PageCache/;
747
748 sub front_page : Path ('/') {
749 my ( $self, $c ) = @_;
750
751 $c->cache_page( 300 );
752
753 # same processing as above
754 }
755
756Now the entire output of the front page, from <html> to </html>, will be
757cached for 5 minutes. After 5 minutes, the next request will rebuild the
758page and it will be re-cached.
759
760Note that the page cache is keyed on the page URI plus all parameters, so
761requests for / and /?foo=bar will result in different cache items. Also,
762only GET requests will be cached by the plugin.
763
764You can even get that front-end Squid proxy to help out by enabling HTTP
765headers for the cached page.
766
767 MyApp->config->{page_cache}->{set_http_headers} = 1;
768
769This would now set the following headers so proxies and browsers may cache
770the content themselves.
771
772 Cache-Control: max-age=($expire_time - time)
773 Expires: $expire_time
774 Last-Modified: $cache_created_time
775
776=head3 Template Caching
777
778Template Toolkit provides support for caching compiled versions of your
779templates. To enable this in Catalyst, use the following configuration.
780TT will cache compiled templates keyed on the file mtime, so changes will
781still be automatically detected.
782
783 package MyApp::View::TT;
784
785 use strict;
786 use warnings;
787 use base 'Catalyst::View::TT';
788
789 __PACKAGE__->config(
790 COMPILE_DIR => '/tmp/template_cache',
791 );
792
793 1;
794
795=head3 More Info
796
797See the documentation for each cache plugin for more details and other
798available configuration options.
799
800L<Catalyst::Plugin::Cache::FastMmap>
801L<Catalyst::Plugin::Cache::FileCache>
802L<Catalyst::Plugin::Cache::Memcached>
803L<Catalyst::Plugin::PageCache>
804L<http://search.cpan.org/dist/Template-Toolkit/lib/Template/Manual/Config.pod#Caching_and_Compiling_Options>
805
806=head1 Testing
807
808Testing is an integral part of the web application development
809process. Tests make multi developer teams easier to coordinate, and
810they help ensure that there are no nasty surprises after upgrades or
811alterations.
812
813=head2 Testing
814
815Catalyst provides a convenient way of testing your application during
816development and before deployment in a real environment.
817
818C<Catalyst::Test> makes it possible to run the same tests both locally
819(without an external daemon) and against a remote server via HTTP.
820
821=head3 Tests
822
823Let's examine a skeleton application's C<t/> directory:
824
825 mundus:~/MyApp chansen$ ls -l t/
826 total 24
827 -rw-r--r-- 1 chansen chansen 95 18 Dec 20:50 01app.t
828 -rw-r--r-- 1 chansen chansen 190 18 Dec 20:50 02pod.t
829 -rw-r--r-- 1 chansen chansen 213 18 Dec 20:50 03podcoverage.t
830
831=over 4
832
833=item C<01app.t>
834
835Verifies that the application loads, compiles, and returns a successful
836response.
837
838=item C<02pod.t>
839
840Verifies that all POD is free from errors. Only executed if the C<TEST_POD>
841environment variable is true.
842
843=item C<03podcoverage.t>
844
845Verifies that all methods/functions have POD coverage. Only executed if the
846C<TEST_POD> environment variable is true.
847
848=back
849
850=head3 Creating tests
851
852 mundus:~/MyApp chansen$ cat t/01app.t | perl -ne 'printf( "%2d %s", $., $_ )'
853 1 use Test::More tests => 2;
854 2 BEGIN { use_ok( Catalyst::Test, 'MyApp' ) }
855 3
856 4 ok( request('/')->is_success );
857
858The first line declares how many tests we are going to run, in this case
859two. The second line tests and loads our application in test mode. The
860fourth line verifies that our application returns a successful response.
861
862C<Catalyst::Test> exports two functions, C<request> and C<get>. Each can
863take three different arguments:
864
865=over 4
866
867=item A string which is a relative or absolute URI.
868
869 request('/my/path');
870 request('http://www.host.com/my/path');
871
872=item An instance of C<URI>.
873
874 request( URI->new('http://www.host.com/my/path') );
875
876=item An instance of C<HTTP::Request>.
877
878 request( HTTP::Request->new( GET => 'http://www.host.com/my/path') );
879
880=back
881
882C<request> returns an instance of C<HTTP::Response> and C<get> returns the
883content (body) of the response.
884
885=head3 Running tests locally
886
887 mundus:~/MyApp chansen$ CATALYST_DEBUG=0 TEST_POD=1 prove --lib lib/ t/
888 t/01app............ok
889 t/02pod............ok
890 t/03podcoverage....ok
891 All tests successful.
892 Files=3, Tests=4, 2 wallclock secs ( 1.60 cusr + 0.36 csys = 1.96 CPU)
893
894C<CATALYST_DEBUG=0> ensures that debugging is off; if it's enabled you
895will see debug logs between tests.
896
897C<TEST_POD=1> enables POD checking and coverage.
898
899C<prove> A command-line tool that makes it easy to run tests. You can
900find out more about it from the links below.
901
902=head3 Running tests remotely
903
904 mundus:~/MyApp chansen$ CATALYST_SERVER=http://localhost:3000/ prove --lib lib/ t/01app.t
905 t/01app....ok
906 All tests successful.
907 Files=1, Tests=2, 0 wallclock secs ( 0.40 cusr + 0.01 csys = 0.41 CPU)
908
909C<CATALYST_SERVER=http://localhost:3000/> is the absolute deployment URI of
910your application. In C<CGI> or C<FastCGI> it should be the host and path
911to the script.
912
913=head3 C<Test::WWW::Mechanize> and Catalyst
914
915Be sure to check out C<Test::WWW::Mechanize::Catalyst>. It makes it easy to
916test HTML, forms and links. A short example of usage:
917
918 use Test::More tests => 6;
919 BEGIN { use_ok( Test::WWW::Mechanize::Catalyst, 'MyApp' ) }
920
921 my $mech = Test::WWW::Mechanize::Catalyst->new;
922 $mech->get_ok("http://localhost/", 'Got index page');
923 $mech->title_like( qr/^MyApp on Catalyst/, 'Got right index title' );
924 ok( $mech->find_link( text_regex => qr/^Wiki/i ), 'Found link to Wiki' );
925 ok( $mech->find_link( text_regex => qr/^Mailing-List/i ), 'Found link to Mailing-List' );
926 ok( $mech->find_link( text_regex => qr/^IRC channel/i ), 'Found link to IRC channel' );
927
928=head3 Further Reading
929
930=over 4
931
932=item Catalyst::Test
933
934L<Catalyst::Test>
935
936=item Test::WWW::Mechanize::Catalyst
937
938L<http://search.cpan.org/dist/Test-WWW-Mechanize-Catalyst/lib/Test/WWW/Mechanize/Catalyst.pm>
939
940=item Test::WWW::Mechanize
941
942L<http://search.cpan.org/dist/Test-WWW-Mechanize/Mechanize.pm>
943
944=item WWW::Mechanize
945
946L<http://search.cpan.org/dist/WWW-Mechanize/lib/WWW/Mechanize.pm>
947
948=item LWP::UserAgent
949
950L<http://search.cpan.org/dist/libwww-perl/lib/LWP/UserAgent.pm>
951
952=item HTML::Form
953
954L<http://search.cpan.org/dist/libwww-perl/lib/HTML/Form.pm>
955
956=item HTTP::Message
957
958L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Message.pm>
959
960=item HTTP::Request
961
962L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Request.pm>
963
964=item HTTP::Request::Common
965
966L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Request/Common.pm>
967
968=item HTTP::Response
969
970L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Response.pm>
971
972=item HTTP::Status
973
974L<http://search.cpan.org/dist/libwww-perl/lib/HTTP/Status.pm>
975
976=item URI
977
978L<http://search.cpan.org/dist/URI/URI.pm>
979
980=item Test::More
981
982L<http://search.cpan.org/dist/Test-Simple/lib/Test/More.pm>
983
984=item Test::Pod
985
986L<http://search.cpan.org/dist/Test-Pod/Pod.pm>
987
988=item Test::Pod::Coverage
989
990L<http://search.cpan.org/dist/Test-Pod-Coverage/Coverage.pm>
991
992=item prove (Test::Harness)
993
994L<http://search.cpan.org/dist/Test-Harness/bin/prove>
995
996=back
997
998=head3 More Information
999
1000L<http://search.cpan.org/perldoc?Catalyst::Plugin::Authorization::Roles>
1001L<http://search.cpan.org/perldoc?Catalyst::Plugin::Authorization::ACL>
1002
1003=head1 AUTHORS
1004
1005Catalyst Contributors, see Catalyst.pm
1006
1007=head1 COPYRIGHT
1008
1009This library is free software. You can redistribute it and/or modify it under
1010the same terms as Perl itself.
1011
1012=cut