Test-Unit-Lite

 view release on metacpan or  search on metacpan

lib/Test/Unit/Lite.pm  view on Meta::CPAN

use warnings;

our $VERSION = '0.1202';

use Carp ();
use File::Spec ();
use File::Basename ();
use File::Copy ();
use File::Path ();
use Symbol ();


# Can't use Exporter 'import'. Compatibility with Perl 5.6
use Exporter ();
BEGIN { *import = \&Exporter::import };
our @EXPORT = qw{ bundle all_tests };


# Copy this module to inc subdirectory of the source distribution
sub bundle {
    -f 'Makefile.PL' or -f 'Build.PL'
        or die "Cannot find Makefile.PL or Build.PL in current directory\n";

    my $src = __FILE__;
    my $dst = "inc/Test/Unit/Lite.pm";


    my @src = split m{/}, $src;
    my @dst = split m{/}, $dst;
    my $srcfile = File::Spec->catfile(@src);
    my $dstfile = File::Spec->catfile(@dst);

    die "Cannot bundle to itself: $srcfile\n" if $srcfile eq $dstfile;
    print "Copying $srcfile -> $dstfile\n";

    my $dstdir = File::Basename::dirname($dstfile);

    -d $dstdir or File::Path::mkpath([$dstdir], 0, oct(777) & ~umask);

    File::Copy::cp($srcfile, $dstfile) or die "Cannot copy $srcfile to $dstfile: $!\n";
}

sub all_tests {
    Test::Unit::TestRunner->new->start('Test::Unit::Lite::AllTests');
}


{
    package Test::Unit::TestCase;
    use Carp ();
    our $VERSION = $Test::Unit::Lite::VERSION;

    our %Seen_Refs = ();
    our @Data_Stack;
    my $DNE = bless [], 'Does::Not::Exist';

    sub new {
        my ($class) = @_;
        $class = ref $class if ref $class;
        my $self = {};
        return bless $self => $class;
    }

    sub set_up { }

    sub tear_down { }

    sub list_tests {
        my ($self) = @_;

        my $class = ref $self || $self;

        my @tests;

        my %seen_isa;
        my $list_base_tests;
        $list_base_tests = sub {
            my ($class) = @_;
            foreach my $isa (@{ *{ Symbol::qualify_to_ref("${class}::ISA") } }) {
                next unless $isa->isa(__PACKAGE__);
                $list_base_tests->($isa) unless $seen_isa{$isa};
                $seen_isa{$isa} = 1;
                push @tests, grep { /^test_/ } keys %{ *{ Symbol::qualify_to_ref("${class}::") } };
            };
        };
        $list_base_tests->($class);

        my %uniq_tests = map { $_ => 1 } @tests;
        @tests = sort keys %uniq_tests;

        return wantarray ? @tests : [ @tests ];
    }

    sub __croak {
        my ($default_message, $custom_message) = @_;
        $default_message = '' unless defined $default_message;
        $custom_message = '' unless defined $custom_message;
        my $n = 1;

        my ($file, $line) = (caller($n++))[1,2];
        my $caller;
        $n++ while (defined( $caller = caller($n) ) and not eval { $caller->isa('Test::Unit::TestSuite') });

        my $sub = (caller($n))[3] || '::';
        $sub =~ /^(.*)::([^:]*)$/;
        my ($test, $unit) = ($1, $2);

        my $message = "$file:$line - $test($unit)\n$default_message\n$custom_message";
        chomp $message;

        no warnings 'once';
        local $Carp::Internal{'Test::Unit::TestCase'} = 1;
        Carp::confess("$message\n");
    }

    sub fail {
        my ($self, $msg) = @_;
        $msg = '' unless defined $msg;
        __croak $msg;
    }

lib/Test/Unit/Lite.pm  view on Meta::CPAN

        return $ok;
    }

    sub _format_stack {
        my ($self, @Stack) = @_;

        my $var = '$FOO';
        my $did_arrow = 0;
        foreach my $entry (@Stack) {
            my $type = $entry->{type} || '';
            my $idx  = $entry->{'idx'};
            if( $type eq 'HASH' ) {
                $var .= "->" unless $did_arrow++;
                $var .= "{$idx}";
            }
            elsif( $type eq 'ARRAY' ) {
                $var .= "->" unless $did_arrow++;
                $var .= "[$idx]";
            }
            elsif( $type eq 'REF' ) {
                $var = "\${$var}";
            }
        }

        my @vals = @{$Stack[-1]{vals}}[0,1];

        my @vars = ();
        ($vars[0] = $var) =~ s/\$FOO/  \$a/;
        ($vars[1] = $var) =~ s/\$FOO/  \$b/;

        my $out = "Structures begin differing at:\n";
        foreach my $idx (0..$#vals) {
            my $val = $vals[$idx];
            $vals[$idx] = !defined $val ? 'undef' :
                          $val eq $DNE  ? 'Does not exist'
                                        : "'$val'";
        }

        $out .= "$vars[0] = $vals[0]\n";
        $out .= "$vars[1] = $vals[1]";

        return $out;
    }

    BEGIN { $INC{'Test/Unit/TestCase.pm'} = __FILE__; }
}

