shlomi-fish-homepage / lib / presentations / spork / Perl / Lightning / Test-Run / Spork.slides

presentation_topic: Test::Run
presentation_title: Test::Run - a New and Improved Test Harness
presentation_place: Netanya, Israel
presentation_date: FILL IN
== How it all Started

* I attended a presentation about [TestOOB] and saw that it provided colours.
+* {image:}
+* I decided that I wanted to colour the summary line in Perl.
== How Perl Testing Works

* The Perl scripts output the results of the individual tests in [the TAP Format]:
+* Like:

    ok 1 Description # Directive
    # Diagnostic
    ok 47 Description
    ok 48 Description
    more tests....
+* The Test::Harness module runs the scripts and analyses their TAP instructions, and produces a report.
== Hacking Test::Harness

* So we need to change Test::Harness.
+* Now where's the summary line?
    sub _show_results {
        my($tot, $failedtests) = @_;

        my $pct;
        my $bonusmsg = _bonusmsg($tot);

        if (_all_ok($tot)) {
            print "All tests successful$bonusmsg.\n"; # <--- here
        elsif (!$tot->{tests}){
            die "FAILED--no tests were run for some reason.\n";
        elsif (!$tot->{max}) {
            my $blurb = $tot->{tests}==1 ? "script" : "scripts";
            die "FAILED--$tot->{tests} test $blurb could be run, ".
                "alas--no output ever seen\n";
        else {
            $pct = sprintf("%.2f", $tot->{good} / $tot->{tests} * 100);
            my $percent_ok = 100*$tot->{ok}/$tot->{max};
            my $subpct = sprintf " %d/%d subtests failed, %.2f%% okay.",
                                  $tot->{max} - $tot->{ok}, $tot->{max},

            my($fmt_top, $fmt) = _create_fmts($failedtests);

            # Now write to formats
            for my $script (sort keys %$failedtests) {
              $Curtest = $failedtests->{$script};
            if ($tot->{bad}) {
                $bonusmsg =~ s/^,\s*//;
                print "$bonusmsg.\n" if $bonusmsg;
                die "Failed $tot->{bad}/$tot->{tests} test scripts, $pct% okay.".

        printf("Files=%d, Tests=%d, %s\n",
               $tot->{files}, $tot->{max}, timestr($tot->{bench}, 'nop'));

+=== Problems

+* A monolithic function with just one line to change.
+* There isn't an object instance for easy inheritance and over-riding.
+* A lot of similar issues in the rest of the code.
== Solution

* Let's create a better test harness, based on Test::Harness, but more:
+00 Modular.
+00 Object-oriented.
+00 Extensible.
== Let's start... coding!

* The code of Test-Harness was forked.
+* It was converted to have an object interface.
+** All functions were converted to accept the |$self| object reference as a first argument.
+* Large functions were broken into smaller ones.
+* Hashes were converted into objects.
+* Arguments passed from function to function were converted into object variables.
+* Object variables became handled using Class::Accessor accessors.
+* Several new classes were created.
== Front-end and Back-end

* Test::Run is the back-end that does all the testing.
+* Test::Run::CmdLine processes environment variables, and feeds them into Test::Run as constructor arguments.
+* Test::Harness accepts several environment variables and package variables as parameters.
+** They were all converted to object variables with accessors in Test::Run.
== Plugins

* One can specify plug-ins to Test::Run::CmdLine from the environment variable.
+* They in turn can specify plug-ins to the Test::Run back-end.
== Back to Colouring...

* Now we can write this plugin:

    package Test::Run::Plugin::ColorSummary;

    use warnings;
    use strict;

    use NEXT;
    use Term::ANSIColor;

    sub _report_success
        my $self = shift;
        print color("bold blue");
        print color("reset");

    sub _handle_runtests_error
        my $self = shift;
        my (%args) = @_;
        my $error = $args{'error'};

        print STDERR color("bold red");
        print STDERR $error;
        print STDERR color("reset");
        # Workaround to make sure color("reset") is accepted and a red cursor
        # is not displayed.
        print STDERR "\n";

== Back to Colouring (2)...

* And get:

+* {image:}
== Where to find everything.

* The most up to date versions of the modules are in the Subversion repository:


* Also on CPAN -
== Thank you!