File Coverage

blib/lib/HTTP/WebTest/API.pm
Criterion Covered Total %
statement 177 177 100.0
branch 37 38 97.3
condition 6 10 60.0
subroutine 32 32 100.0
pod 0 20 0.0
total 252 277 90.9


line stmt bran cond sub pod time code
1             # $Id: API.pm,v 1.29 2003/03/02 11:52:10 m_ilya Exp $
2              
3             # note that it is not package HTTP::WebTest::API. That's right
4             package HTTP::WebTest;
5              
6             =head1 NAME
7              
8             HTTP::WebTest::API - API of HTTP::WebTest
9              
10             =head1 SYNOPSIS
11              
12             use HTTP::WebTest;
13              
14             my $webtest = new HTTP::WebTest;
15              
16             # run test from file
17             $webtest->run_wtscript('script.wt');
18              
19             # or (to pass test parameters as method arguments)
20             $webtest->run_tests($tests);
21              
22             =head1 DESCRIPTION
23              
24             This document describes Perl API of C.
25              
26             =head1 METHODS
27              
28             =cut
29              
30 20     20   548 use 5.005;
  20         76  
  20         1194  
31 20     20   110 use strict;
  20         38  
  20         908  
32              
33 20     20   24664 use IO::File;
  20         251842  
  20         3600  
34 20     20   32110 use LWP::UserAgent;
  20         27639280  
  20         1108  
35 20     20   37356 use Time::HiRes qw(time);
  20         50148  
  20         118  
36              
37 20     20   65760 use HTTP::WebTest::Cookies;
  20         74  
  20         734  
38 20     20   134 use HTTP::WebTest::Utils qw(make_access_method load_package);
  20         40  
  20         1760  
39 20     20   16226 use HTTP::WebTest::Plugin;
  20         60  
  20         860  
40 20     20   14914 use HTTP::WebTest::Request;
  20         58  
  20         1090  
41 20     20   13900 use HTTP::WebTest::Test;
  20         52  
  20         1222  
42              
43             # BACKWARD COMPATIBILITY BITS - exporting this subroutine is a part of
44             # HTTP-WebTest 1.xx API
45              
46 20     20   150 use base qw(Exporter);
  20         34  
  20         2868  
47 20     20   118 use vars qw(@EXPORT_OK);
  20         42  
  20         48960  
