NAME Test::Trivial - Declutter and simplify tests SYNOPSIS use Test::Trivial tests => 11; OK $expression; NOK $expression; IS $got => $expected; ISNT $got => $expected; ISA $obj => $class; ID $refA => $refB; EQ $numA => $numB; LIKE $got => qr/regex/; UNLIKE $got => qr/regex/; IS ERR { die "OMG No!\n" } => "OMG No!\n"; TODO IS $got, $expected; DESCRIPTION "Test::Trivial" was written to allow test writters to trivially write tests while still allowing the test code to be readable. The output upon failure has been modified to provide better diagnostics when things go wrong, including the source line number for the failed test. Global getopt options are automatically added to all tests files to allow for easier debugging when things go wrong. OPTIONS --verbose --verbose passed on the command line to any Test::Trivial test file will automatically print out verbose data for each test. Primarily this will use Data::Dumper to print out the arguments to the various operators. --fatal --fatal passed will automatically cause the test run to abort on the first (non TODO) "not ok" check. --log[=] --log can be used to force verbose log to the the given log file name (default $0.log) while allowing non-verbose output to go to the terminal. This can be useful to diagnose bugs that happen during the night when run under some automated testing. OK Takes one argument which will be evaluated for boolean truth. The expression will be evaluated in scalar context. Examples: OK 1 + 1 == 2; # output: # ok 1 - 1 + 1 == 2 OK 1 + 1 == 3; # output: # # Time: 2012-02-28 12:20:19 PM # ./example.t:5:1: Test 2 Failed # not ok 2 - 1 + 1 == 3 # # Failed test '1 + 1 == 3' @array = (1,2,3); OK @array; # output: # ok 3 - @array @array = (); OK @array; # output: # # Time: 2012-02-28 12:20:19 PM # ./example.t:18:1: Test 4 Failed # not ok 4 - @array # # Failed test '@array' NOK Takes one argument which is evaluated for boolean false. The expression will be evaluated in scalar context. Examples: NOK 1 + 1 == 2; # output: # # Time: 2012-02-28 12:25:45 PM # ./example.t:1:1: Test 1 Failed # not ok 1 - not [1 + 1 == 2] # # Failed test 'not [1 + 1 == 2]' NOK 1 + 1 == 3; # output: # ok 2 - not [1 + 1 == 3] @array = (1,2,3); NOK @array; # output: # # Time: 2012-02-28 12:25:45 PM # ./example.t:13:1: Test 3 Failed # not ok 3 - not [@array] # # Failed test 'not [@array]' @array = (); NOK @array; # output: # ok 4 - not [@array] IS Takes two arguments and compares the values (or structures if references). The arguments will be evaluated in scalar context. If the inputs are strings with embedded newlines then Text::Diff will be used to print out the differences when the strings dont match. If the inputs are references then the structures will be compared recusively for equivalence. Examples: my $string = "abc"; IS $string => "abc"; # output: # ok 1 - $string == "abc" my @array = (1,2,3); IS @array => 3; # output: # ok 2 - @array == 3 IS "a\nb\n" => "a\nc\n"; # output: # # Time: 2012-02-28 01:27:33 PM # ./example.t:10:1: Test 3 Failed # not ok 3 - "a\nb\n" == "a\nc\n" # # Failed test '"a\nb\n" == "a\nc\n"' # # --- got # # +++ expected # # @@ -1,2 +1,2 @@ # # a # # -b # # +c IS [1,2,3,5,8], [1,2,3,5,8]; # output: # ok 4 - [1,2,3,5,8] == [1,2,3,5,8] IS [{a=>1}], [{b=>1}]; # output: # # Time: 2012-02-28 01:27:33 PM # ./example.t:26:1: Test 5 Failed # not ok 5 - [{a=>1}] == [{b=>1}] # # Failed test '[{a=>1}] == [{b=>1}]' # # Structures begin differing at: # # $got->[0]{b} = Does not exist # # $expected->[0]{b} = '1' IS substr("abcdef",0,3), "abc"; # output: # ok 6 - substr("abcdef",0,3) == "abc" ISNT Takes two arguments and compares the values (or structures if references) for non equivalence. The arguments will be evaluated in scalar context. If the inputs are references then the structures will be compared recusively for non equivalence. Examples: my $string = "abc"; ISNT $string => "abc"; # output: # # Time: 2012-02-28 01:45:18 PM # ./example.t:2:1: Test 1 Failed # not ok 1 - $string != "abc" # # Failed test '$string != "abc"' # # got: 'abc' # # expected: anything else my @array = (1,2,3); ISNT @array => 3; # output: # # Time: 2012-02-28 01:45:18 PM # ./example.t:12:1: Test 2 Failed # not ok 2 - @array != 3 # # Failed test '@array != 3' # # got: '3' # # expected: anything else ISNT "a\nb" => "a\nc"; # output: # ok 3 - "a\nb" != "a\nc" ISNT [1,2,3,5,8], [1,2,3,5,8]; # output: # not ok 4 - [1,2,3,5,8] != [1,2,3,5,8] # # Failed test '[1,2,3,5,8] != [1,2,3,5,8]' ISNT [{a=>1}], [{b=>1}]; # output: # ok 5 - [{a=>1}] != [{b=>1}] ISNT substr("abcdef",0,3), "abc"; # output: # # Time: 2012-02-28 01:45:18 PM # ./example.t:34:1: Test 6 Failed # not ok 6 - substr("abcdef",0,3) != "abc" # # Failed test 'substr("abcdef",0,3) != "abc"' # # got: 'abc' # # expected: anything else ISA Takes two arguments and checks to see if the first argument is a reference that inherits from the class/type of the second argument. Examples: ISA [] => "ARRAY"; # output: # ok 1 - [] ISA "ARRAY" ISA {} => "HASH"; # output: # ok 2 - {} ISA "HASH" ISA qr/ABC/ => "REGEXP"; # output: # ok 3 - qr/ABC/ ISA "REGEXP" ISA \*STDIO => "GLOB"; # output: # ok 4 - \*STDIO ISA "GLOB" my $io = IO::File->new(); ISA $io => "IO::File"; # output: # ok 5 - $io ISA "IO::File" ISA $io => "IO::Handle"; # output: # ok 6 - $io ISA "IO::Handle" ISA $io => "Exporter"; # output: # ok 7 - $io ISA "Exporter" ISA $io => "GLOB"; # output: # ok 8 - $io ISA "GLOB" ISA $io => "ARRAY"; # output: # # Time: 2012-02-28 02:03:20 PM # ./example.t:34:1: Test 9 Failed # not ok 9 - $io ISA "ARRAY" # # Failed test '$io ISA "ARRAY"' ISA $io => "IO::Socket"; # output: # # Time: 2012-02-28 02:03:20 PM # ./example.t:41:1: Test 10 Failed # not ok 10 - $io ISA "IO::Socket" # # Failed test '$io ISA "IO::Socket"' ID Takes two arguments and compares them for exact values. ID is similar to IS except that references are compared literally (ie the reference address is compared) instead of recusively comparing the data structures. Examples: my $arr1 = my $arr2 = []; ID $arr1 => $arr2; # output: # ok 1 - $arr1 == $arr2 ID $arr1 => []; # output: # # Time: 2012-02-28 02:35:38 PM # ./example.t:6:1: Test 2 Failed # not ok 2 - $arr1 == [] # # Failed test '$arr1 == []' # # got: 'ARRAY(0x186fd80)' # # expected: 'ARRAY(0x188c588)' my $hash1 = $hash2 = {}; ID $hash1 => $hash2; # output: # ok 3 - $hash1 == $hash2 ID $hash1 => {}; # output: # # Time: 2012-02-28 02:35:38 PM # ./example.t:20:1: Test 4 Failed # not ok 4 - $hash1 == {} # # Failed test '$hash1 == {}' # # got: 'HASH(0x189bcc8)' # # expected: 'HASH(0x1ee95b8)' my %hash = (); my $hash3 = \%hash; ID $hash3 => \%hash; # output: # ok 5 - $hash3 == \%hash EQ Takes two arguments and compares them for numeric equivalence. Examples: EQ 12 => 12; # output: # ok 1 - 12 == 12 EQ 12.00001 => 12; # output: # # Time: 2012-02-28 03:16:49 PM # ./example.t:4:1: Test 2 Failed # not ok 2 - 12.00001 == 12 # # Failed test '12.00001 == 12' # # got: '12.00001' # # expected: '12' EQ 12.0 => 12; # output: # ok 3 - 12.0 == 12 EQ 12.0 / 1.0 => 12; # output: # ok 4 - 12.0 / 1.0 == 12 EQ 0.12E2 => 12; # output: # ok 5 - 0.12E2 == 12 EQ 1200E-2 => 12; # output: # ok 6 - 1200E-2 == 12 EQ 0x0C => 12; # output: # ok 7 - 0x0C == 12 EQ 014 => 12; # output: # ok 8 - 014 == 12 EQ 0b001100 => 12; # output: # ok 9 - 0b001100 == 12 EQ "12" => 12; # output: # ok 10 - "12" == 12 EQ "12.0" => 12; # output: # ok 11 - "12.0" == 12 EQ "0.12E2" => 12; # output: # ok 12 - "0.12E2" == 12 EQ "1200E-2" => 12; # output: # ok 13 - "1200E-2" == 12 EQ "12 Monkeys" => 12; # output: # ok 14 - "12 Monkeys" == 12 LIKE Takes two arguments, the first argument should be a string, and the second argument should be a REGEXP. The regex will be run against the string to verify that there is a successful match. Examples: LIKE "abc" => qr{^a}; # output: # ok 1 - "abc" =~ qr{^a} LIKE "ABC" => qr{^a}i; # output: # ok 2 - "ABC" =~ qr{^a}i LIKE "ABC" => qr/^(?i:a)/; # output: # ok 3 - "ABC" =~ qr/^(?i:a)/ use Regexp::Common; LIKE "123.456E3" => qr[$RE{num}{real}]; # output: # ok 4 - "123.456E3" =~ qr[$RE{num}{real}] LIKE "foo" => qr{bar}; # output: # # Time: 2012-02-28 03:44:35 PM # ./example.t:18:1: Test 5 Failed # not ok 5 - "foo" =~ qr{bar} # # Failed test '"foo" =~ qr{bar}' # # 'foo' # # doesn't match '(?-xism:bar)' UNLIKE Takes two arguments, the first argument should be a string, and the second argument should be a REGEXP. The regex will be run against the string to verify that there is a negative match. Examples: UNLIKE "abc" => qr{^A}; # output: # ok 1 - "abc" !~ qr{^A} UNLIKE "ABC" => qr{^a}i; # output: # # Time: 2012-02-28 03:54:31 PM # ./example.t:5:1: Test 2 Failed # not ok 2 - "ABC" !~ qr{^a}i # # Failed test '"ABC" !~ qr{^a}i' # # 'ABC' # # matches '(?i-xsm:^a)' UNLIKE "ABC" => qr/^(?i:a)/; # output: # # Time: 2012-02-28 03:54:31 PM # ./example.t:14:1: Test 3 Failed # not ok 3 - "ABC" !~ qr/^(?i:a)/ # # Failed test '"ABC" !~ qr/^(?i:a)/' # # 'ABC' # # matches '(?-xism:^(?i:a))' use Regexp::Common; UNLIKE "123.456E3" => qr[$RE{num}{int}]; # output: # # Time: 2012-02-28 03:54:31 PM # ./example.t:24:1: Test 4 Failed # not ok 4 - "123.456E3" !~ qr[$RE{num}{int}] # # Failed test '"123.456E3" !~ qr[$RE{num}{int}]' # # '123.456E3' # # matches '(?-xism:(?:(?:[+-]?)(?:[0123456789]+)))' UNLIKE "foo" => qr{bar}; # output: # ok 5 - "foo" !~ qr{bar} ERR ERR is a wrapper to help capture exceptions to make analyzing error cases easier. The argument to ERR is a subroutine or code block. Examples: package PosixErr; use POSIX qw(strerror); use overload '""' => \&stringify; sub new { bless { code => $_[1] }, $_[0] } sub stringify { strerror($_[0]->{code}) } package main; IS ERR { die "OMG No!\n" } => "OMG No!\n"; # output: # ok 1 - ERR { die "OMG No!\n" } == "OMG No!\n" IS ERR { die PosixErr->new(12) } => PosixErr->new(12); # output: # ok 2 - ERR { die PosixErr->new(12) } == PosixErr->new(12) IS ERR { die PosixErr->new(12) } => "Cannot allocate memory"; # output: # ok 3 - ERR { die PosixErr->new(12) } == "Cannot allocate memory" IS ERR { die PosixErr->new(13) } => "Knock it out, wiseguy"; # output: # # Time: 2012-02-28 04:27:35 PM # ./example.t:20:1: Test 4 Failed # not ok 4 - ERR { die PosixErr->new(13) } == "Knock it out # # Failed test 'ERR { die PosixErr->new(13) } == "Knock it out' # # got: 'Permission denied' # # expected: 'Knock it out, wiseguy' IS ERR { die PosixErr->new(13) } => "Permission denied"; # output: # ok 5 - ERR { die PosixErr->new(13) } == "Permission denied" IS ERR { "ok" } => "ok"; # output: # ok 6 - ERR { "ok" } == "ok" TODO TODO can be used a prefix to any test to indicate that it is a known failure. For futher reading on TODO please read Test::More. Examples: TODO OK 1 == 2; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:1:6: Test 1 Failed # not ok 1 - 1 == 2 # TODO Test Know to fail # # Failed (TODO) test '1 == 2' TODO NOK 1 == 1; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:8:6: Test 2 Failed # not ok 2 - not [1 == 1] # TODO Test Know to fail # # Failed (TODO) test 'not [1 == 1]' TODO IS "abc" => "ABC"; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:15:6: Test 3 Failed # not ok 3 - "abc" == "ABC" # TODO Test Know to fail # # Failed (TODO) test '"abc" == "ABC"' # # got: 'abc' # # expected: 'ABC' TODO ISNT "abc" => "abc"; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:24:6: Test 4 Failed # not ok 4 - "abc" != "abc" # TODO Test Know to fail # # Failed (TODO) test '"abc" != "abc"' # # got: 'abc' # # expected: anything else TODO ISA [] => "HASH"; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:33:6: Test 5 Failed # not ok 5 - [] ISA "HASH" # TODO Test Know to fail # # Failed (TODO) test '[] ISA "HASH"' TODO ID [] => []; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:40:6: Test 6 Failed # not ok 6 - [] == [] # TODO Test Know to fail # # Failed (TODO) test '[] == []' # # got: 'ARRAY(0x1c62a28)' # # expected: 'ARRAY(0x1c62a10)' TODO EQ 123 => 124; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:49:6: Test 7 Failed # not ok 7 - 123 == 124 # TODO Test Know to fail # # Failed (TODO) test '123 == 124' # # got: '123' # # expected: '124' TODO LIKE "abc" => qr/^ABC$/; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:58:6: Test 8 Failed # not ok 8 - "abc" =~ qr/^ABC$/ # TODO Test Know to fail # # Failed (TODO) test '"abc" =~ qr/^ABC$/' # # 'abc' # # doesn't match '(?-xism:^ABC$)' TODO UNLIKE "abc" => qr/^abc$/; # output: # # Time: 2012-02-28 04:39:55 PM # ./example.t:67:6: Test 9 Failed # not ok 9 - "abc" !~ qr/^abc$/ # TODO Test Know to fail # # Failed (TODO) test '"abc" !~ qr/^abc$/' # # 'abc' # # matches '(?-xism:^abc$)' ENVIRONMENT TEST_TRIVIAL_LOG This environment variable will act as if --log=$ENV{TEST_TRIVIAL_LOG} had been set. AUTHOR 2007-2012, Cory Bennett SOURCE The Source is available at github: https://github.com/coryb/perl-test-trivial SEE ALSO Test::More, Test::Harness, Text::Diff COPYRIGHT and LICENSE Copyright (c) 2008 Yahoo! Inc. All rights reserved. The copyrights to the contents of this file are licensed under the Perl Artistic License (ver. 15 Aug 1997).