From 04429fc9126bc0ba41774fe37ba2f6811f623947 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 17 May 2013 13:39:56 +0200 Subject: Import libtap-formatter-html-perl_0.11+dfsg.orig.tar.gz [dgit import orig libtap-formatter-html-perl_0.11+dfsg.orig.tar.gz] --- Build.PL | 56 + Changes | 105 ++ MANIFEST | 46 + META.json | 61 + META.yml | 37 + Makefile.PL | 35 + README | 385 ++++++ Todo | 44 + examples/DBD-SQLite-example.html | 1799 +++++++++++++++++++++++++++++ examples/test-output.html | 795 +++++++++++++ lib/App/Prove/Plugin/HTML.pm | 128 ++ lib/TAP/Formatter/HTML.pm | 913 +++++++++++++++ lib/TAP/Formatter/HTML/Session.pm | 269 +++++ lib/TAP/Formatter/HTML/default_page.css | 20 + lib/TAP/Formatter/HTML/default_report.css | 411 +++++++ lib/TAP/Formatter/HTML/default_report.js | 109 ++ lib/TAP/Formatter/HTML/default_report.tt2 | 170 +++ t/01_basic.t | 37 + t/02_escape_output.t | 33 + t/03_silent.t | 52 + t/04_really_quiet.t | 31 + t/05_quiet.t | 32 + t/06_output.t | 19 + t/07_multiple_aggregate.t | 29 + t/08_env_vars.t | 44 + t/09_empty_testdir.t | 19 + t/10_win32.t | 43 + t/11_force_inline.t | 28 + t/20_prove_html.t | 59 + t/30_tap_harness_compat.t | 17 + t/31_inc_path.t | 23 + t/99_test_pod.t | 4 + t/data/01_pass.pl | 26 + t/data/02_fail.pl | 18 + t/data/03_plan_fail.pl | 9 + t/data/04_die_fail.pl | 10 + t/data/05_compile_fail.pl | 12 + t/data/06_skip_all.pl | 6 + t/data/07_todo_pass.pl | 20 + t/data/08_html_in_output.pl | 9 + t/data/09_skip_error.pl | 11 + t/data/10_todo_skip.pl | 10 + t/data/11_lots_of_tests.pl | 9 + t/lib/FileTempTFH.pm | 21 + t/selenium/server.pl | 73 ++ t/selenium_basic.t | 234 ++++ 46 files changed, 6321 insertions(+) create mode 100644 Build.PL create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 META.json create mode 100644 META.yml create mode 100644 Makefile.PL create mode 100644 README create mode 100644 Todo create mode 100644 examples/DBD-SQLite-example.html create mode 100644 examples/test-output.html create mode 100644 lib/App/Prove/Plugin/HTML.pm create mode 100644 lib/TAP/Formatter/HTML.pm create mode 100644 lib/TAP/Formatter/HTML/Session.pm create mode 100644 lib/TAP/Formatter/HTML/default_page.css create mode 100644 lib/TAP/Formatter/HTML/default_report.css create mode 100644 lib/TAP/Formatter/HTML/default_report.js create mode 100644 lib/TAP/Formatter/HTML/default_report.tt2 create mode 100644 t/01_basic.t create mode 100644 t/02_escape_output.t create mode 100644 t/03_silent.t create mode 100644 t/04_really_quiet.t create mode 100644 t/05_quiet.t create mode 100644 t/06_output.t create mode 100644 t/07_multiple_aggregate.t create mode 100644 t/08_env_vars.t create mode 100644 t/09_empty_testdir.t create mode 100644 t/10_win32.t create mode 100644 t/11_force_inline.t create mode 100644 t/20_prove_html.t create mode 100644 t/30_tap_harness_compat.t create mode 100644 t/31_inc_path.t create mode 100644 t/99_test_pod.t create mode 100644 t/data/01_pass.pl create mode 100644 t/data/02_fail.pl create mode 100644 t/data/03_plan_fail.pl create mode 100644 t/data/04_die_fail.pl create mode 100644 t/data/05_compile_fail.pl create mode 100644 t/data/06_skip_all.pl create mode 100644 t/data/07_todo_pass.pl create mode 100644 t/data/08_html_in_output.pl create mode 100644 t/data/09_skip_error.pl create mode 100644 t/data/10_todo_skip.pl create mode 100644 t/data/11_lots_of_tests.pl create mode 100644 t/lib/FileTempTFH.pm create mode 100644 t/selenium/server.pl create mode 100644 t/selenium_basic.t diff --git a/Build.PL b/Build.PL new file mode 100644 index 0000000..5995ff8 --- /dev/null +++ b/Build.PL @@ -0,0 +1,56 @@ +#!/usr/bin/perl + +=head1 NAME + +Build.PL - Build script generator for C module + +=head1 SYNOPSIS + + perl Build.PL + ./Build + ./Build test + ./Build install + +=cut + +use strict; +use warnings; +use Module::Build; + +my $build = Module::Build->new + ( + module_name => 'TAP::Formatter::HTML', + dist_version_from => 'lib/TAP/Formatter/HTML.pm', + create_makefile_pl => 'passthrough', + create_readme => 1, + license => 'perl', + requires => { + 'perl' => '5.6.0', + 'accessors' => '0.02', + 'URI' => '1.35', + 'Template' => '2.14', + 'TAP::Parser' => '3.10', + 'File::Temp' => '0.17', + 'Test::Harness' => '3.17', + }, + build_requires => { + 'Test::More' => '0.01', + 'Module::Build' => '0.20', + }, + ); + +$build->add_build_element("tt2"); +$build->add_build_element("css"); +$build->add_build_element("js"); + +$build->create_build_script; + + +__END__ + +=head1 AUTHOR + +Steve Purkis + +=cut + diff --git a/Changes b/Changes new file mode 100644 index 0000000..c0c5ad3 --- /dev/null +++ b/Changes @@ -0,0 +1,105 @@ +Revision history for 'TAP-Formatter-HTML' Perl module +----------------------------------------------------- + +All changes by Steve Purkis, unless otherwise noted. + +0.11 + + fixed RT #81922: tests no longer hang on Win32. Didn't get to the bottom + of the issue (likely IPC::Open3 & redirecting STDOUT not playing nicely), + but worked around it. + + fixed a bug on Win32 where default js_uris & css_uris were being mangled: + "C:%5C..." vs "C:\". May have affected other Win32 URIs too. + +0.10 + + fixed RT #82738: color method was not implemented. + + fixed RT #74364: TT2 INCLUDE_PATH no longer set to all dirs in @INC, + now it is set to parent directory TAP::Formatter::HTML was loaded from. + +0.09 + + upgraded to jQuery 1.4.2 + + updated App::Prove::Plugin::HTML to simplify cmdline usage to the + extent possible. + + fixed RT #41457 & RT #49621: applied Neil Hemingway, Tim Esselens, and + Panu Ervamaa's patches, and got everything working. This addresses: + + small changes to the top-left corner menu (default_report.css) + to render it corretly with Firefox 3 (Linux) + + inline_js fix + + added support for force_inline_js (not on by default, including + jQuery inline causes errors) + + fixed bug in handling of parse_errors in default_report.tt + + fixed bug: nothing happens when I click on the test output. + + XHTML support + + fixed bug: click on summary changes location + + fixed 2 minor javascript bugs where '#' was being used as a jQuery id ref + + added new feature: column sorting via Christian Bach's jquery.tablesorter + plugin (bundled from http://tablesorter.com). optional. + + added new feature: up to top of test when the test filename is no longer + visible. + + +0.08 + + applied Steffen Schwigon's patch to display YAML TAP as + pre-formatted text. + + fixed RT #43871: missing dep on File::Temp 0.17 + [reported by Paddy Newman] + + fixed RT #37983: CSS and JS Paths on Win32 get mangled + and documented solution. [reported by Chris Davaz] + + wrote some selenium tests, finally. found & fixed small bug where + a test's html_id wasn't being set. + + fixed RT #48296: pod for js_uris mentions styles, not scripts + [reported by Slaven Rezić] + + started on RT #41457: only got "incline_js" fixed + [reported by Neil Hemingway] + +0.07 + + you can now specify an output file for the HTML to be written to! + + you can now set some config params using environment vars. this should + make it easier to configure without having to write custom code. + + started writing an App::Prove plugin + + fixed RT #40306: Typo in TAP::Formatter::HTML (incline_js) + (also reported by Nathan S. Watson-Haigh) + + applied patch from Michael Hendricks (who's work on this was sponsored + by Grant Street Group) for a bug he & others identified: + If tests are aggregated in multiple phases (per http://xrl.us/bedfih), + ... the HTML output shows only the results from the final phase. + + finally wrote some more tests, though selenium tests still not done + + fixed RT #41411: fails on empty directory + * started using IO::* modules for stdout & output_fh + +0.06 + + fixed RT #37019: tempdir without cleanup [reported by Steffen Schwigon] + +0.05 + + fixed width issue: test files with hundreds of tests were causing + uncontrollable width in summary, making the report pretty annoying + to read. + + added toggle to display all / failed tests [requested by Alex Monney] + + highlight failed test file names + + reduced the size of generated HTML by a further ~10-35% (depending on + the number of tests you run): + * set test title on mouse-over so it's included only once + * moved inline JS out of default_report.tt2 to its own file that is + included by default. + * split css into 'page' & 'report' for ease of user maintainability. + [requested by Steffen Schwigon] + + fixed bug: % passed on test file != % ok, was really confusing people. + [requested by Wolfram Pfeiffer] + * upgraded to jquery-1.2.6 + +0.04 + + reduced the size of the generated HTML (by 25% on avg for my tests): + * added 'minify' option to strip leading tabs + * used short css class names + * used numeric html id's + * got rid of some other unnecessary whitespace + +0.03 + + updated deps in Build.PL (again, *sigh*) + +0.02 + + updated deps in Build.PL + + wrote more docs, fixed a few errors & omissions + - removed bin/runtests_html (it was added before I found out about 'prove') + +0.01 + + created Thurs May 14 2008 diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..90d11a7 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,46 @@ +Build.PL +Changes +examples/DBD-SQLite-example.html +examples/test-output.html +lib/App/Prove/Plugin/HTML.pm +lib/TAP/Formatter/HTML.pm +lib/TAP/Formatter/HTML/default_page.css +lib/TAP/Formatter/HTML/default_report.css +lib/TAP/Formatter/HTML/default_report.js +lib/TAP/Formatter/HTML/default_report.tt2 +lib/TAP/Formatter/HTML/Session.pm +Makefile.PL +MANIFEST This list of files +META.json +META.yml +README +t/01_basic.t +t/02_escape_output.t +t/03_silent.t +t/04_really_quiet.t +t/05_quiet.t +t/06_output.t +t/07_multiple_aggregate.t +t/08_env_vars.t +t/09_empty_testdir.t +t/10_win32.t +t/11_force_inline.t +t/20_prove_html.t +t/30_tap_harness_compat.t +t/31_inc_path.t +t/99_test_pod.t +t/data/01_pass.pl +t/data/02_fail.pl +t/data/03_plan_fail.pl +t/data/04_die_fail.pl +t/data/05_compile_fail.pl +t/data/06_skip_all.pl +t/data/07_todo_pass.pl +t/data/08_html_in_output.pl +t/data/09_skip_error.pl +t/data/10_todo_skip.pl +t/data/11_lots_of_tests.pl +t/lib/FileTempTFH.pm +t/selenium/server.pl +t/selenium_basic.t +Todo diff --git a/META.json b/META.json new file mode 100644 index 0000000..de065b0 --- /dev/null +++ b/META.json @@ -0,0 +1,61 @@ +{ + "abstract" : "TAP Test Harness output delegate for html output", + "author" : [ + "Steve Purkis " + ], + "dynamic_config" : 1, + "generated_by" : "Module::Build version 0.38, CPAN::Meta::Converter version 2.113640", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "TAP-Formatter-HTML", + "prereqs" : { + "build" : { + "requires" : { + "Module::Build" : "0.20", + "Test::More" : "0.01" + } + }, + "configure" : { + "requires" : { + "Module::Build" : "0.38" + } + }, + "runtime" : { + "requires" : { + "File::Temp" : "0.17", + "TAP::Parser" : "3.10", + "Template" : "2.14", + "Test::Harness" : "3.17", + "URI" : "1.35", + "accessors" : "0.02", + "perl" : "v5.6.0" + } + } + }, + "provides" : { + "App::Prove::Plugin::HTML" : { + "file" : "lib/App/Prove/Plugin/HTML.pm", + "version" : "0.11" + }, + "TAP::Formatter::HTML" : { + "file" : "lib/TAP/Formatter/HTML.pm", + "version" : "0.11" + }, + "TAP::Formatter::HTML::Session" : { + "file" : "lib/TAP/Formatter/HTML/Session.pm", + "version" : "0.11" + } + }, + "release_status" : "stable", + "resources" : { + "license" : [ + "http://dev.perl.org/licenses/" + ] + }, + "version" : "0.11" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..3859868 --- /dev/null +++ b/META.yml @@ -0,0 +1,37 @@ +--- +abstract: 'TAP Test Harness output delegate for html output' +author: + - 'Steve Purkis ' +build_requires: + Module::Build: 0.20 + Test::More: 0.01 +configure_requires: + Module::Build: 0.38 +dynamic_config: 1 +generated_by: 'Module::Build version 0.38, CPAN::Meta::Converter version 2.113640' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: TAP-Formatter-HTML +provides: + App::Prove::Plugin::HTML: + file: lib/App/Prove/Plugin/HTML.pm + version: 0.11 + TAP::Formatter::HTML: + file: lib/TAP/Formatter/HTML.pm + version: 0.11 + TAP::Formatter::HTML::Session: + file: lib/TAP/Formatter/HTML/Session.pm + version: 0.11 +requires: + File::Temp: 0.17 + TAP::Parser: 3.10 + Template: 2.14 + Test::Harness: 3.17 + URI: 1.35 + accessors: 0.02 + perl: v5.6.0 +resources: + license: http://dev.perl.org/licenses/ +version: 0.11 diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..d32a25a --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,35 @@ +# Note: this file was auto-generated by Module::Build::Compat version 0.3800 +require 5.006000; + + unless (eval "use Module::Build::Compat 0.02; 1" ) { + print "This module requires Module::Build to install itself.\n"; + + require ExtUtils::MakeMaker; + my $yn = ExtUtils::MakeMaker::prompt + (' Install Module::Build now from CPAN?', 'y'); + + unless ($yn =~ /^y/i) { + die " *** Cannot install without Module::Build. Exiting ...\n"; + } + + require Cwd; + require File::Spec; + require CPAN; + + # Save this 'cause CPAN will chdir all over the place. + my $cwd = Cwd::cwd(); + + CPAN::Shell->install('Module::Build::Compat'); + CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate + or die "Couldn't install Module::Build, giving up.\n"; + + chdir $cwd or die "Cannot chdir() back to $cwd: $!"; + } + eval "use Module::Build::Compat 0.02; 1" or die $@; + + Module::Build::Compat->run_build_pl(args => \@ARGV); + my $build_script = 'Build'; + $build_script .= '.com' if $^O eq 'VMS'; + exit(0) unless(-e $build_script); # cpantesters convention + require Module::Build; + Module::Build::Compat->write_makefile(build_class => 'Module::Build'); diff --git a/README b/README new file mode 100644 index 0000000..29af679 --- /dev/null +++ b/README @@ -0,0 +1,385 @@ +NAME + TAP::Formatter::HTML - TAP Test Harness output delegate for html output + +SYNOPSIS + ## + ## command-line usage (alpha): + ## + prove -m -Q -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0 + + # backwards compat usage: + prove -m -Q --formatter=TAP::Formatter::HTML >output.html + + # for more detail: + perldoc App::Prove::Plugin::HTML + + ## + ## perl usage: + ## + use TAP::Harness; + + my @tests = glob( 't/*.t' ); + my $harness = TAP::Harness->new({ formatter_class => 'TAP::Formatter::HTML', + merge => 1 }); + $harness->runtests( @tests ); + # prints HTML to STDOUT by default + + # or if you really don't want STDERR merged in: + my $harness = TAP::Harness->new({ formatter_class => 'TAP::Formatter::HTML' }); + + # to use a custom formatter: + my $fmt = TAP::Formatter::HTML->new; + $fmt->css_uris([])->inline_css( $my_css ) + ->js_uris(['http://mysite.com/jquery.js', 'http://mysite.com/custom.js']) + ->inline_js( '$(div.summary).hide()' ); + + my $harness = TAP::Harness->new({ formatter => $fmt, merge => 1 }); + + # to output HTML to a file[handle]: + $fmt->output_fh( $fh ); + $fmt->output_file( '/tmp/foo.html' ); + + # you can use your own customized templates too: + $fmt->template('custom.tt2') + ->template_processor( Template->new ) + ->force_inline_css(0) + ->force_inline_js(0); + +DESCRIPTION + This module provides HTML output formatting for TAP::Harness (a + replacement for Test::Harness. It is largely based on ideas from + TAP::Test::HTMLMatrix (which was built on Test::Harness and thus had a + few limitations - hence this module). For sample output, see: + + + + This module is targeted at all users of automated test suites. It's + meant to make reading test results easier, giving you a visual summary + of your test suite and letting you drill down into individual failures + (which will hopefully make testing more likely to happen at your + organization ;-). + + The design goals are: + + * *easy to use* + + Once you've got your test report, it should be obvious how to use + it. + + * *helpful* + + It should be helpful by pointing out *where* & *why* your test suite + is breaking. If you've written your tests well, it should give you + enough info to start tracking down the issue. + + * *easy to install* + + Eg: should be a clean install from CPAN, and you shouldn't need to + modify your existing test suite to get up & running, though *you + will need to stop using Test::Harness unfortunately*. + + * *work out of the box* + + You shouldn't need to do any custom-coding to get it working - the + default configuration & templates should be enough to get started + with. Once installed it should be a matter of running: + + % prove -m -Q --formatter=TAP::Formatter::HTML >output.html + + From your project's home dir, and opening the resulting file. + + * *easy to configure* + + You should be able to configure & customize it to suit your needs. + As such, css, javascript and templates are all configurable. + +METHODS + CONSTRUCTOR + new + my $fmt = $class->new({ %args }); + + ACCESSORS + All chaining accessors: + + verbosity + $fmt->verbosity( [ $v ] ) + + Verbosity level, as defined in "new" in TAP::Harness: + + 1 verbose Print individual test results (and more) to STDOUT. + 0 normal + -1 quiet Suppress some test output (eg: test failures). + -2 really quiet Suppress everything to STDOUT but the HTML report. + -3 silent Suppress all output to STDOUT, including the HTML report. + + Note that the report is also available via "html". You can also provide + a custom "output_fh" (aka "output_file") that will be used instead of + "stdout", even if *silent* is on. + + stdout + $fmt->stdout( [ \*FH ] ); + + An IO::Handle filehandle for catching standard output. Defaults to + "STDOUT". + + output_fh + $fmt->output_fh( [ \*FH ] ); + + An IO::Handle filehandle for printing the HTML report to. Defaults to + the same object as "stdout". + + Note: If "verbosity" is set to "silent", printing to "output_fh" will + still occur. (that is, assuming you've opened a different file, not + "STDOUT"). + + output_file + $fmt->output_file( $file_name ) + + Not strictly an accessor - this is a shortcut for setting "output_fh", + equivalent to: + + $fmt->output_fh( IO::File->new( $file_name, 'w' ) ); + + You can set this with the "TAP_FORMATTER_HTML_OUTFILE=/path/to/file" + environment variable + + escape_output + $fmt->escape_output( [ $boolean ] ); + + If set, all output to "stdout" is escaped. This is probably only useful + if you're testing the formatter. Defaults to 0. + + html + $fmt->html( [ \$html ] ); + + This is a reference to the scalar containing the html generated on the + last test run. Useful if you have "verbosity" set to "silent", and have + not provided a custom "output_fh" to write the report to. + + tests + $fmt->tests( [ \@test_files ] ) + + A list of test files we're running, set by TAP::Parser. + + session_class + $fmt->session_class( [ $class ] ) + + Class to use for TAP::Parser test sessions. You probably won't need to + use this unless you're hacking or sub-classing the formatter. Defaults + to TAP::Formatter::HTML::Session. + + sessions + $fmt->sessions( [ \@sessions ] ) + + Test sessions added by TAP::Parser. You probably won't need to use this + unless you're hacking or sub-classing the formatter. + + template_processor + $fmt->template_processor( [ $processor ] ) + + The template processor to use. Defaults to a TT2 Template processor with + the following config: + + COMPILE_DIR => catdir( tempdir(), 'TAP-Formatter-HTML' ), + COMPILE_EXT => '.ttc', + INCLUDE_PATH => parent directory TAP::Formatter::HTML was loaded from + + Note: INCLUDE_PATH used to be set to: "join(':', @INC)" but this was + causing issues on systems with > 64 dirs in @INC. See RT #74364 for + details. + + template + $fmt->template( [ $file_name ] ) + + The template file to load. Defaults to + "TAP/Formatter/HTML/default_report.tt2". + + You can set this with the "TAP_FORMATTER_HTML_TEMPLATE=/path/to.tt" + environment variable. + + css_uris + $fmt->css_uris( [ \@uris ] ) + + A list of URIs (or strings) to include as external stylesheets in + + + + + + +
+ FAILED +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test fileTest resultsTime%
+ t/00basic.t + + + + + +
 