48             @EXPORT_OK = qw(run_web_test);
49              
50             =head2 new ()
51              
52             Constructor.
53              
54             =head3 Returns
55              
56             A new C object.
57              
58             =cut
59              
60             sub new {
61 12     12 0 892 my $class = shift;
62              
63 12         575766 my $self = bless {}, $class;
64              
65 12         129 return $self;
66             }
67              
68             =head2 run_tests ($tests, $optional_params)
69              
70             Runs a test sequence.
71              
72             =head3 Parameters
73              
74             =over 4
75              
76             =item * $test
77              
78             A reference to an array that contains test objects.
79              
80             =item * $optional_params
81              
82             A reference to a hash that contains optional global parameters for test.
83              
84             =back
85              
86             =cut
87              
88             sub run_tests {
89 82     82 0 146868 my $self = shift;
90 82         154 my $tests = shift;
91 82   50     315 my $params = shift || {};
92              
93 82         447 $self->reset_plugins;
94              
95             # reset current test object
96 82         353 $self->current_test(undef);
97              
98             # convert tests to canonic representation
99 82         511 my @tests = $self->convert_tests(@$tests);
100              
101 82         842 $self->tests([ @tests ]);
102 82         352 $self->_global_test_params($params);
103              
104             # start tests hook; note that plugins can load other plugins and
105             # modify $self->plugins in start tests hook
106 82         190 my %initialized = ();
107             {
108 82         119 my $done = 1;
  189         295  
109              
110 189         280 my @plugins = @{$self->plugins};
  189         662  
111 189         525 for my $plugin (@plugins) {
112 1566 100       4830 unless($initialized{$plugin}) {
113 683 100       3505 if($plugin->can('start_tests')) {
114 175         1135 $plugin->start_tests;
115             }
116 683         2186 $initialized{$plugin} = 1;
117             # we must do one more round to check for uninitialized
118             # plugins
119 683         1328 $done = 0;
120             }
121             }
122              
123 189 100       844 redo unless $done;
124             }
125              
126             # run all tests: note that content and length of @{$self->tests}
127             # may change inside the loop so idiomatic "for my $i (...)"
128             # doesn't work here
129 82         167 for(my $i = 0; $i < @{$self->tests}; $i ++) {
  271         3468  
130 193         636 my $test = $self->tests->[$i];
131 193         953 $self->current_test_num($i);
132 193         1008 $self->run_test($test, $self->_global_test_params);
133             }
134              
135             # end tests hook
136 78         196 for my $plugin (@{$self->plugins}) {
  78         298  
137 647 100       3203 if($plugin->can('end_tests')) {
138 85         339 $plugin->end_tests;
139             }
140             }
141             }
142              
143             =head2 run_wtscript ($wtscript, $optional_params)
144              
145             Reads wtscript and runs tests it defines.
146              
147             =head3 Parameters
148              
149             =over 4
150              
151             =item * $wtscript
152              
153             Either the name of wtscript file or wtscript passed as string. Very
154             simple heuristic is used distinguish first from second. If
155             C<$wtscript> contains either C<\n> or C<\r> it is treated as a
156             wtscript string. Otherwise, it is treated as a file name.
157              
158             =item * $optional_params
159              
160             =back
161              
162             A reference to a hash that contains optional test parameters that can
163             override parameters defined in wtscript.
164              
165             =cut
166              
167             sub run_wtscript {
168 4     4 0 28 my $self = shift;
169 4         6 my $wtscript = shift;
170 4   50     19 my $opts_override = shift || {};
171              
172 4 100       43 unless($wtscript =~ /[\r\n]/) {
173 3         77 my $fh = new IO::File;
174 3         295 my $file = $wtscript;
175 3 50       40 $fh->open("< $file") or
176             die "HTTP::WebTest: Can't open file $file: $!";
177              
178 3         272 $wtscript = join '', <$fh>;
179 3         34 $fh->close;
180             }
181              
182 4         71 my ($tests, $opts) = $self->parse($wtscript);
183              
184 4         32 $self->run_tests($tests, { %$opts, %$opts_override });
185             }
186              
187             =head2 num_fail ()
188              
189             =head3 Returns
190              
191             The number of failed tests.
192              
193             =cut
194              
195             sub num_fail {
196 7     7 0 18 my $self = shift;
197              
198 7         13 my $fail = 0;
199              
200 7         13 for my $test (@{$self->tests}) {
  7         24  
201 13         42 my $results = $test->results;
202              
203 13         25 for my $result (@$results) {
204 20         51 for my $subresult (@$result[1 .. @$result - 1]) {
205 20 100       52 $fail ++ unless $subresult;
206             }
207             }
208             }
209              
210 7         40 return $fail;
211             }
212              
213             =head2 num_succeed ()
214              
215             =head3 Returns
216              
217             The number of passed tests.
218              
219             =cut
220              
221             sub num_succeed {
222 3     3 0 6 my $self = shift;
223              
224 3         20 my $succeed = 0;
225              
226 3         7 for my $test (@{$self->tests}) {
  3         11  
227 7         22 my $results = $test->results;
228              
229 7         18 for my $result (@$results) {
230 10         27 for my $subresult (@$result[1 .. @$result - 1]) {
231 10 100       30 $succeed ++ if $subresult;
232             }
233             }
234             }
235              
236 3         20 return $succeed;
237             }
238              
239             =head2 have_succeed ()
240              
241             =head3 Returns
242              
243             True if all tests have passed, false otherwise.
244              
245             =cut
246              
247             sub have_succeed {
248 4     4 0 10 my $self = shift;
249              
250 4 100       12 $self->num_fail > 0 ? 0 : 1;
251             }
252              
253             =head2 parser_package($optional_parser_package)
254              
255             If $optional_parser is defined sets a parser package to use when
256             parsing wtscript files. Otherwise just returns current parser package.
257              
258             =head3 Returns
259              
260             The parser package.
261              
262             =cut
263              
264             *parser_package = make_access_method('PARSER_PACKAGE',
265             sub { 'HTTP::WebTest::Parser' });
266              
267             =head2 parse ($data)
268              
269             Parses test specification in wtscript format.
270              
271             =head3 Parameters
272              
273             =over 4
274              
275             =item * $data
276              
277             Scalar that contains test specification in wtscript format.
278              
279             =back
280              
281             =head3 Returns
282              
283             A list of two elements. First element is a reference to an array that
284             contains test objects. Second element is a reference to a hash that
285             contains optional global test parameters.
286              
287             It can be passed directly to C.
288              
289             =head3 Example
290              
291             $webtest->run_tests($webtest->parse($data));
292              
293             =cut
294              
295             sub parse {
296 7     7 0 25 my $self = shift;
297 7         16 my $data = shift;
298              
299 7 100       57 load_package('HTTP::WebTest::Parser')
300             unless(UNIVERSAL::can($self->parser_package, 'parse'));
301              
302 7         40 my ($tests, $opts) = $self->parser_package->parse($data);
303              
304 7         39 return ($tests, $opts);
305             }
306              
307             =head1 LOW-LEVEL API METHODS
308              
309             Most users don't need to use this part of C API
310             directly. It could be useful for users who want to:
311              
312             =over 4
313              
314             =item *
315              
316             Write an C plugin.
317              
318             =item *
319              
320             Get access to L,
321             L,
322             L and
323             other objects used by C during runing test sequence.
324              
325             =back
326              
327             =head2 tests ()
328              
329             =head3 Returns
330              
331             A reference to an array that contains test objects.
332              
333             =cut
334              
335             *tests = make_access_method('TESTS', sub { [] });
336              
337             =head2 user_agent ($optional_user_agent)
338              
339             If $optional_user_agent is a user agent object,
340             it is used by the C object for all requests.
341             If $optional_user_agent is passed as undef, the HTTP::WebTest object is
342             reset to use the default user agent.
343              
344             =head3 Returns
345              
346             The user agent object used by the C object.
347              
348             =cut
349              
350             *user_agent = make_access_method('USER_AGENT', 'create_user_agent');
351              
352             =head2 plugins ($optional_plugins)
353              
354             If C<$optional_plugins> is a reference to an array that contains plugin
355             objects, the C object uses these plugins while running tests.
356             If C<$optional_plugins> is passed as
357             undef, the C object is reset to use the default set of plugins.
358              
359             =head3 Returns
360              
361             A reference to an array that contains plugin objects. If you
362             add or remove plugin objects in this array, you will change the set of
363             plugins used by C object during tests.
364              
365             =cut
366              
367             *plugins = make_access_method('PLUGINS', 'default_plugins');
368              
369             =head2 create_user_agent ()
370              
371             =head3 Returns
372              
373             A new L object, initialized with default
374             settings.
375              
376             =cut
377              
378             sub create_user_agent {
379 15     15 0 30 my $self = shift;
380              
381             # create user agent
382 15         614 my $user_agent = new LWP::UserAgent;
383              
384             # create cookie jar
385 15         58605 $user_agent->cookie_jar(new HTTP::WebTest::Cookies);
386              
387 15         2689 return $user_agent;
388             }
389              
390             =head2 reset_user_agent ()
391              
392             Resets the user agent to the default.
393              
394             =cut
395              
396             sub reset_user_agent {
397 2     2 0 22 my $self = shift;
398              
399 2         13 $self->user_agent(undef);
400             }
401              
402             =head2 reset_plugins ()
403              
404             Resets the set of plugin objects to the default set.
405              
406             =cut
407              
408             sub reset_plugins {
409 82     82 0 159 my $self = shift;
410              
411 82         547 $self->plugins(undef);
412             }
413              
414             =head2 default_plugins ()
415              
416             =head3 Returns
417              
418             A reference to the set of default plugin objects.
419              
420             =cut
421              
422             sub default_plugins {
423 83     83 0 149 my $self = shift;
424              
425 83         264 my @plugins = ();
426              
427 83         325 for my $sn_package (qw(Loader SetRequest Cookies
428             StatusTest TextMatchTest
429             ContentSizeTest ResponseTimeTest
430             DefaultReport)) {
431 664         1375 my $package = "HTTP::WebTest::Plugin::$sn_package";
432              
433 664         2251 load_package($package);
434              
435 664         2887 push @plugins, $package->new($self);
436             }
437              
438 83         583 return [@plugins];
439             }
440              
441             # accessor method for global test parameters data
442             *_global_test_params = make_access_method('GLOBAL_TEST_PARAMS');
443              
444             =head2 global_test_param ($param)
445              
446             =head3 Returns
447              
448             The value of the global test parameter C<$param>.
449              
450             =cut
451              
452             sub global_test_param {
453 14212     14212 0 21600 my $self = shift;
454 14212         20985 my $param = shift;
455              
456 14212         51126 return $self->_global_test_params->{$param};
457             }
458              
459             =head2 current_test_num ()
460              
461             =head3 Returns
462              
463             The number of the current test or, if no test is running, the current test run.
464              
465             =cut
466              
467             *current_test_num = make_access_method('CURRENT_TEST_NUM');
468              
469             =head2 current_test ()
470              
471             =head3 Returns
472              
473             The L object which corresponds
474             to the current test or, if no test is running, the current test run.
475              
476             =cut
477              
478             *current_test = make_access_method('CURRENT_TEST');
479              
480             =head2 current_request ()
481              
482             =head3 Returns
483              
484             The L object used in current test.
485              
486             =cut
487              
488 944     944 0 3726 sub current_request { shift->current_test->request(@_) }
489              
490             =head2 current_response ()
491              
492             =head3 Returns
493              
494             The L object used in current test.
495              
496             =cut
497              
498 1118     1118 0 3830 sub current_response { shift->current_test->response(@_) }
499              
500             =head2 current_response_time ()
501              
502             =head3 Returns
503              
504             The response time for the HTTP request used in current test.
505              
506             =cut
507              
508 380     380 0 1937 sub current_response_time { shift->current_test->response_time(@_) }
509              
510             =head2 current_results ()
511              
512             =head3 Returns
513              
514             A reference to an array that contains the results of checks made by plugins
515             for the current test.
516              
517             =cut
518              
519 362     362 0 1534 sub current_results { shift->current_test->results(@_) }
520              
521             =head2 run_test ($test, $optional_params)
522              
523             Runs a single test.
524              
525             =head3 Parameters
526              
527             =over 4
528              
529             =item * $test
530              
531             A test object.
532              
533             =item * $optional_params
534              
535             A reference to a hash that contains optional global test parameters.
536              
537             =back
538              
539             =cut
540              
541             sub run_test {
542 194     194 0 11985 my $self = shift;
543 194         372 my $test = shift;
544 194   100     691 my $params = shift || {};
545              
546             # convert test to canonic representation
547 194         718 $test = $self->convert_tests($test);
548 194         835 $self->current_test($test);
549              
550 194         5190 $self->_global_test_params($params);
551              
552             # create request (note that actual uri is more likely to be
553             # set in plugins)
554 194         2717 my $request = HTTP::WebTest::Request->new('GET' =>
555             'http://MISSING_HOSTNAME/');
556 194         2299 $self->current_request($request);
557              
558             # set request object with plugins
559 194         409 for my $plugin (@{$self->plugins}) {
  194         599  
560 1612 100       12605 if($plugin->can('prepare_request')) {
561 435         2188 $plugin->prepare_request;
562             }
563             }
564              
565             # check if one of plugins did change request uri
566 194 100       1964 if($request->uri eq 'http://MISSING_HOSTNAME/') {
567 4         105 die "HTTP::WebTest: request uri is not set";
568             }
569              
570             # measure current time
571 190         2166 my $time1 = time;
572              
573             # get response
574 190         769 my $response = $self->user_agent->request($request);
575 190         64579 $self->current_response($response);
576              
577             # measure current time
578 190         1138 my $time2 = time;
579              
580             # calculate response time
581 190         998 $self->current_response_time($time2 - $time1);
582              
583             # init results
584 190         576 my @results = ();
585              
586             # check response with plugins
587 190         361 for my $plugin (@{$self->plugins}) {
  190         965  
588 1576 100       11744 if($plugin->can('check_response')) {
589 970         6109 push @results, $plugin->check_response;
590             }
591             }
592 190         877 $self->current_results(\@results);
593              
594             # report test results
595 190         1298 for my $plugin (@{$self->plugins}) {
  190         691  
596 1576 100       7126 if($plugin->can('report_test')) {
597 195         1064 $plugin->report_test;
598             }
599             }
600             }
601              
602             =head2 convert_tests (@tests)
603              
604             Converts test objects C<@tests> of any supported type to internal
605             canonical representation (i.e. to
606             L objects).
607              
608             =head3 Returns
609              
610             A list of L objects (list
611             context) or the first value from a list of
612             L objects (scalar context).
613              
614             =cut
615              
616             sub convert_tests {
617 278     278 0 1032 my $self = shift;
618 278         635 my @tests = @_;
619              
620 278         3133 my @conv = map HTTP::WebTest::Test->convert($_), @tests;
621              
622 278 100       1391 return wantarray ? @conv : $conv[0];
623             }
624              
625             =head1 BACKWARD COMPATIBILITY
626              
627             C offers a richer API than its predecessor
628             C. The old API is still supported, but may be
629             deprecated in the future and is not recommended.
630              
631             =cut
632              
633             =head2 web_test ($file, $num_fail_ref, $num_succeed_ref, $optional_options)
634              
635             Reads wtscript file and runs tests it defines.
636              
637             In C you should use method C.
638              
639             =head3 Parameters
640              
641             =over 4
642              
643             =item * $file
644              
645             Name of a wtscript file.
646              
647             =item * $num_fail_ref
648              
649             A reference on scalar where a number of failed tests will be stored or
650             C if you don't need it.
651              
652             =item * $num_succed_ref
653              
654             A reference on scalar where a number of passed tests will be stored or
655             C if you don't need it.
656              
657             =item * $optional_params
658              
659             A reference to a hash that contains optional test parameters which can
660             override parameters defined in wtscript.
661              
662             =back
663              
664             =cut
665              
666             sub web_test {
667 2     2 0 45 my $self = shift;
668 2         12 my $file = shift;
669 2         3 my $num_fail_ref = shift;
670 2         3 my $num_succeed_ref = shift;
671 2   50     15 my $opts = shift || {};
672              
673 2         15 $self->run_wtscript($file, $opts);
674              
675 2 100       13 $$num_fail_ref = $self->num_fail if defined $num_fail_ref;
676 2 100       19 $$num_succeed_ref = $self->num_succeed if defined $num_succeed_ref;
677              
678 2         11 return $self->have_succeed;
679             }
680              
681             =head2 run_web_test ($tests, $num_fail_ref, $num_succeed_ref, $optional_options)
682              
683             This is not a method. It is subroutine which creates a
684             C object and runs test sequence using it.
685              
686             You need to either import C into you namespace with
687              
688             use HTTP::WebTest qw(run_web_test);
689              
690             or use the full name C
691              
692             In C you should use the method C.
693              
694             =head3 Parameters
695              
696             =over 4
697              
698             =item * $tests
699              
700             A reference to an array that contains a set of test objects.
701              
702             =item * $num_fail_ref
703              
704             A reference to a scalar where the number of failed tests will be stored or
705             C if you don't need it.
706              
707             =item * $num_succed_ref
708              
709             A reference to a scalar where the number of passed tests will be stored or
710             C if you don't need it.
711              
712             =item * $optional_params
713              
714             A reference to a hash that contains optional test parameters.
715              
716             =back
717              
718             =cut
719              
720             sub run_web_test {
721 2     2 0 467 my $tests = shift;
722 2         4 my $num_fail_ref = shift;
723 2         4 my $num_succeed_ref = shift;
724 2   50     8 my $opts = shift || {};
725              
726 2         17 my $webtest = new HTTP::WebTest;
727              
728 2         8 $webtest->run_tests($tests, $opts);
729              
730 2 100       11 $$num_fail_ref = $webtest->num_fail if defined $num_fail_ref;
731 2 100       10 $$num_succeed_ref = $webtest->num_succeed if defined $num_succeed_ref;
732              
733 2         9 return $webtest->have_succeed;
734             }
735              
736             =head1 COPYRIGHT
737              
738             Copyright (c) 2000-2001 Richard Anderson. All rights reserved.
739              
740             Copyright (c) 2001-2003 Ilya Martynov. All rights reserved.
741              
742             This program is free software; you can redistribute it and/or modify
743             it under the same terms as Perl itself.
744              
745             =head1 SEE ALSO
746              
747             L
748              
749             L
750              
751             L
752              
753             L
754              
755             L
756              
757             L
758              
759             L
760              
761             L
762              
763             L
764              
765             L
766              
767             =cut
768              
769             1;