home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Tests.pm < prev    next >
Encoding:
Perl POD Document  |  2003-11-12  |  21.7 KB  |  926 lines

  1. package HTML::Mason::Tests;
  2.  
  3. use strict;
  4.  
  5. use Cwd;
  6.  
  7. use File::Path;
  8. use File::Spec;
  9.  
  10. use HTML::Mason;
  11. use HTML::Mason::Compiler::ToObject;
  12. use HTML::Mason::Tools qw(make_fh);
  13.  
  14. use Getopt::Long;
  15.  
  16. use vars qw($VERBOSE $DEBUG @SHARED);
  17.  
  18. $VERBOSE = $ENV{MASON_DEBUG} || $ENV{MASON_VERBOSE} || $ENV{TEST_VERBOSE};
  19. $DEBUG = $ENV{MASON_DEBUG};
  20.  
  21. $| = 1;
  22.  
  23. @SHARED = ( { path => '/shared/check_error',
  24.           component => <<'EOF',
  25. <% ($error) ? "Error: $error" : "No error!?" %>
  26. <%init>
  27. if ($error) {
  28.   my @lines = split("\n",$error);
  29.   $error = join("\n",@lines[0..$lines-1]);
  30.   $error =~ s{\s+at .*}{}g;
  31. }
  32. </%init>
  33. <%args>
  34. $error
  35. $lines=>1
  36. </%args>
  37. EOF
  38.         },
  39.         { path => '/shared/display_comp_obj',
  40.           component => <<'EOF',
  41. Declared args:
  42. % my %decl = %{$comp->declared_args};
  43. % foreach (sort keys %decl) {
  44. <% $_ %><% (defined($decl{$_}->{default})) ? "=>".$decl{$_}->{default} : "" %>
  45. % }
  46.  
  47. I am <% $comp->is_subcomp ? '' : 'not ' %>a subcomponent.
  48. I am <% $comp->is_method ? '' : 'not ' %>a method.
  49. I am <% $comp->is_file_based ? '' : 'not ' %>file-based.
  50. % if (defined($comp->name)) {
  51. My short name is <% $comp->name =~ /anon/ ? '[anon something]' : $comp->name %>.
  52. % }
  53. % if ($comp->is_subcomp and defined($comp->owner)) {
  54. My parent component is <% $comp->owner->title %>.
  55. % }
  56. % if (defined($comp->dir_path)) {
  57. My directory is <% $comp->dir_path %>.
  58. % }
  59. % my @subkeys = sort keys(%{$comp->subcomps});
  60. I have <% scalar(@subkeys) %> subcomponent(s).
  61. % if (@subkeys) {
  62. Including one called <% $comp->subcomps($subkeys[0])->name %>.
  63. % }
  64. My title is <% $comp->title =~ /anon/ ? '[anon something]' : $comp->title %>.
  65.  
  66. % if (defined($comp->path)) {
  67. My path is <% $comp->path %>.
  68. % }
  69. % if (defined($comp->comp_id)) {
  70. My comp_id is <% $comp->comp_id =~ /anon/ ? '[anon something]' : $comp->comp_id %>.
  71. % }
  72. <%args>
  73. $comp
  74. </%args>
  75. EOF
  76.         },
  77.             { path => '/shared/display_req_obj',
  78.               component => <<'EOF',
  79. My depth is <% $m->depth %>.
  80.  
  81. The top-level component is <% $m->request_comp->title %>.
  82.  
  83. My stack looks like:
  84. -----
  85. % foreach my $comp ($m->callers) {
  86. <% $comp->title %>
  87. % }
  88. -----
  89.  
  90. EOF
  91.             },
  92.       );
  93.  
  94. #
  95. # Get command options here so that we read tests_class before user
  96. # calls new().
  97. #
  98. my %cmd_options;
  99. GetOptions( 'create' => \$cmd_options{create},
  100.         'tests-to-run=s' => \$cmd_options{tests_to_run},
  101.         'tests-to-skip=s' => \$cmd_options{tests_to_skip},
  102.         'tests-class=s' => \$cmd_options{tests_class},
  103.         );
  104.  
  105. #
  106. # Allow options to be passed in the environment as well.
  107. #
  108. $cmd_options{tests_to_run} = $ENV{MASON_TESTS_TO_RUN}
  109.     if !defined($cmd_options{tests_to_run}) and defined($ENV{MASON_TESTS_TO_RUN});
  110. $cmd_options{tests_to_skip} = $ENV{MASON_TESTS_TO_SKIP}
  111.     if !defined($cmd_options{tests_to_skip}) and defined($ENV{MASON_TESTS_TO_SKIP});
  112. $cmd_options{tests_class} = $ENV{MASON_TESTS_CLASS}
  113.     if !defined($cmd_options{tests_class}) and defined($ENV{MASON_TESTS_CLASS});
  114.  
  115. # If user specifies tests_class, load that package; otherwise,
  116. # default it to this package.
  117. if (defined($cmd_options{tests_class})) {
  118.     eval "use $cmd_options{tests_class}";
  119. } else {
  120.     $cmd_options{tests_class} = __PACKAGE__;
  121. }
  122.  
  123. my %tests_to_run;
  124. if ($cmd_options{tests_to_run}) {
  125.     for ($cmd_options{tests_to_run}) { s/^\s+//; s/\s+$// }
  126.     my @tests_to_run = sort { $a <=> $b } split(/\s*,\s*/, $cmd_options{tests_to_run});
  127.     %tests_to_run = map { ($_, 1) } @tests_to_run;
  128.     printf ("Running only test%s %s\n", @tests_to_run == 1 ? "" : "s", join(", ", @tests_to_run));
  129. }
  130.  
  131. my %tests_to_skip;
  132. if ($cmd_options{tests_to_skip}) {
  133.     for ($cmd_options{tests_to_skip}) { s/^\s+//; s/\s+$// }
  134.     my @tests_to_skip = split(/\s*,\s*/, $cmd_options{tests_to_skip});
  135.     %tests_to_skip = map { ($_, 1) } @tests_to_skip;
  136.     printf ("Skipping test%s %s\n", @tests_to_skip == 1 ? "" : "s", join(", ", @tests_to_skip));
  137. }
  138.  
  139. sub new
  140. {
  141.     my $class = shift;
  142.     my %p = (@_, %cmd_options);
  143.  
  144.     die "No group name provided\n"
  145.     unless exists $p{name};
  146.  
  147.     die "No description for test group provided\n"
  148.     unless exists $p{description};
  149.  
  150.     $p{pre_test_cleanup} = 1
  151.         unless exists $p{pre_test_cleanup};
  152.  
  153.     return bless {
  154.           %p,
  155.           support => [],
  156.           tests => [],
  157.          }, $class;
  158. }
  159.  
  160. # Returns the tests class to use for class methods - defaults to this package.
  161. sub tests_class
  162. {
  163.     return $cmd_options{tests_class};
  164. }
  165.  
  166. sub add_support
  167. {
  168.     my $self = shift;
  169.     my %p = @_;
  170.  
  171.     die "'support' key array member contains no 'path' key\n"
  172.     unless exists $p{path};
  173.  
  174.     die "'support' key array member contains no 'component' key\n"
  175.     unless exists $p{component};
  176.  
  177.     push @{ $self->{support} }, \%p;
  178. }
  179.  
  180. sub add_test
  181. {
  182.     my $self = shift;
  183.     my %p = @_;
  184.  
  185.     die "no name provided for test\n"
  186.     unless exists $p{name};
  187.  
  188.     $self->{test_count}++;
  189.     
  190.     
  191.     unless ( exists $p{path} )
  192.     {
  193.     $p{path} = $p{call_path} || $p{name};
  194.     }
  195.  
  196.     my $call_path = "/$self->{name}";
  197.     if ( exists $p{call_path} )
  198.     {
  199.     $call_path .= '/' unless substr( $p{call_path}, 0, 1 ) eq '/';
  200.     $call_path .= $p{call_path};
  201.     }
  202.     else
  203.     {
  204.     $call_path .= '/' . $p{name};
  205.     }
  206.     $p{call_path} = $call_path;
  207.  
  208.     if ( ref($p{call_args}) eq 'HASH' )
  209.     {
  210.     my @lst = %{$p{call_args}};
  211.     $p{call_args} = \@lst;
  212.     }
  213.     elsif ( !exists($p{call_args}) ) {
  214.     $p{call_args} = [];
  215.     }
  216.  
  217.     die "'$p{name}' test has no description\n"
  218.     unless exists $p{description};
  219.  
  220.     die "'$p{name}' test has no component\n"
  221.     unless exists $p{component} || $p{skip_component};
  222.  
  223.     die "'$p{name}' test has no 'expect' or 'expect_error' key\n"
  224.     unless exists $p{expect} || exists $p{expect_error} || $p{skip_expect} || $self->{create};
  225.  
  226.     foreach ( qw( interp_params ) )
  227.     {
  228.     die "$_ must be a hash reference"
  229.         if exists $p{$_} && ! UNIVERSAL::isa( $p{$_}, 'HASH' );
  230.     }
  231.  
  232.     push @{ $self->{tests} }, \%p;
  233. }
  234.  
  235. sub run
  236. {
  237.     my $self = shift;
  238.  
  239.     die "No tests exist in this group"
  240.     unless @{ $self->{tests} };
  241.  
  242.     if ($DEBUG)
  243.     {
  244.     print "Will " . ( $self->{create} ? '' : 'not ' ) . "create 'expect' files\n";
  245.     }
  246.  
  247.     $self->{test_count} = 0;
  248.  
  249.     eval
  250.     {
  251.         # 1 indicates to be silent on missing directories
  252.     $self->_cleanup(1) if $self->{pre_test_cleanup};
  253.     $self->_make_dirs;
  254.     $self->_write_shared_comps;
  255.     $self->_write_support_comps;
  256.     $self->_run_tests;
  257.     };
  258.  
  259.     $self->_cleanup unless $ENV{MASON_NO_CLEANUP};
  260.  
  261.     die $@ if $@;
  262. }
  263.  
  264. sub _make_dirs
  265. {
  266.     my $self = shift;
  267.  
  268.     my $comp_root = $self->comp_root;
  269.     my $data_dir = $self->data_dir;
  270.  
  271.     unless ( -d $self->comp_root )
  272.     {
  273.     print "Making comp_root directory: $comp_root\n" if $DEBUG;
  274.     mkpath( $self->comp_root, 0, 0755 )
  275.         or die "Unable to make base test directory '$comp_root': $!";
  276.     }
  277.  
  278.     unless ( -d $self->data_dir )
  279.     {
  280.     print "Making data_dir directory: $data_dir\n" if $DEBUG;
  281.     mkpath( $self->data_dir, 0, 0755 )
  282.         or die "Unable to make base test directory '$data_dir': $!";
  283.     }
  284. }
  285.  
  286. sub base_path
  287. {
  288.     my $proto = shift;
  289.  
  290.     if (ref $proto)
  291.     {
  292.     $proto->{base_path} ||= File::Spec->catdir( cwd(), 'mason_tests' );
  293.     return $proto->{base_path};
  294.     }
  295.     else
  296.     {
  297.     return File::Spec->catdir( cwd(), 'mason_tests' );
  298.     }
  299. }
  300.  
  301. sub comp_root
  302. {
  303.     my $proto = shift;
  304.  
  305.     return File::Spec->catdir( $proto->base_path, 'comps' );
  306. }
  307.  
  308. sub data_dir
  309. {
  310.     my $proto = shift;
  311.  
  312.     return File::Spec->catdir( $proto->base_path, 'data' );
  313. }
  314.  
  315. sub _write_shared_comps
  316. {
  317.     my $self = shift;
  318.  
  319.     return unless @SHARED;
  320.  
  321.     foreach my $comp ( @SHARED )
  322.     {
  323.     my @path = split m(/), $comp->{path};
  324.     my $file = pop @path;
  325.  
  326.     my $dir = File::Spec->catdir( $self->comp_root, @path );
  327.  
  328.     $self->write_comp( $comp->{path}, $dir, $file, $comp->{component} );
  329.     }
  330. }
  331.  
  332. sub _write_support_comps
  333. {
  334.     my $self = shift;
  335.  
  336.     unless ( @{ $self->{support} } )
  337.     {
  338.     print "No support comps to create\n" if $DEBUG;
  339.     return;
  340.     }
  341.  
  342.     foreach my $supp ( @{ $self->{support} } )
  343.     {
  344.     my @path = split m(/), $supp->{path};
  345.     my $file = pop @path;
  346.  
  347.     my $dir = File::Spec->catdir( $self->comp_root, $self->{name}, @path );
  348.  
  349.     $self->write_comp( $supp->{path}, $dir, $file, $supp->{component} );
  350.     }
  351. }
  352.  
  353. sub _write_test_comp
  354. {
  355.     my $self = shift;
  356.     my $test = $self->{current_test};
  357.  
  358.     my @path = split m(/), $test->{path};
  359.     my $file = pop @path;
  360.  
  361.     my $dir = File::Spec->catdir( $self->comp_root, $self->{name}, @path );
  362.     unless ( -d $dir )
  363.     {
  364.     print "Making dir: $dir\n" if $DEBUG;
  365.     mkpath( $dir, 0, 0755 )
  366.         or die "Unable to create directory '$dir': $!";
  367.     }
  368.  
  369.     $self->write_comp( $test->{path}, $dir, $file, $test->{component} );
  370. }
  371.  
  372. sub write_comp
  373. {
  374.     my $self = shift;
  375.     my ($path, $dir, $file, $component) = @_;
  376.  
  377.     unless (-d $dir)
  378.     {
  379.     print "Making dir: $dir\n" if $DEBUG;
  380.     mkpath( $dir, 0, 0755 )
  381.         or die "Unable to create directory '$dir': $!";
  382.     }
  383.  
  384.     my $real_file = File::Spec->catfile( $dir, $file );
  385.  
  386.     print "Making component $path at $real_file\n"
  387.     if $DEBUG;
  388.  
  389.     my $fh = make_fh();
  390.     open $fh, ">$real_file"
  391.     or die "Unable to write to '$real_file': $!";
  392.     print $fh $component
  393.     or die "Unable to write to '$real_file': $!";
  394.     close $fh
  395.     or die "Unable to write to '$real_file': $!";
  396. }
  397.  
  398. sub _run_tests
  399. {
  400.     my $self = shift;
  401.  
  402.     my $count = scalar @{ $self->{tests} };
  403.     print "\n1..$count\n";
  404.  
  405.     if ($VERBOSE)
  406.     {
  407.     print "Running $self->{name} tests ($count tests): $self->{description}\n";
  408.     }
  409.  
  410.     my $x = 1;
  411.     foreach my $test ( @{ $self->{tests} } )
  412.     {
  413.     $self->{current_test} = $test;
  414.     
  415.     #
  416.     # If tests_to_run or tests_to_skip were specified in the
  417.     # environment or command line, check them to see whether to
  418.     # run the test.
  419.     #
  420.     if (%tests_to_run or %tests_to_skip) {
  421.  
  422.         # Look for any of the specs [test_file_name:](test_number|test_name|*)
  423.         my $wildcard_name = join(":", $self->{name}, "*");
  424.         my $full_name = join(":", $self->{name}, $test->{name});
  425.         my $full_number = join(":", $self->{name}, $x);
  426.         my @all_specs = ($x, $test->{name}, $full_name, $full_number, $wildcard_name);
  427.  
  428.         # If our test isn't mentioned in %tests_to_run or is
  429.         # mentioned in %tests_to_skip, skip it.
  430.         #
  431.         if ((%tests_to_run and !(grep { $tests_to_run{$_} } @all_specs))
  432.         or (%tests_to_skip and (grep { $tests_to_skip{$_} } @all_specs))) {
  433.  
  434.         # Use presence of PERL_DL_NONLAZY to decide if we are
  435.         # running inside "make test", and if so, actually
  436.         # print the appropriate skip response to comply with the
  437.         # Test::Harness standard. If the user is running the
  438.         # test by hand, this would just be clutter.
  439.         #
  440.         # Checking PERL_DL_NONLAZY is a hack but I don't
  441.         # know of a better detection method.
  442.         #
  443.         $self->_skip if ($ENV{PERL_DL_NONLAZY});
  444.         $x++;
  445.         next;
  446.         }
  447.     }
  448.     print "Running $test->{name} (#$x): $test->{description}\n" if $VERBOSE;
  449.     $self->_make_component unless $test->{skip_component};
  450.     $self->_run_test;
  451.     $x++;
  452.     }
  453. }
  454.  
  455. sub _make_component
  456. {
  457.     my $self = shift;
  458.     my $test = $self->{current_test};
  459.     $self->_write_test_comp;
  460. }
  461.  
  462. sub _make_main_interp
  463. {
  464.     my $self = shift;
  465.     my $test = $self->{current_test};
  466.     return $test->{interp} if $test->{interp};
  467.  
  468.     my %interp_params = ( exists $test->{interp_params} ?
  469.               %{ $test->{interp_params} } :
  470.               () );
  471.  
  472.     if ($DEBUG && %interp_params)
  473.     {
  474.     print "Interp params:\n";
  475.     while ( my ($k, $v) = each %interp_params)
  476.     {
  477.         print "  $k => $v\n";
  478.     }
  479.     }
  480.  
  481.     return $self->_make_interp ( comp_root => $self->comp_root,
  482.                  data_dir  => $self->data_dir,
  483.                  %interp_params );
  484. }
  485.  
  486. sub _make_interp
  487. {
  488.     my ($class, %interp_params) = @_;
  489.  
  490.     return HTML::Mason::Interp->new( %interp_params );
  491. }
  492.  
  493. sub _run_test
  494. {
  495.     my $self = shift;
  496.     my $test = $self->{current_test};
  497.  
  498.     $self->{buffer} = '';
  499.     my $interp = $self->_make_main_interp;
  500.     $interp->out_method( sub { for (@_) { $self->{buffer} .= $_ if defined $_ } } );
  501.  
  502.     eval { $self->_execute($interp) };
  503.  
  504.     return $self->check_result($@);
  505. }
  506.  
  507. sub _execute
  508. {
  509.     my ($self, $interp) = @_;
  510.     my $test = $self->{current_test};
  511.  
  512.     print "Calling $test->{name} test with path: $test->{call_path}\n" if $DEBUG;
  513.     $test->{pretest_code}->() if $test->{pretest_code};
  514.     $interp->exec( $test->{call_path}, @{$test->{call_args}} );
  515. }
  516.  
  517. sub check_result {
  518.     my ($self, $error) = @_;
  519.     my $test = $self->{current_test};
  520.  
  521.     if ($error)
  522.     {
  523.     if ( $test->{expect_error} )
  524.     {
  525.         if ( $@ =~ /$test->{expect_error}/ )
  526.         {
  527.         return $self->_success
  528.         }
  529.         else
  530.         {
  531.         if ($VERBOSE)
  532.         {
  533.             print "Got error:\n$error\n...but expected something matching:\n$test->{expect_error}\n";
  534.         }
  535.         return $self->_fail;
  536.         }
  537.     }
  538.     else
  539.     {
  540.         print "Unexpected error running $test->{name}:\n$error" if $VERBOSE;
  541.         return $self->_fail;
  542.     }
  543.  
  544.     }
  545.     elsif ( $test->{expect_error} )
  546.     {
  547.     print "Expected an error matching '$test->{expect_error}' but no error occurred\n" if $VERBOSE;
  548.     return $self->_fail;
  549.     }
  550.  
  551.     if ($self->{create})
  552.     {
  553.     print "Results for $test->{name}:\n$self->{buffer}\n";
  554.     return;
  555.     }
  556.  
  557.     my $success = $test->{skip_expect} ? 1 : $self->check_output( actual => $self->{buffer}, expect => $test->{expect} );
  558.  
  559.     $success ? $self->_success : $self->_fail;
  560. }
  561.  
  562. sub check_output
  563. {
  564.     my ($self, %p) = @_;
  565.  
  566.     my $same;
  567.  
  568.     # Allow a regex for $p{expect}
  569.     if (ref $p{expect}) {
  570.     $same = ($p{actual} =~ /$p{expect}/);
  571.  
  572.     } else {
  573.     # Whitespace at end can vary.  (Or rather, it is varying in the tests, and
  574.     # should be made not to vary, but I don't have time to fix it yet.)
  575.     
  576.     for ($p{actual}, $p{expect}) {  s/\s+$//  }
  577.     $same = ($p{actual} eq $p{expect});
  578.     }
  579.  
  580.     if (!$same and $VERBOSE) {
  581.     print "Got ...\n-----\n$p{actual}\n-----\n   ... but expected ...\n-----\n$p{expect}\n-----\n";
  582.     }
  583.     return $same;
  584. }
  585.  
  586. sub _fail
  587. {
  588.     my $self = shift;
  589.     my $test = $self->{current_test};
  590.  
  591.     $self->{test_count}++;
  592.  
  593.     print "Result for $self->{name}: $test->{name}\nnot ok $self->{test_count}\n";
  594. }
  595.  
  596. sub _success
  597. {
  598.     my $self = shift;
  599.     my $test = $self->{current_test};
  600.  
  601.     $self->{test_count}++;
  602.  
  603.     print "Result for $self->{name}: $test->{name}\nok $self->{test_count}\n";
  604. }
  605.  
  606. sub _skip
  607. {
  608.     my $self = shift;
  609.     my $test = $self->{current_test};
  610.  
  611.     $self->{test_count}++;
  612.  
  613.     die "no test name for " . $self->{test_count} unless $test->{name};
  614.     print "Result for $self->{name}: $test->{name}\nok $self->{test_count}  # skip Skipped by user\n";
  615. }
  616.  
  617. #
  618. # We use our own rm_tree, rather than File::Path::rmtree, so that we
  619. # can silently fail to entirely remove directories. On some systems
  620. # .nfs files prevent total removal of directories but should not
  621. # otherwise interfere with tests.
  622. #
  623. sub rm_tree {
  624.     my ($path, $debug, $silent) = @_;
  625.     $path =~ s#/$##;
  626.     if (-d $path) {
  627.     local *DIR;
  628.     opendir DIR, $path or warn "Can't open $path: $!";
  629.     while (defined(my $file = readdir DIR)) {
  630.         next if $file eq '.' or $file eq '..';
  631.         rm_tree("$path/$file");
  632.     }
  633.     closedir DIR;
  634.     rmdir $path;
  635.     } elsif (-f $path) {
  636.     unlink $path;
  637.     } else {
  638.     warn "Can't find $path to remove"
  639.             unless $silent;
  640.     }
  641. }
  642.  
  643. sub _cleanup
  644. {
  645.     my $self = shift;
  646.  
  647.     rm_tree( $self->base_path, $DEBUG, @_ );
  648. }
  649.  
  650. 1;
  651.  
  652. __END__
  653.  
  654. =head1 NAME
  655.  
  656. HTML::Mason::Tests - Test harness for testing Mason
  657.  
  658. =head1 SYNOPSIS
  659.  
  660.  use HTML::Mason::Tests;
  661.  
  662.  my $group = HTML::Mason::Tests->new( name => 'name of group', description => 'tests something' );
  663.  $group->add_test( name => 'foo',
  664.                    description => 'tests foo',
  665.                    component => <<'EOF'
  666.  <%args>
  667.  $foo => 1
  668.  </%args>
  669.  <% $foo %>
  670.  EOF
  671.                    expect => <<'EOF',
  672.  1
  673.  EOF
  674.                  );
  675.  
  676.  $group->run;
  677.  
  678. =head1 DESCRIPTION
  679.  
  680. This module is designed to automate as much as possible of the Mason
  681. test suite.  It does tasks like write component files to disk, call
  682. them, compare the actual results to the expected results, and more.
  683. In addition, it also is capable of printing out useful information
  684. about test failures when run in verbose mode.  See the ADDITIONAL RUN
  685. MODES section for more information.
  686.  
  687. It also makes sure that any given group of tests provides all the
  688. information needed to run them (test names, components and results,
  689. etc.).
  690.  
  691. Now you have no excuse for writing new tests (and that goes double for
  692. me!).
  693.  
  694. =head1 METHODS
  695.  
  696. =head2 new
  697.  
  698. Takes the following parameters:
  699.  
  700. =over 4
  701.  
  702. =item * name (required)
  703.  
  704. The name of the entire group of tests.
  705.  
  706. =item * description (required)
  707.  
  708. What this group tests.
  709.  
  710. =item * pre_test_cleanup (optional, default=1)
  711.  
  712. If this is true (the default), the component root and data directory
  713. will be deleted both before and after running tests.
  714.  
  715. =back
  716.  
  717. =head2 add_support
  718.  
  719. Takes the following parameters:
  720.  
  721. =over 4
  722.  
  723. =item * path (required)
  724.  
  725. The path that other components will expect this component to be
  726. reachable at.  All paths are prepended with the group name.  So '/bar'
  727. as a support component in the 'foo' group's ultimate path would be
  728. '/foo/bar'.
  729.  
  730. =item * component
  731.  
  732. Text of the support component.  This parameter must have a value
  733. unless the skip_component parameter is true.
  734.  
  735. =item * skip_component
  736.  
  737. If true, then the test harness will not write a component to disk for
  738. this test.
  739.  
  740. =back
  741.  
  742. =head2 add_test
  743.  
  744. Takes the following parameters:
  745.  
  746. =over 4
  747.  
  748. =item * name (required)
  749.  
  750. The name of this test.
  751.  
  752. =item * description (required)
  753.  
  754. What this test is testing.
  755.  
  756. =item * component (required)
  757.  
  758. Text of the component.
  759.  
  760. =item * path (optional)
  761.  
  762. The path that this component should written to.  As with support
  763. components, this path is prepended with the group's name.  If no path
  764. is given, the value of the name parameter is used.
  765.  
  766. =item * call_path (optional)
  767.  
  768. The path that should be used to call the component.  If none is given,
  769. then the value is the same as the path option, if that exists,
  770. otherwise it is /<group name>/<test name>.  If a value is given, it is
  771. still prepended by /<group name>/.
  772.  
  773. =item * call_args (optional)
  774.  
  775. The arguments that should be passed to the component, in list or hash
  776. reference form. If none is given, no arguments are passed.
  777.  
  778. =item * compiler_params
  779.  
  780. This is a hash reference of parameters to be passed to the Compiler->new
  781. method.
  782.  
  783. =item * interp_params
  784.  
  785. This is a hash reference of parameters to be passed to the Interp->new
  786. method.
  787.  
  788. =item * interp
  789.  
  790. Provide an HTML::Mason::Interp object to be used for the test.
  791.  
  792. =back
  793.  
  794. One of the following three options is required:
  795.  
  796. =over 4
  797.  
  798. =item * expect
  799.  
  800. The text expected as a result of calling the component.  This
  801. parameter is _not_ required when running in L<Create mode|"ADDITIONAL
  802. RUN MODES">.
  803.  
  804. =item * expect_error
  805.  
  806. A regex containing that will be matched against the error returned
  807. from the component execution.
  808.  
  809. =item * skip_expect
  810.  
  811. This causes the component to be run but its output is ignored.
  812. However, if the component execution causes an error this will cause
  813. the test to fail.  This is used in a few situations where it is
  814. necessary to just run a component as part the preparation for another
  815. test.
  816.  
  817. =back
  818.  
  819. =head2 run
  820.  
  821. Run the tests in the group.
  822.  
  823. =head2 Class methods
  824.  
  825. These methods are provided since some tests may need to know these
  826. values.
  827.  
  828. =head2 base_path
  829.  
  830. The base path under which the component root and data directory for
  831. the tests are created.
  832.  
  833. =head2 comp_root
  834.  
  835. Returns the component root directory.
  836.  
  837. =head2 data_dir
  838.  
  839. Return the data directory
  840.  
  841. =head2 check_output ( actual => $actual_output, expect => $expected_output )
  842.  
  843. Given the parameters shown above, this method will check to see if the
  844. two are equal.  If they're not equal, it will print out an error
  845. message attempting to highlight the difference.
  846.  
  847. =head1 ADDITIONAL RUN MODES
  848.  
  849. The following additional modes are available for running tests.
  850.  
  851. =head2 Verbose mode
  852.  
  853. To turn this on, set the environment variables MASON_VERBOSE or
  854. MASON_DEBUG as true or run the tests as 'make test TEST_VERBOSE=1'.
  855. In this mode, the C<run> method will output information about tests as
  856. they are run.  If a test fails, then it will also show the cause of
  857. the failure.
  858.  
  859. =head2 Debug mode
  860.  
  861. To turn this on, set the MASON_DEBUG environment variable to a true
  862. value.  In this mode, the C<run> method will print detailed
  863. information of its actions.  This mode includes the output printed in
  864. VERBOSE mode.
  865.  
  866. =head2 No cleanup mode
  867.  
  868. Setting the MASON_NO_CLEANUP environment variable will tell the module
  869. to not clean up generated data from running the tests.  This includes
  870. the components written to disk and the data directory used during
  871. testing.  This can be useful when debugging.
  872.  
  873. =head2 Create mode
  874.  
  875. If the individual tests are run from the command line with the
  876. '--create' flag, then instead of checking the output of a component,
  877. the test harness will simply output its results.  This allows you to
  878. cut and paste these results back into the test file (assuming they are
  879. correct!).
  880.  
  881. =head2 Running and/or skipping selected tests
  882.  
  883. You can run just some of a test file with the '--tests-to-run' flag or
  884. the MASON_TESTS_TO_RUN environment variable. Similarly you can skip
  885. specific tests with the '--tests-to-skip' flag or the
  886. MASON_TESTS_TO_SKIP environment variable.
  887.  
  888. The value of either flag is a comma-separated list of one or more of
  889.  
  890.    [test_file_name:](test_number|test_name|*)
  891.  
  892. e.g.
  893.  
  894.     perl ./01-syntax.t --tests-to-run=3,5
  895.     MASON_TESTS_TO_SKIP=fake_percent,empty_percents perl ./01-syntax.t
  896.     MASON_TESTS_TO_RUN="misc:autohandler, request:*, interp:private1" make test
  897.  
  898. =head2 Subclassing this module
  899.  
  900. You can run tests with your own Tests.pm subclass using the
  901. '--tests-class' flag or the MASON_TESTS_CLASS environment variable.
  902. The value is a fully qualified package name that will be loaded before
  903. each test file is run.  e.g.
  904.  
  905.     perl ./01-syntax.t --tests-class=HTML::Mason::Tests::MyTests
  906.     MASON_TESTS_CLASS=HTML::Mason::Tests::MyTests make test
  907.  
  908. For example, if you have created your own lexer subclass and want
  909. to make sure that tests still pass with it, create a Tests subclass
  910. that overrides the _make_interp method to use your subclass:
  911.  
  912.     sub _make_interp
  913.     {
  914.         my ($self, %interp_params) = @_;
  915.         
  916.         return HTML::Mason::Interp->new
  917.         ( lexer_class => HTML::Mason::MyLexer,
  918.           %interp_params );
  919.     }
  920.  
  921. =head1 SEE ALSO
  922.  
  923. L<HTML::Mason|HTML::Mason>
  924.  
  925. =cut
  926.