+
+
    +
+
    +
  • 1..1
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:34 2008
  • +
  • # Current time GMT: Sun May 18 14:26:34 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
+
+
0.11s100.0%
+ t/01logon.t + + + + + + + +
   
+
+
    +
+
    +
  • 1..3
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:34 2008
  • +
  • # Current time GMT: Sun May 18 14:26:34 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • sqlite_version=3.4.2, sqlite_encoding=
  • +
+
+
0.11s100.0%
+ t/02cr_table.t + + + + + + + + +
    
+
+
    +
+
    +
  • 1..4
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:34 2008
  • +
  • # Current time GMT: Sun May 18 14:26:34 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • f1, f1, f2, f3
  • +
  • ok 4
  • +
  • closing dbh with active statement handles at t/02cr_table.t line 16.
  • +
+
+
0.17s100.0%
+ t/03insert.t + + + + + + + + + + + + + +
         
+
+
    +
+
    +
  • 1..9
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:34 2008
  • +
  • # Current time GMT: Sun May 18 14:26:34 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • DBI::db=HASH(0x180a69c)->disconnect invalidates 1 active statement handle (either destroy statement handles or call finish on them before disconnecting) at t/03insert.t line 15.
  • +
  • closing dbh with active statement handles at t/03insert.t line 15.
  • +