{
    package Test::Unit::Result;
    our $VERSION = $Test::Unit::Lite::VERSION;

    sub new {
        my ($class) = @_;
        my $self = {
            'messages' => [],
            'errors'   => 0,
            'failures' => 0,
            'passes'   => 0,
        };

        return bless $self => $class;
    }

    sub messages {
        my ($self) = @_;
        return $self->{messages};
    }

    sub errors {
        my ($self) = @_;
        return $self->{errors};
    }

    sub failures {
        my ($self) = @_;
        return $self->{failures};
    }

    sub passes {
        my ($self) = @_;
        return $self->{passes};
    }

    sub add_error {
        my ($self, $test, $message, $runner) = @_;
        $self->{errors}++;
        my $result = {test => $test, type => 'ERROR', message => $message};
        push @{$self->messages}, $result;
        $runner->print_error($result) if defined $runner;
    }

    sub add_failure {
        my ($self, $test, $message, $runner) = @_;
        $self->{failures}++;
        my $result = {test => $test, type => 'FAILURE', message => $message};
        push @{$self->messages}, $result;
        $runner->print_failure($result) if defined $runner;
    }

    sub add_pass {
        my ($self, $test, $message, $runner) = @_;
        $self->{passes}++;
        my $result = {test => $test, type => 'PASS', message => $message};
        push @{$self->messages}, $result;
        $runner->print_pass($result) if defined $runner;
    }

    BEGIN { $INC{'Test/Unit/Result.pm'} = __FILE__; }
}