+
+
0.13s100.0%
+ t/04select.t + + + + + + + + + + + +
       
+
+
    +
+
    +
  • 1..7
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:35 2008
  • +
  • # Current time GMT: Sun May 18 14:26:35 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • Fred, Bloggs, fred@bloggs.com
  • +
  • ok 6
  • +
  • ok 7
  • +
  • closing dbh with active statement handles at t/04select.t line 17.
  • +
+
+
0.13s100.0%
+ t/05tran.t + + + + + + +
  
+
+
    +
+
    +
  • 1..2
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:35 2008
  • +
  • # Current time GMT: Sun May 18 14:26:35 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ID, TITLE, TOTAL
  • +
  • closing dbh with active statement handles at t/05tran.t line 34.
  • +
+
+
0.12s100.0%
+ t/06error.t + + + + + + +
  
+
+
    +
+
    +
  • 1..2
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:35 2008
  • +
  • # Current time GMT: Sun May 18 14:26:35 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
+
+
0.12s100.0%
+ t/08create_function.t + + + + + + + + + + + + + + + + + + + + + + +
                  
+
+
    +
+
    +
  • 1..18
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:35 2008
  • +
  • # Current time GMT: Sun May 18 14:26:35 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
+
+
0.06s100.0%
+ t/09create_aggregate.t + + + + + + + + + + + + + + + + + + + +
               
+
+
    +
+
    +
  • 1..15
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:35 2008
  • +
  • # Current time GMT: Sun May 18 14:26:35 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
+
+
0.13s100.0%
+ t/10dsnlist.t + + + + + + + +
   
+
+
    +
+
    +
  • Driver is SQLite
  • +
  • 1..3
  • +
  • ok 1
  • +
  • ok 2
  • +
  • List of SQLite data sources:
  • +
  • List ends.
  • +
  • ok 3
  • +
+
+
0.04s100.0%
+ t/20createdrop.t + + + + + + + + + +
     
+
+
    +
+
    +
  • 1..5
  • +
  • ok 1
  • +
  • ok 2
  • +
  • Creating table:
  • +
  • CREATE TABLE testaa (id INTEGER NOT NULL, name CHAR (64) NOT NULL)
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
+
+
0.01s100.0%
+ t/30insertfetch.t + + + + + + + + + + + + + + + + + + + + + +
                 
+
+
    +
+
    +
  • 1..17
  • +
  • ok 1 connect
  • +
  • ok 2 FindNewTable
  • +
  • CREATE TABLE testaa (id INTEGER NOT NULL, name CHAR (64) NOT NULL, val INTEGER NOT NULL, txt CHAR (64) NOT NULL)
  • +
  • ok 3 create
  • +
  • ok 4 insert
  • +
  • ok 5 prepare select
  • +
  • ok 6 execute select
  • +
  • ok 7 fetch select
  • +
  • ok 8 compare select
  • +
  • ok 9 finish select
  • +
  • ok 10 undef select
  • +
  • ok 11 delete
  • +
  • ok 12 prepare select deleted
  • +
  • ok 13 execute select deleted
  • +
  • ok 14 fetch select deleted
  • +
  • ok 15 finish select deleted
  • +
  • ok 16 undef select deleted
  • +
  • ok 17 drop
  • +
+
+
0.15s100.0%
+ t/40bindparam.t + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                            
+
+
    +
+
    +
  • 1..28
  • +
  • ok 1 connect
  • +
  • ok 2 FindNewTable
  • +
  • CREATE TABLE testaa (id INTEGER NOT NULL, name CHAR (64))
  • +
  • ok 3 create
  • +
  • ok 4 prepare
  • +
  • ok 5 execute insert 1
  • +
  • ok 6 execute insert num as string
  • +
  • ok 7 execute insert 2
  • +
  • ok 8 bind 1
  • +
  • ok 9 bind 2
  • +
  • ok 10 execute binds
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14 finish
  • +
  • ok 15 undef cursor
  • +
  • ok 16 disconnect
  • +
  • ok 17 undef dbh
  • +
  • ok 18 connect for read
  • +
  • ok 19
  • +
  • ok 20
  • +
  • ok 21
  • +
  • ok 22
  • +
  • ok 23
  • +
  • ok 24
  • +
  • ok 25
  • +
  • ok 26
  • +
  • ok 27
  • +
  • ok 28
  • +
+
+
0.13s100.0%
+ t/40blobs.t + + + + + + + + + + + + + + + +
           
+
+
    +
+
    +
  • 1..11
  • +
  • ok 1
  • +
  • ok 2
  • +
  • Creating table:
  • +
  • CREATE TABLE testaa (id INTEGER NOT NULL, name BLOB NOT NULL)
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
+
+
0.11s100.0%
+ t/40listfields.t + + + + + + + + + + + + + + + + + +
             
+
+
    +
+
    +
  • 1..13
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3 0E0
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
+
+
0.11s100.0%
+ t/40nulls.t + + + + + + + + + + + + + + + +
           
+
+
    +
+
    +
  • 1..11
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3 0E0
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
+
+
0.05s100.0%
+ t/40numrows.t + + + + + + + + + + + + + + + + + + + + + + + + + + +
                      
+
+
    +
+
    +
  • 1..22
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3 0E0
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
  • ok 19
  • +
  • ok 20
  • +
  • ok 21
  • +
  • ok 22
  • +
+
+
0.13s100.0%
+ t/50chopblanks.t + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                   
+
+
    +
+
    +
  • 1..35
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3 0E0
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
  • ok 19
  • +
  • ok 20
  • +
  • ok 21
  • +
  • ok 22
  • +
  • ok 23
  • +
  • ok 24
  • +
  • ok 25
  • +
  • ok 26
  • +
  • ok 27
  • +
  • ok 28
  • +
  • ok 29
  • +
  • ok 30
  • +
  • ok 31
  • +
  • ok 32
  • +
  • ok 33
  • +
  • ok 34
  • +
  • closing dbh with active statement handles at t/50chopblanks.t line 144.
  • +
  • ok 35
  • +
+
+
0.13s100.0%
+ t/50commit.t + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                              
+
+
    +
+
    +
  • 1..30
  • +
  • Attempting to connect.
  • +
  • ok 1 connect
  • +
  • ok 2
  • +
  • ok 3 0E0
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
  • ok 19
  • +
  • ok 20
  • +
  • ok 21 NumRows
  • +
  • ok 22 disconnect
  • +
  • ok 23
  • +
  • ok 24
  • +
  • ok 25
  • +
  • ok 26
  • +
  • ok 27
  • +
  • ok 28
  • +
  • ok 29
  • +
  • ok 30
  • +
+
+
0.01s100.0%
+ t/60metadata.t + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        
+
+
    +
+
    +
  • 1..24
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:37 2008
  • +
  • # Current time GMT: Sun May 18 14:26:37 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
  • ok 19
  • +
  • ok 20
  • +
  • ok 21
  • +
  • ok 22
  • +
  • # Types: varchar(2) char(1)
  • +
  • # Names: f1 f2
  • +
  • ok 23
  • +
  • ok 24
  • +
+
+
0.14s100.0%
+ t/90cppcomments.t + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                 
+
+
    +
+
    +
  • 1..33
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:37 2008
  • +
  • # Current time GMT: Sun May 18 14:26:37 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8
  • +
  • ok 9
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
  • ok 19
  • +
  • ok 20
  • +
  • ok 21
  • +
  • ok 22
  • +
  • ok 23
  • +
  • ok 24
  • +
  • ok 25
  • +
  • ok 26
  • +
  • ok 27
  • +
  • ok 28
  • +
  • ok 29
  • +
  • ok 30
  • +
  • ok 31
  • +
  • ok 32
  • +
  • ok 33
  • +
+
+
0.13s100.0%
+ t/99cleanup.t + + + + + + +
  
+
+
    +
+
    +
  • 1..2
  • +
  • # Running under perl version 5.008004 for darwin
  • +
  • # Current time local: Sun May 18 15:26:37 2008
  • +
  • # Current time GMT: Sun May 18 14:26:37 2008
  • +
  • # Using Test.pm version 1.24
  • +
  • ok 1
  • +
  • ok 2
  • +