{
    package Test::Unit::TestSuite;
    our $VERSION = $Test::Unit::Lite::VERSION;

    sub empty_new {
        my ($class, $name) = @_;
        my $self = {
            'name' => defined $name ? $name : 'Test suite',
            'units' => [],
        };

        return bless $self => $class;
    }

    sub new {
        my ($class, $test) = @_;

        my $self = {
            'name' => 'Test suite',
            'units' => [],
        };

        if (defined $test and not ref $test) {
            # untaint $test
            $test =~ /([A-Za-z0-9:-]*)/;
            $test = $1;
            eval "use $test;";
            die if $@;
        }
        elsif (not defined $test) {
            $test = $class;
        }

        if (defined $test and $test->isa('Test::Unit::TestSuite')) {
            $class = ref $test ? ref $test : $test;
            $self->{name} = $test->name if ref $test;
            $self->{units} = $test->units if ref $test;
        }
        elsif (defined $test and $test->isa('Test::Unit::TestCase')) {
            $class = ref $test ? ref $test : $test;
            $self->{units} = [ $test ];
        }
        else {
            require Carp;
            Carp::croak(sprintf("usage: %s->new([CLASSNAME | TEST])\n", __PACKAGE__));
        }

        return bless $self => $class;
    }

    sub name {
        return $_[0]->{name};
    }

    sub units {
        return $_[0]->{units};
    }

    sub add_test {
        my ($self, $unit) = @_;

        if (not ref $unit) {
            # untaint $unit
            $unit =~ /([A-Za-z0-9:-]*)/;
            $unit = $1;
            eval "use $unit;";
            die if $@;
            return unless $unit->isa('Test::Unit::TestCase');
        }

        return push @{ $self->{units} }, ref $unit ? $unit : $unit->new;
    }

    sub count_test_cases {
        my ($self) = @_;

        my $plan = 0;

        foreach my $unit (@{ $self->units }) {
            $plan += scalar @{ $unit->list_tests };
        }
        return $plan;
    }

    sub run {
        my ($self, $result, $runner) = @_;

        die "Undefined result object" unless defined $result;

        foreach my $unit (@{ $self->units }) {
            foreach my $test (@{ $unit->list_tests }) {
                my $unit_test = (ref $unit ? ref $unit : $unit) . '::' . $test;
                my $add_what;
                my $e = '';
                eval {
                    $unit->set_up;
                };
                if ($@) {
                    $e = "$@";
                    $add_what = 'add_error';
                }
                else {
                    eval {
                        $unit->$test;
                    };
                    if ($@) {
                        $e = "$@";
                        $add_what = 'add_failure';
                    }
                    else {
                        $add_what = 'add_pass';
                    };
                };
                eval {
                    $unit->tear_down;
                };
                if ($@) {
                    $e .= "$@";
                    $add_what = 'add_error';
                };
                $result->$add_what($unit_test, $e, $runner);
            }
        }
        return;
    }

    BEGIN { $INC{'Test/Unit/TestSuite.pm'} = __FILE__; }
}

{
    package Test::Unit::TestRunner;
    our $VERSION = $Test::Unit::Lite::VERSION;

    sub new {
        my ($class, $fh_out, $fh_err) = @_;
        $fh_out = \*STDOUT unless defined $fh_out;
        $fh_err = \*STDERR unless defined $fh_err;
        _autoflush($fh_out);
        _autoflush($fh_err);
        my $self = {
            'suite'  => undef,
            'fh_out' => $fh_out,
            'fh_err' => $fh_err,
        };
        return bless $self => $class;
    }

    sub fh_out {
        my ($self) = @_;
        return $self->{fh_out};
    }

    sub fh_err {
        my ($self) = @_;
        return $self->{fh_err};
    }

    sub result {
        my ($self) = @_;
        return $self->{result};
    }

    sub _autoflush {
        my ($fh) = @_;
        my $old_fh = select $fh;
        $| = 1;
        select $old_fh;
    }

    sub suite {
        my ($self) = @_;
        return $self->{suite};
    }

    sub print_header {
    }

    sub print_error {
        my ($self, $result) = @_;
        print { $self->fh_out } "E";
    }

    sub print_failure {
        my ($self, $result) = @_;
        print { $self->fh_out } "F";
    }

    sub print_pass {
        my ($self, $result) = @_;
        print { $self->fh_out } ".";
    }

    sub print_footer {
        my ($self, $result) = @_;
        printf { $self->fh_out } "\nTests run: %d", $self->suite->count_test_cases;
        if ($result->errors) {
            printf { $self->fh_out } ", Errors: %d", $result->errors;
        }
        if ($result->failures) {
            printf { $self->fh_out } ", Failures: %d", $result->failures;
        }
        print { $self->fh_out } "\n";
        if ($result->errors) {
            print { $self->fh_out } "\nERRORS!!!\n\n";
            foreach my $message (@{ $result->messages }) {



( run in 0.318 second using v1.01-cache-2.11-cpan-eab888a1d7d )