+
+
0.01s100.0%
+ t/ak-dbd.t + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                 
+
+
    +
+
    +
  • Inserting a row...
  • +
  • Deleting a row...
  • +
  • 1..49
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3 0E0
  • +
  • ok 4
  • +
  • ok 5
  • +
  • ok 6
  • +
  • ok 7
  • +
  • ok 8 0E0
  • +
  • Inserting a row...
  • +
  • ok 9
  • +
  • Deleting a row...
  • +
  • ok 10
  • +
  • ok 11
  • +
  • ok 12
  • +
  • ok 13
  • +
  • ok 14
  • +
  • ok 15
  • +
  • ok 16
  • +
  • ok 17
  • +
  • ok 18
  • +
  • Test 19: Setting $debug_me to TRUE
  • +
  • ok 19
  • +
  • not ok 20 -
  • +
  • FAILED Test 20 -
  • +
  • sth->rows returned wrong result 0 after 'execute'.
  • +
  • ok 21
  • +
  • ok 22
  • +
  • ok 23
  • +
  • ok 24
  • +
  • Test 25: Setting $debug_me to TRUE
  • +
  • ok 25
  • +
  • ok 26
  • +
  • ok 27
  • +
  • ok 28
  • +
  • ok 29
  • +
  • ok 30
  • +
  • ok 31
  • +
  • ok 32
  • +
  • ok 33
  • +
  • ok 34
  • +
  • ok 35
  • +
  • ok 36
  • +
  • ok 37
  • +
  • ok 38
  • +
  • ok 39
  • +
  • ok 40
  • +
  • ok 41 execute 284
  • +
  • fetchrow 286
  • +
  • ok 42 Alligator Descartes
  • +
  • ok 43
  • +
  • ok 44
  • +
  • ok 45
  • +
  • ok 46
  • +
  • ok 47
  • +
  • ok 48
  • +
  • ok 49
  • +
+
+
0.16s98.0%
+ t/dbdadmin.t + + + + + + + + +
    
+
+
    +
+
    +
  • 1..4
  • +
  • ok 1
  • +
  • ok 2
  • +
  • ok 3
  • +
  • ok 4
  • +
+
+
0.10s100.0%
24 files + 348 tests, + 347 ok, + 1 failed, + 0 todo, + 0 skipped, + 0 parse errors
+ exit status: 0, + wait status: 0
+ elapsed time: 4 wallclock secs ( 0.31 usr 0.19 sys + 2.32 cusr 0.77 csys = 3.59 CPU)
2.52s99.7%
+
+ + + + + diff --git a/examples/test-output.html b/examples/test-output.html new file mode 100644 index 0000000..d1f4447 --- /dev/null +++ b/examples/test-output.html @@ -0,0 +1,795 @@ + + + Test Report + + + + + + + +
+ FAILED +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test fileTest resultsTime%
+ t/data/01_pass.pl + + + + + + + + + + + + + +
         
+
+
    +
+
    +
  • ok 1 - im ok
  • +
  • ok 2 - one is one
  • +
  • ok 3 - contains b
  • +
  • not ok 4 - one is two? # TODO just cant get these working?
  • +
  • +
  • # Failed (TODO) test 'one is two?'
  • +
  • # at t/data/01_pass.pl line 12.
  • +
  • # got: '1'
  • +
  • # expected: '2'
  • +
  • not ok 5 - contains d? # TODO just cant get these working?
  • +
  • +
  • # Failed (TODO) test 'contains d?'
  • +
  • # at t/data/01_pass.pl line 13.
  • +
  • # 'abc'
  • +
  • # doesn't match '(?-xism:d)'
  • +
  • ok 6 # skip to the loo
  • +
  • ok 7 # skip to the loo
  • +
  • not ok 8 # TODO & SKIP to the loo again
  • +
  • not ok 9 # TODO & SKIP to the loo again
  • +
  • 1..9
  • +
+
+
0.06s100.0%
+ t/data/02_fail.pl + + + + + + + + + + + +
       
+
+
    +
+
    +
  • ok 1 - im ok
  • +
  • ok 2 - one is one
  • +
  • ok 3 - contains b
  • +
  • not ok 4 - one is two?
  • +
  • +
  • # Failed test 'one is two?'
  • +
  • # at t/data/02_fail.pl line 11.
  • +
  • # got: '1'
  • +
  • # expected: '2'
  • +
  • not ok 5 - contains d?
  • +
  • +
  • # Failed test 'contains d?'
  • +
  • # at t/data/02_fail.pl line 12.
  • +
  • # 'abc'
  • +
  • # doesn't match '(?-xism:d)'
  • +
  • ok 6 - youre ok
  • +
  • not ok 7 - dont run me
  • +
  • +
  • # Failed test 'dont run me'
  • +
  • # at t/data/02_fail.pl line 17.
  • +
  • 1..7
  • +
  • # Looks like you failed 3 tests of 7.
  • exit status: 3, wait status: 768
  • +
+
+
0.11s57.1%
+ t/data/03_plan_fail.pl + + + + + + + +
   
+
+
    +
  • Parse error: Bad plan. You planned 2 tests but ran 3.
  • +
+
    +
  • 1..2
  • +
  • ok 1 - im ok
  • +
  • ok 2 - one is one
  • +
  • ok 3 - contains b (unplanned!)
  • +
  • # Looks like you planned 2 tests but ran 1 extra.
  • exit status: 255, wait status: 65280
  • +
+
+
0.04s150.0%
+ t/data/04_die_fail.pl + + + + + + + +
   
+
+
    +
+
    +
  • 1..3
  • +
  • ok 1 - im ok
  • +
  • ok 2 - one is one
  • +
  • ok 3 - contains b
  • +
  • this is an error test, not some horrible error at t/data/04_die_fail.pl line 10.
  • +
  • # Looks like your test died just after 3.
  • exit status: 255, wait status: 65280
  • +
+
+
0.11s100.0%
+ t/data/05_compile_fail.pl + + + + +
 
+
+
    +
  • Parse error: No plan found in TAP output
  • +
+
    +
  • Bareword found where operator expected at t/data/05_compile_fail.pl line 6, near "be ok"
  • +
  • (Do you need to predeclare be?)
  • +
  • Semicolon seems to be missing at t/data/05_compile_fail.pl line 8.
  • +
  • syntax error at t/data/05_compile_fail.pl line 6, near "be ok"
  • +
  • Execution of t/data/05_compile_fail.pl aborted due to compilation errors.
  • +
  • # Looks like your test died before it could output anything.
  • exit status: 255, wait status: 65280
  • +
+
+
0.05sn/a
+ t/data/06_skip_all.pl + + + + +
 
+
+
    +
+
    +
  • 1..0 # Skip likity skipity
  • +
+
+
0.03sn/a
+ t/data/07_todo_pass.pl + + + + + + + + + + + +
       
+
+
    +
+
    +
  • 1..7
  • +
  • ok 1 - im ok
  • +
  • ok 2 - one is one
  • +
  • ok 3 - contains b
  • +
  • ok 4 - one is one! # TODO just cant get these working? (unexpectedly succeeded!)
  • +
  • ok 5 - contains c? # TODO just cant get these working? (unexpectedly succeeded!)
  • +
  • not ok 6 # TODO & SKIP to the loo
  • +
  • not ok 7 # TODO & SKIP to the loo
  • +
+
+
0.09s100.0%
+ t/data/08_html_in_output.pl + + + + + + + +
   
+
+
    +
+
    +
  • ok 1 - escape some of these chars: !@\#$%^++_)(*&^%$\#@!><
  • +
  • ok 2 - contains <b> in the <output>
  • +
  • not ok 3 - <html> in the diag messages..
  • +
  • +
  • # Failed test '<html> in the diag messages..'
  • +
  • # at t/data/08_html_in_output.pl line 8.
  • +
  • # got: 'a<b>c'
  • +
  • # expected: '<html><body><h1>eeek</h1></body></html>'
  • +
  • 1..3
  • +
  • # Looks like you failed 1 test of 3.
  • exit status: 1, wait status: 256
  • +
+
+
0.02s66.7%
+ t/data/09_skip_error.pl + + + + + + +
  
+
+
    +
+
    +
  • ok 1 # skip to the loo
  • +
  • ok 2 # skip to the loo
  • +
  • Label not found for "last SKIP" at /usr/local/lib/perl5/5.8.4/Test/More.pm line 1023.
  • +
  • 1..2
  • +
  • # Looks like your test died just after 2.
  • exit status: 255, wait status: 65280
  • +
+
+
0.01s100.0%
+ t/data/10_todo_skip.pl + + + + + + +
  
+
+
    +
+
    +
  • 1..2
  • +
  • not ok 1 # TODO & SKIP to the loo
  • +
  • not ok 2 # TODO & SKIP to the loo
  • +
+
+
0.10s100.0%
10 files + 36 tests, + 31 ok, + 5 failed, + 10 todo, + 4 skipped, + 2 parse errors
+ exit status: 1024, + wait status: 262144
+ elapsed time: 1 wallclock secs ( 0.10 usr 0.08 sys + 0.58 cusr 0.18 csys = 0.94 CPU)
0.62s91.7%
+
+ + + + + diff --git a/lib/App/Prove/Plugin/HTML.pm b/lib/App/Prove/Plugin/HTML.pm new file mode 100644 index 0000000..6887532 --- /dev/null +++ b/lib/App/Prove/Plugin/HTML.pm @@ -0,0 +1,128 @@ +package App::Prove::Plugin::HTML; + +=head1 NAME + +App::Prove::Plugin::HTML - a prove plugin for HTML output + +=head1 SYNOPSIS + + # command-line usage: + prove -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0 + + # NOTE: this is currently in alpha, this usage will likely change! + +=cut + +use strict; +use warnings; + +use TAP::Formatter::HTML; + +our $VERSION = '0.11'; + +sub import { + my ($class, @args) = @_; + # deprecated, do nothing + return $class; +} + +sub load { + my ($class, $p) = @_; + my @args = @{ $p->{args} }; + my $app = $p->{app_prove}; + + # parse the args + my %TFH_args; + foreach my $arg (@args) { + my ($key, $val) = split(/:/, $arg, 2); + if (grep {$key eq $_} qw(css_uri js_uri)) { + push @{ $TFH_args{$key . 's'}}, $val; + } else { + $TFH_args{$key} = $val; + } + } + + # set the formatter to use + $app->formatter( 'TAP::Formatter::HTML' ); + + # set ENV vars in order to pass args to TAP::Formatter::HTML + # horrible, but it's currently the only way :-/ + while (my ($key, $val) = each %TFH_args) { + $val = join( ':', @$val ) if (ref($val) eq 'ARRAY'); + $ENV{"TAP_FORMATTER_HTML_".uc($key)} = $val; + } + + # we're done + return $class; +} + + +1; + +__END__ + +=head1 DESCRIPTION + +This is a quick & dirty second attempt at making L easier +to use from the command line. It will change once L has better +support for plugins than need to take cmdline data. + +The original goal was to be able to specify all the args on the cmdline, ala: + + prove --html=output.html --css-uri foo.css --css-uri bar.css --force-inline-css 0 + +But this is currently not possible with the way the L plugin system +works. + +As a compromise, you must use the following syntax: + + prove -P HTML=arg1:val1,arg2:val2,... + +Where I is any L parameter that is configurable via +C<%ENV>. + +=head2 Example + + prove -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0 + +This will cause L to load this plugin, which loads L +for you, and sets I to C to save you some typing. + +To configure L, the following C<%ENV> vars are set: + + TAP_FORMATTER_HTML_OUTFILE=out.html + TAP_FORMATTER_HTML_FORCE_INLINE_CSS=0 + TAP_FORMATTER_HTML_CSS_URIS=style.css + TAP_FORMATTER_HTML_JS_URIS=func.js + +Yes, you can pass 2 or more I or I args. + +=head2 %ENV vars?! + +Briefly, L currently only lets you specify the C for +L, it doesn't let you instantiate a formatter, or pass config to +the formatter. + +I If it bugs you too, +then join the L devs and help us fix it ;-). + +=head1 BUGS + +Please use http://rt.cpan.org to report any issues. + +=head1 AUTHOR + +Steve Purkis + +=head1 COPYRIGHT + +Copyright (c) 2008-2010 Steve Purkis , S Purkis Consulting Ltd. +All rights reserved. + +This module is released under the same terms as Perl itself. + +=head1 SEE ALSO + +L, L, L + +=cut diff --git a/lib/TAP/Formatter/HTML.pm b/lib/TAP/Formatter/HTML.pm new file mode 100644 index 0000000..6a6bbd7 --- /dev/null +++ b/lib/TAP/Formatter/HTML.pm @@ -0,0 +1,913 @@ +=head1 NAME + +TAP::Formatter::HTML - TAP Test Harness output delegate for html output + +=head1 SYNOPSIS + + ## + ## command-line usage (alpha): + ## + prove -m -Q -P HTML=outfile:out.html,css_uri:style.css,js_uri:foo.js,force_inline_css:0 + + # backwards compat usage: + prove -m -Q --formatter=TAP::Formatter::HTML >output.html + + # for more detail: + perldoc App::Prove::Plugin::HTML + + ## + ## perl usage: + ## + use TAP::Harness; + + my @tests = glob( 't/*.t' ); + my $harness = TAP::Harness->new({ formatter_class => 'TAP::Formatter::HTML', + merge => 1 }); + $harness->runtests( @tests ); + # prints HTML to STDOUT by default + + # or if you really don't want STDERR merged in: + my $harness = TAP::Harness->new({ formatter_class => 'TAP::Formatter::HTML' }); + + # to use a custom formatter: + my $fmt = TAP::Formatter::HTML->new; + $fmt->css_uris([])->inline_css( $my_css ) + ->js_uris(['http://mysite.com/jquery.js', 'http://mysite.com/custom.js']) + ->inline_js( '$(div.summary).hide()' ); + + my $harness = TAP::Harness->new({ formatter => $fmt, merge => 1 }); + + # to output HTML to a file[handle]: + $fmt->output_fh( $fh ); + $fmt->output_file( '/tmp/foo.html' ); + + # you can use your own customized templates too: + $fmt->template('custom.tt2') + ->template_processor( Template->new ) + ->force_inline_css(0) + ->force_inline_js(0); + +=cut + +package TAP::Formatter::HTML; + +use strict; +use warnings; + +use URI; +use URI::file; +use Template; +use POSIX qw( ceil ); +use IO::File; +use File::Temp qw( tempfile tempdir ); +use File::Spec::Functions qw( catdir catfile file_name_is_absolute rel2abs ); + +use TAP::Formatter::HTML::Session; + +# DEBUG: +#use Data::Dumper 'Dumper'; + +use base qw( TAP::Base ); +use accessors qw( verbosity stdout output_fh escape_output tests session_class sessions + template_processor template html html_id_iterator minify color + css_uris js_uris inline_css inline_js abs_file_paths force_inline_css force_inline_js ); + +use constant default_session_class => 'TAP::Formatter::HTML::Session'; +use constant default_template => 'TAP/Formatter/HTML/default_report.tt2'; +use constant default_js_uris => ['file:TAP/Formatter/HTML/jquery-1.4.2.min.js', + 'file:TAP/Formatter/HTML/jquery.tablesorter-2.0.3.min.js', + 'file:TAP/Formatter/HTML/default_report.js']; +use constant default_css_uris => ['file:TAP/Formatter/HTML/default_page.css', + 'file:TAP/Formatter/HTML/default_report.css']; + +use constant severity_map => { + '' => 0, + 'very-low' => 1, + 'low' => 2, + 'med' => 3, + 'high' => 4, + 'very-high' => 5, + 0 => '', + 1 => 'very-low', + 2 => 'low', + 3 => 'med', + 4 => 'high', + 5 => 'very-high', + }; + +our $VERSION = '0.11'; +our $FAKE_WIN32_URIS = 0; # for testing only + +sub _initialize { + my ($self, $args) = @_; + + $args ||= {}; + $self->SUPER::_initialize($args); + + my $stdout_fh = IO::File->new_from_fd( fileno(STDOUT), 'w' ) + or die "Error opening STDOUT for writing: $!"; + + $self->verbosity( 0 ) + ->stdout( $stdout_fh ) + ->output_fh( $stdout_fh ) + ->minify( 1 ) + ->escape_output( 0 ) + ->abs_file_paths( 1 ) + ->abs_file_paths( 1 ) + ->force_inline_css( 1 ) + ->force_inline_js( 0 ) + ->session_class( $self->default_session_class ) + ->template_processor( $self->default_template_processor ) + ->template( $self->default_template ) + ->js_uris( $self->default_js_uris ) + ->css_uris( $self->default_css_uris ) + ->inline_js( '' ) + ->inline_css( '' ) + ->sessions( [] ); + + $self->check_for_overrides_in_env; + + # Laziness... + # trust the user knows what they're doing with the args: + foreach my $key (keys %$args) { + $self->$key( $args->{$key} ) if ($self->can( $key )); + } + + $self->html_id_iterator( $self->create_iterator( $args ) ); + + return $self; +} + +sub check_for_overrides_in_env { + my $self = shift; + + if (my $file = $ENV{TAP_FORMATTER_HTML_OUTFILE}) { + $self->output_file( $file ); + } + + my $force_css = $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_CSS}; + if (defined( $force_css )) { + $self->force_inline_css( $force_css ); + } + + my $force_js = $ENV{TAP_FORMATTER_HTML_FORCE_INLINE_JS}; + if (defined( $force_js )) { + $self->force_inline_js( $force_js ); + } + + if (my $uris = $ENV{TAP_FORMATTER_HTML_CSS_URIS}) { + my $list = [ split( ':', $uris ) ]; + $self->css_uris( $list ); + } + + if (my $uris = $ENV{TAP_FORMATTER_HTML_JS_URIS}) { + my $list = [ split( ':', $uris ) ]; + $self->js_uris( $list ); + } + + if (my $file = $ENV{TAP_FORMATTER_HTML_TEMPLATE}) { + $self->template( $file ); + } + + return $self; +} + +sub default_template_processor { + my $path = __FILE__; + $path =~ s/.TAP.Formatter.HTML.pm$//; + return Template->new( + # arguably shouldn't compile as this is only used once + COMPILE_DIR => catdir( tempdir( CLEANUP => 1 ), 'TAP-Formatter-HTML' ), + COMPILE_EXT => '.ttc', + INCLUDE_PATH => $path, + ); +} + + +sub output_file { + my ($self, $file) = @_; + my $fh = IO::File->new( $file, 'w' ) + or die "Error opening '$file' for writing: $!"; + $self->output_fh( $fh ); +} + +sub create_iterator { + my $self = shift; + my $args = shift || {}; + my $prefix = $args->{html_id_prefix} || 't'; + my $i = 0; + my $iter = sub { return $prefix . $i++ }; +} + +sub verbose { + my $self = shift; + # emulate a classic accessor for compat w/TAP::Formatter::Console: + if (@_) { $self->verbosity(1) } + return $self->verbosity >= 1; +} + +sub quiet { + my $self = shift; + # emulate a classic accessor for compat w/TAP::Formatter::Console: + if (@_) { $self->verbosity(-1) } + return $self->verbosity <= -1; +} + +sub really_quiet { + my $self = shift; + # emulate a classic accessor for compat w/TAP::Formatter::Console: + if (@_) { $self->verbosity(-2) } + return $self->verbosity <= -2; +} + +sub silent { + my $self = shift; + # emulate a classic accessor for compat w/TAP::Formatter::Console: + if (@_) { $self->verbosity(-3) } + return $self->verbosity <= -3; +} + +# Called by Test::Harness before any test output is generated. +sub prepare { + my ($self, @tests) = @_; + # warn ref($self) . "->prepare called with args:\n" . Dumper( \@tests ); + $self->info( 'running ', scalar @tests, ' tests' ); + $self->tests( [@tests] ); +} + +# Called to create a new test session. A test session looks like this: +# +# my $session = $formatter->open_test( $test, $parser ); +# while ( defined( my $result = $parser->next ) ) { +# $session->result($result); +# exit 1 if $result->is_bailout; +# } +# $session->close_test; +sub open_test { + my ($self, $test, $parser) = @_; + #warn ref($self) . "->open_test called with args: " . Dumper( [$test, $parser] ); + my $session = $self->session_class->new({ test => $test, + parser => $parser, + formatter => $self }); + push @{ $self->sessions }, $session; + return $session; +} + +# $str = $harness->summary( $aggregate ); +# +# C produces the summary report after all tests are run. The argument is +# an aggregate. +sub summary { + my ($self, $aggregate) = @_; + #warn ref($self) . "->summary called with args: " . Dumper( [$aggregate] ); + + # farmed out to make sub-classing easy: + my $report = $self->prepare_report( $aggregate ); + $self->generate_report( $report ); + + # if silent is set, only print HTML if we're not printing to stdout + if (! $self->silent or $self->output_fh->fileno != fileno(STDOUT)) { + print { $self->output_fh } ${ $self->html }; + $self->output_fh->flush; + } + + return $self; +} + +sub generate_report { + my ($self, $r) = @_; + + $self->check_uris; + $self->slurp_css if $self->force_inline_css; + $self->slurp_js if $self->force_inline_js; + + my $params = { + report => $r, + js_uris => $self->js_uris, + css_uris => $self->css_uris, + inline_js => $self->inline_js, + inline_css => $self->inline_css, + formatter => { class => ref( $self ), + version => $self->VERSION }, + }; + + my $html = ''; + $self->template_processor->process( $self->template, $params, \$html ) + || die $self->template_processor->error; + + $self->html( \$html ); + $self->minify_report if $self->minify; + + return $self; +} + +# try and reduce the size of the report +sub minify_report { + my $self = shift; + my $html_ref = $self->html; + $$html_ref =~ s/^\t+//mg; + return $self; +} + +# convert all uris to URI objs +# check file uris (if relative & not found, try & find them in @INC) +sub check_uris { + my ($self) = @_; + + foreach my $uri_list ($self->js_uris, $self->css_uris) { + # take them out of the list to verify, push them back on later + my @uris = splice( @$uri_list, 0, scalar @$uri_list ); + foreach my $uri (@uris) { + if (($^O =~ /win32/i or $FAKE_WIN32_URIS) + and $uri =~ /^(?:(?:file)|(?:\w:)?\\)/) { + $uri = URI::file->new($uri, 'win32'); + } else { + $uri = URI->new( $uri ); + } + if ($uri->scheme && $uri->scheme eq 'file') { + my $path = $uri->path; + unless (file_name_is_absolute($path)) { + my $new_path; + if (-e $path) { + $new_path = rel2abs( $path ) if ($self->abs_file_paths); + } else { + $new_path = $self->find_in_INC( $path ); + } + if ($new_path) { + if (($^O =~ /win32/i or $FAKE_WIN32_URIS)) { + $uri = URI::file->new("file://$new_path", 'win32'); + } else { + $uri->path( $new_path ); + } + } + } + } + push @$uri_list, $uri; + } + } + + return $self; +} + +sub prepare_report { + my ($self, $a) = @_; + + my $r = { + tests => [], + start_time => '?', + end_time => '?', + elapsed_time => $a->elapsed_timestr, + }; + + + # add aggregate test info: + for my $key (qw( + total + has_errors + has_problems + failed + parse_errors + passed + skipped + todo + todo_passed + wait + exit + )) { + $r->{$key} = $a->$key; + } + + # do some other handy calcs: + $r->{actual_passed} = $r->{passed} + $r->{todo_passed}; + if ($r->{total}) { + $r->{percent_passed} = sprintf('%.1f', $r->{actual_passed} / $r->{total} * 100); + } else { + $r->{percent_passed} = 0; + } + + # estimate # files (# sessions could be different?): + $r->{num_files} = scalar @{ $self->sessions }; + + # add test results: + my $total_time = 0; + foreach my $s (@{ $self->sessions }) { + my $sr = $s->as_report; + push @{$r->{tests}}, $sr; + $total_time += $sr->{elapsed_time} || 0; + } + $r->{total_time} = $total_time; + + # estimate total severity: + my $smap = $self->severity_map; + my $severity = 0; + $severity += $smap->{$_->{severity} || ''} for @{$r->{tests}}; + my $avg_severity = 0; + if (scalar @{$r->{tests}}) { + $avg_severity = ceil($severity / scalar( @{$r->{tests}} )); + } + $r->{severity} = $smap->{$avg_severity}; + + # TODO: coverage? + + return $r; +} + +# adapted from Test::TAP::HTMLMatrix +# always return abs file paths if $self->abs_file_paths is on +sub find_in_INC { + my ($self, $file) = @_; + + foreach my $path (grep { not ref } @INC) { + my $target = catfile($path, $file); + if (-e $target) { + $target = rel2abs($target) if $self->abs_file_paths; + return $target; + } + } + + # non-fatal + $self->log("Warning: couldn't find $file in \@INC"); + return; +} + +# adapted from Test::TAP::HTMLMatrix +# slurp all 'file' uris, if possible +# note: doesn't remove them from the css_uris list, just in case... +sub slurp_css { + my ($self) = shift; + $self->info("slurping css files inline"); + + my $inline_css = ''; + $self->_slurp_uris( $self->css_uris, \$inline_css ); + + # append any inline css so it gets interpreted last: + $inline_css .= "\n" . $self->inline_css if $self->inline_css; + + $self->inline_css( $inline_css ); +} + +sub slurp_js { + my ($self) = shift; + $self->info("slurping js files inline"); + + my $inline_js = ''; + $self->_slurp_uris( $self->js_uris, \$inline_js ); + + # append any inline js so it gets interpreted last: + $inline_js .= "\n" . $self->inline_js if $self->inline_js; + + $self->inline_js( $inline_js ); +} + +sub _slurp_uris { + my ($self, $uris, $slurp_to_ref) = @_; + + foreach my $uri (@$uris) { + my $scheme = $uri->scheme; + if ($scheme && $scheme eq 'file') { + my $path = $uri->path; + if (-e $path) { + if (open my $fh, $path) { + local $/ = undef; + $$slurp_to_ref .= <$fh>; + $$slurp_to_ref .= "\n"; + } else { + $self->log("Warning: couldn't open $path: $!"); + } + } else { + $self->log("Warning: couldn't read $path: file does not exist!"); + } + } else { + $self->log("Warning: can't include $uri inline: not a file uri"); + } + } + + return $slurp_to_ref; +} + + + +sub log { + my $self = shift; + push @_, "\n" unless grep {/\n/} @_; + $self->_output( @_ ); + return $self; +} + +sub info { + my $self = shift; + return unless $self->verbose; + return $self->log( @_ ); +} + +sub log_test { + my $self = shift; + return if $self->really_quiet; + return $self->log( @_ ); +} + +sub log_test_info { + my $self = shift; + return if $self->quiet; + return $self->log( @_ ); +} + +sub _output { + my $self = shift; + return if $self->silent; + if (ref($_[0]) && ref( $_[0]) eq 'SCALAR') { + # DEPRECATED: printing HTML: + print { $self->stdout } ${ $_[0] }; + } else { + unshift @_, '# ' if $self->escape_output; + print { $self->stdout } @_; + } +} + + +1; + + +__END__ + +=head1 DESCRIPTION + +This module provides HTML output formatting for L (a replacement +for L. It is largely based on ideas from +L (which was built on L and thus had a +few limitations - hence this module). For sample output, see: + +L + +This module is targeted at all users of automated test suites. It's meant to +make reading test results easier, giving you a visual summary of your test suite +and letting you drill down into individual failures (which will hopefully make +testing more likely to happen at your organization ;-). + +The design goals are: + +=over 4 + +=item * + +I + +Once you've got your test report, it should be obvious how to use it. + +=item * + +I + +It should be helpful by pointing out I & I your test suite is +breaking. If you've written your tests well, it should give you enough info to +start tracking down the issue. + +=item * + +I + +Eg: should be a clean install from CPAN, and you shouldn't need to modify your +existing test suite to get up & running, though I unfortunately>. + +=item * + +I + +You shouldn't need to do any custom-coding to get it working - the default +configuration & templates should be enough to get started with. Once installed +it should be a matter of running: + + % prove -m -Q --formatter=TAP::Formatter::HTML >output.html + +From your project's home dir, and opening the resulting file. + +=item * + +I + +You should be able to configure & customize it to suit your needs. As such, +css, javascript and templates are all configurable. + +=back + +=head1 METHODS + +=head2 CONSTRUCTOR + +=head3 new + + my $fmt = $class->new({ %args }); + +=head2 ACCESSORS + +All chaining L: + +=head3 verbosity + + $fmt->verbosity( [ $v ] ) + +Verbosity level, as defined in L: + + 1 verbose Print individual test results (and more) to STDOUT. + 0 normal + -1 quiet Suppress some test output (eg: test failures). + -2 really quiet Suppress everything to STDOUT but the HTML report. + -3 silent Suppress all output to STDOUT, including the HTML report. + +Note that the report is also available via L. You can also provide a +custom L (aka L) that will be used instead of +L, even if I is on. + +=head3 stdout + + $fmt->stdout( [ \*FH ] ); + +An L filehandle for catching standard output. Defaults to C. + +=head3 output_fh + + $fmt->output_fh( [ \*FH ] ); + +An L filehandle for printing the HTML report to. Defaults to the +same object as L. + +B If L is set to C, printing to C will +still occur. (that is, assuming you've opened a different file, B +C). + +=head3 output_file + + $fmt->output_file( $file_name ) + +Not strictly an accessor - this is a shortcut for setting L, +equivalent to: + + $fmt->output_fh( IO::File->new( $file_name, 'w' ) ); + +You can set this with the C +environment variable + +=head3 escape_output + + $fmt->escape_output( [ $boolean ] ); + +If set, all output to L is escaped. This is probably only useful +if you're testing the formatter. +Defaults to C<0>. + +=head3 html + + $fmt->html( [ \$html ] ); + +This is a reference to the scalar containing the html generated on the last +test run. Useful if you have L set to C, and have not +provided a custom L to write the report to. + +=head3 tests + + $fmt->tests( [ \@test_files ] ) + +A list of test files we're running, set by L. + +=head3 session_class + + $fmt->session_class( [ $class ] ) + +Class to use for L test sessions. You probably won't need to use +this unless you're hacking or sub-classing the formatter. +Defaults to L. + +=head3 sessions + + $fmt->sessions( [ \@sessions ] ) + +Test sessions added by L. You probably won't need to use this +unless you're hacking or sub-classing the formatter. + +=head3 template_processor + + $fmt->template_processor( [ $processor ] ) + +The template processor to use. +Defaults to a TT2 L