Perl Testing
description
Transcript of Perl Testing
Perl Testing
Testphilosophie
Testgeschichte
bis 1956 - Debugging oriented1957–1978 - Demonstration oriented
1979–1982 - Destruction oriented1983–1987 - Evaluation oriented1988–2000 - Prevention oriented
Testwissenschaft
Smoke -Unit - Regression -white-/Grey-/Black– box
Testmafia
V-ModellXP
Testreligion
Am Anfang
Am Anfang
1987: Perl 1.0
starke Testsuite
1987: Perl 1.0
starke Testsuite
Anfänge von TAP
1987: Perl 1.0
starke Testsuite
Anfänge von TAP
Testscripte benutzten print
1987: Perl 1.0
starke Testsuite
Anfänge von TAP
Testscripte benutzten print
TEST fasste zusammen
1987: Perl 1.0
starke Testsuite
Anfänge von TAP
Testscripte benutzten print
TEST => Test::[Harness|Run]
Starte Tests
Starte Testsmake test # nur wenn Makefile da ist
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.pl
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von t
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von tprove -v # mehr Ausgabe
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von tprove --verbose # mehr Ausgabeprove t xt # + alternative Tests
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von tprove --verbose # mehr Ausgabeprove t xt # + alternative Testsprove -r # alle dir (keine subdir)
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von tprove --verbose # mehr Ausgabeprove t xt # + alternative Testsprove -r # alle dir (keine subdir)prove --jobs N # nutze N Kerne
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von tprove --verbose # mehr Ausgabeprove t xt # + alternative Testsprove -r # alle dir (keine subdir)prove --jobs N # nutze N Kerneprove -s # shuffle–zufällige Reih.
Starte Testsmake test # nur wenn Makefile da ist
perl t/datei.plperl datei.pl # BEGIN {chdir '..' if -d '../t'}
prove # oberhalb von tprove --verbose # mehr Ausgabeprove t xt # + alternative Testsprove -r # alle dir (keine subdir)prove --jobs N # nutze N Kerneprove -s # shuffle–zufällige Reih.
Test
Test use Test;
tests =>, todo=>, onfail =>
ok(); skip(); plan(); # Joshua Nathaniel Pritikin
sofort austauschen
# use Test; use Test::Legacy;
Test::Legacy::More # use Test; use Test::Legacy;
Test::Legacy use Test::Legacy; use Test::Legacy::More;
# use Test::More import => [ qw(!ok !skip !plan)];
Warum?
TAP : Test Anything Protocol
Wichtig!
Test::Simple
Test::Simple
use Test::Simple 'no_plan';
ok( $dies eq $das, 'dies gleich das' );
Test::Simple
use Test::Simple 'no_plan';
ok( $dies eq $das, 'dies gleich das' );
Vergleich Meldung (Name)
Test::Simplemake test # nur wenn Makefile da ist
Test::Simple
use Test::Simple 'no_plan';
ok( $dies eq $das, 'dies gleich das' );
ok( $dies == $das, 'numerisch gleich' );
Test::Simple
use Test::Simple tests => 2;
ok( $dies eq $das, 'dies gleich das' );
ok( $dies == $das, 'numerisch gleich' );
Test::Simplepackage Test::Simple;
use 5.006;use strict;
our $VERSION = '0.96';
use Test::Builder::Module;our @ISA = qw(Test::Builder::Module);our @EXPORT = qw(ok);
my $CLASS = __PACKAGE__;
Test::Betweenpackage Test::Between;
use base 'Exporter';our @EXPORT = qw( is_between);
use Test::Builder;my $test = Test::Builder->new();
sub is_between($$$;$) { my ($item, $lower, $upper, $name) = @_; return ( $test->ok(...) || $test->diag(„...“) );}1;
Test::More
wie Test::Simple
mehr Augabe
Test::More use Test::More 'no_plan'; # or skip_all => $reason;
ok, is, isnt, like, unlike, cmp_ok, is_deeply
use_ok, require_ok, can_ok, isa_ok, new_ok
SKIP, TODO, BAIL_OUT, subtest
diag, note, explain, pass, fail, done_testing
Test::More
ok, is, isnt, like, unlike, cmp_ok, is_deeply
Vergleiche: pos, eq, re, cmp, HoH....
Test::More
Module
use_ok, require_ok, can_ok, isa_ok, new_ok
Test::More
Steuern: überspringen, abbrechen, zusammenfassen
SKIP, TODO, BAIL_OUT, subtest
Test::More
Ausgabe: Warnungen(STDERR), Zählung
diag, note, explain, pass, fail, done_testing
Test::More use Test::More 'no_plan'; # or skip_all => $reason;
ok, is, isnt, like, unlike, cmp_ok, is_deeply
use_ok, require_ok, can_ok, isa_ok, new_ok
SKIP, TODO, BAIL_OUT, subtest
diag, note, explain, pass, fail, done_testing
Test::Most
Devel::Cover$ cover -testDeleting database /home/pjcj/g/perl/Shell-Source-0.01/cover_dbPERL_DL_NONLAZY=1 /usr/local/pkg/cover/c1/perl-5.8.7/bin/perl "-MExtUtils::Command::MM" \ "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.tt/bash....ok...All tests successful.Files=6, Tests=24, 17 wallclock secs (16.16 cusr + 1.01 csys = 17.17 CPU)Reading database from /home/pjcj/g/perl/Shell-Source-0.01/cover_db
------------------------------------------ ------ ------ ------ ------ ------ ------ ------File stmt bran cond sub pod time total------------------------------------------ ------ ------ ------ ------ ------ ------ ------blib/lib/Shell/Source.pm 96.6 65.0 66.7 90.9 n/a 100.0 86.1Total 96.6 65.0 66.7 90.9 n/a 100.0 86.1------------------------------------------ ------ ------ ------ ------ ------ ------ ------
Writing HTML output to /home/pjcj/g/perl/Shell-Source0.01/cover_db/coverage.html …done.
Devel::Cover
Test::TestCoverageuse Test::More;
eval { require Test::Pod::Coverage; import Test::Pod::Coverage;};
plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage" if $@;all_pod_coverage_ok();
Test::Pod::Coverageuse Test::More;
eval { require Test::Pod::Coverage; import Test::Pod::Coverage;};
plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage" if $@;all_pod_coverage_ok();
Test::Ifuse Test::More;use Test::If # Checked first $ENV{TEST_AUTHOR}, or skip sub { $ENV{TEST_AUTHOR} }, # Use Test::Pod::Coverage of at least version 1.08 'Test::Pod::Coverage 1.08', # And want Pod::Coverage at least of version 0.18 'Pod::Coverage 0.18',; all_pod_coverage_ok();
Test::Poduse Test::More;
eval { require Test::Pod; import Test::Pod;};
plan skip_all => "Test::Pod missing" if $@;all_pod_files_ok();
Test::Spelling
use Test::Spelling;use Test::More;
all_pod_files_spelling_ok();
Test::Spellinguse Test::Spelling;use Test::More;
add_stopwords();my @files = all_pod_files();pod_files_spelling_ok( @files, "POD file spelling OK" );
pod_file_spelling_ok( $file, "$file spelling OK" );
Test::Pod::Spelling::CommonMistakes
use Test::Spelling;use Test::More;
pod_file_ok( $file, "POD file spelling OK" );all_pod_files_ok();
Test::Strict
Test::Kwaliteeuse Test::More;
eval { require Test::Kwalitee; Test::Kwalitee->import()};
plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@;
Test::Kwalitee● extractable, no_symlinks
● has_readme, have_manifest, have_meta_yml
● have_buildtool, have_changelog, have_tests
● use_strict, proper_libs
● no_pod_errors, have_test_pod, have_test_pod_coverage
Test::Distribution
fast deckungsgleich mit Test::Kwalitee
Test::Module::Used use Test::Module::Used;
my $used = Test::Module::Used->new(); $used->ok;
Werden benutze Bibliotheken gefordert?Werden Geforderte Bibliohteken benutzt?
Test::CPANpm
simuliert einen CPAN install
kein ersatz für vorige Module
Test::Perl::Critic use Test::Perl::Critic; use Test::More tests => 1;
critic_ok($file);
all_critic_ok($dir_1, $dir_2, $dir_N);
all_critic_ok();
Test::Most use Test::More;
use Test::Differences;
use Test::Deep;
use Test::Exception;
use Test::Warn;
mehr ...
Test::Most use Test::More;
use Test::Differences;
use Test::Deep;
use Test::Exception;
use Test::Warn;
mehr ...
Test::Most● die_on_fail bail_on_fail● restore_fail set_failure_handler ● explain # prove -v● show
● all_done
Test::Most use Test::More;
use Test::Differences;
use Test::Deep;
use Test::Exception;
use Test::Warn;
mehr ...
Test::Differences
Test::Differencesuse Test::More;
is_deeply([1,2],[1,2,[3]], '… nicht gleich');
Test::Differencesuse Test::More;
is_deeply([1,2],[1,2,[3]], '… nicht gleich');
# Failed test 'is_deeply'# at t\02-more.t line 12.# Structures begin differing at:# $got->[3] = ARRAY(0xae3704)# $expected->[3] = Does not exist
Test::Differencesuse Test::More tests => 1;use Test::Differences;
eq_or_diff([1,2],[1,2,[3]], '… nicht gleich');
Test::Differencesuse Test::Most tests => 1;
eq_or_diff([1,2],[1,2,[3]], '… nicht gleich');
Test::Differences# Failed test '...nicht gleich' eq_or_diff([1,2],[1,2,[3]]# at t\04-diff.t line 8.# +----+------+----+------------+# | Elt|Got | Elt|Expected |# +----+------+----+------------+# | 0|[ | 0|[ |# | 1| 1, | 1| 1, |# * 2| 2 * 2| 2, *# | | * 3| [ *# | | * 4| 3 *# | | * 5| ] *# | 3|] | 6|] |# +----+------+----+------------+
Test::Differences4 Anzeigestile:
* table_diff; #(the default) * unified_diff; * oldstyle_diff; * context_diff;
Test::Differences# Failed test '...nicht gleich' unified_diff;# at t\04-diff.t line 8. eq_or_diff([1,2],[1,2,[3]]# --- Got # +++ Expected# @@ -1,4 +1,7 @@# [# 1,# - 2# + 2,# + [# + 3# + ]
Test::Differences# Failed test '...nicht gleich' oldstyle_diff;# at t\04-diff.t line 8. eq_or_diff([1,2],[1,2,[3]]# 3c3,6 # < 2# ---# > 2,# > [# > 3# > ]
Test::Differences# *** Got context_diff;# --- Expected eq_or_diff([1,2],[1,2,[3]]# ***************# *** 1,4 ****# [# 1,# ! 2# ]# --- 1,7 ----# [# 1,# ! 2,# ! [# ! 3# ! ]# ]
Test::Differencesuse Test::More; # oder Testuse Test::Differences; # use Text::Diff;
eq_or_diff($gegeben, $gesucht, $meldung);# autoselect:eq_or_diff_data($gegeben, $gesucht, $meldung);eq_or_diff_text($gegeben, $gesucht, $meldung);
Test::Moreuse Test::More;
is_deeply([1,2],[1,2,[3]], '… nicht gleich');
Test::Moreuse Test::More;
is_deeply([1,2],[1,2,[3]], '… nicht gleich');
eq_array();eq_hash();eq_set();
Test::Moreuse Test::More;
is_deeply([1,2],[1,2,[3]], '… nicht gleich');
eq_array();eq_hash();eq_set();
Test::Deepuse Test::More 'no_plan';use Test::Deep;
cmp_deeply($got, $expected, $name); # is_deeply
not ok 1 – test name# Failed test 'test name'# at t\03-deep.t line 7.# Compared $data->[3][2][0]# got : '2'# expect : '1'
Test::Deepuse Test::Most 'no_plan';
cmp_deeply($got, $expected, $name); # is_deeplyeq_deeply($got, $expected); # no testcmp_bag(\@got, \@bag, $name); # Reihenfolge egal cmp_set(\@got, \@set, $name); # Mehrfache mögl.cmp_methods(\@got, \@methods, $name);
Test::Deepuse Test::Most 'no_plan';
cmp_deeply($got, $expected, $name); # is_deeplyeq_deeply($got, $expected); # no testcmp_bag(\@got, \@bag, $name); # bag wie in P6 cmp_set(\@got, \@set, $name); # eq_setcmp_methods(\@got, \@methods, $name);
Aliaseuse Test::Deep;
cmp_bag(\@got, \@bag, $name);cmp_deeply(\@got, bag(@exp), $name);
cmp_set(\@got, \@set, $name);cmp_deeply(\@got, set(@exp), $name);
cmp_methods($obj, \@exp, $name);cmp_deeply($obj, methods(%exp), $name);
kombinierbare Befehle
cmp_deeply(\@got, bag(@exp), $name);
cmp_deeply(\@got, set(@exp), $name);
cmp_deeply($obj, methods(%exp), $name);
kombinierbare Befehle
bag(@exp)
set(@exp)
methods(%exp)
kombinierbare Befehleignore()any(@exp) / all(@exp)bag(@exp)set(@exp)super|sub . hash|bag|set . of ()array_eachstr / num / bool / codere(@exp)shallow($ref)methods(@exp)listmethods(@exp)noclass(@exp)useclass(@exp)isa(@exp)
Test::Deep::NoTest
use Test::Deep::NoTest;
Test::Exception
use Test::Exception;
throws_ok( {...}, $ausnahmeklasse, $name);throws_ok( {...}, $regex, $name);lives_ok( {…}, $name);dies_ok({...}, $name);
Test::Warn# Welche Warnungen wurden ausgegeben?
use Test::Warn;
warning_is( {...} $warnung, $name);warnings_are( {...} @warnungen, $name);
warning_like();
Test::Most use Test::More;
use Test::Differences;
use Test::Deep;
use Test::Exception;
use Test::Warn;
mehr … fertig
Bundle::Test Test Test::Simple Test::More Test::Harness Test::MockObject Test::Pod Test::Builder Test::Warn Test::Inline Test::Strict Test::Distribution Test::Perl::Critic Test::Kwalitee Pod::Spell Test::Spelling Devel::Cover ...
Test::NoWarnings
use Test::NoWarnings;
Test::NoWarnings
use Test::NoWarnings;
# $plan += 1
>ok $plan - no warnings
Test::Script
use Test::Script;
script_compiles();
script_runs();
Test::Cmduse Test::Cmd;
my $cmd = Test::Cmd->new ( prog => 'prog.pl', interpreter => 'script_interpreter', string => 'identifier_string', workdir => '', subdir => 'dir', match_sub => $code_ref, verbose => 1, ...);
$cmd->write( # Datei schreiben$cmd->run( # $? == 0
Test::Expect expect_run ( command => "cpan", prompt => 'install Kephra', quit => 'q', );expect_like(qr/install UNINST=1 -- OK/, "gut");
expect_handle();
Test::Timeruse Test::Timer;
time_ok, time_atmost time_betweentime_atleast
time_between
Test::Benchmark
use Test::Timer;
is_faster($times, $sub1, $sub2, $name);is_n_times_faster($factor, $t, $sub1, $sub2, $name);is_fastest();
Test::ManyParamsuse Test::ManyParams;
all_ok { tannu(shift) }, @para, $nachricht;all_ok { tuwas(@_) }, [ @a, @b], $nachricht;
qw(all any) X~ qw(ok is isnt) most_ok{ sub(@_) }, [ @a, @b] => $nr, $nachricht;
Randomuse File::Random;
my $random_gif = random_file(-dir => $dir,
-check => qr/\.gif$/, -recursive => 1);
use Data::Random;
Win32::GuiTest
SendKeys();
MouseMoveAbsPix(100, 200);SendMouse();
Win32::Screenshot
Test::Data
use Test::Data qw(Scalar Array Hash Function);
Test::Data::Scalarblessed_okdefined_okundef_ok
greater_thanless_thanlength_ok
maxlength_okminlength_oknumber_ok
Test::LongStringuse Test::LongString max => 100; # 50 ist default
is_stringis_string_nowscontains_stringlacks_stringlike_stringunlike_string
Test::LongStringuse Test::LongString max => 100; # 50 ist default
is_string # Failed test (html-test.t at line 12) # got: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Trans"... # length: 58930 # doesn't match '(?-xism:(perl|cpan)\.org)'
Test::LongStringuse Test::LongString max => 100; # 50 ist default
like_string# Failed test (soliloquy.t at line 15)# got: "To be, or not to be: that is the question:\x{0a} Wh" ...# length: 1490# doesn't match '(?-xism:Romeo|Juliet|Mercutio|Tybalt)'
Test::Outputstdout_is
stderr_isnt
output_iscombined_is
stdout_likestdout_unlike
Test::Carp
does_carp(\&function);
does_carp_that_matches(\&function, qr/whoopsy/);
Test::Log4perl
Test::Log::Dispatch
Test Techniken
analyze this
Mocking
Mocking
Test::MockModule
Test::MockObject
Test::MockObject::Extends
DBD::Mock
Test::MockModuleuse Module::Name;use Test::MockModule;
{ my $module = new Test::MockModule('Module::Name'); $module->mock('subroutine', sub { ... }); Module::Name::subroutine(@args); # mocked} Module::Name::subroutine(@args); # unverändert
Test::MockObject
use
Test::MockObject::Extends
use
Devel::Hide
use Devel::Hide qw[Test::Most];
use Tests::Most; # error
Test::Without::Module
use Test::Without::Module qw[Test::Most];
use Tests::Most; # error
Test::Without
run { ... } without 'Net::Server';
run { ... } with 'Net::Server';
Organisation
Test::Standaloneuse Test::Standalone;
=begin test .... .... =end test
script.pl --test
Test::Inline
=begin testing label ... normaler Testcode .... .... =end testing
Test::Inline
=begin testing label .... .... =end testing
inline2test.pl
Test::Plan
plan tests => 3, need need_module('Kephra'), need_min_module_version(Wx => 0.9), need_min_perl_version(5.6);
Test::Blockuse Test::More 'no_plan';use Test::Block qw($Plan);
{local $Plan = 2;
}
Test::Groupuse Test::More no_plan;use Test::Group;
test "tausend tests" => sub {ok(1,'—') for 1..1000;
};
----------------------------------------------------------
ok 1 - tausend tests1..1
Unit-Testing
Test::Unit # starte und räume aufsub set_up { ... }sub tear_down { ... }
# eigentliche testssub test_... { ... {}
# starte alle testscreate_suite();run_suite();
Test::Unit
use Test::Unit; # 2001
Test::Unit::Lite
use Test::Unit::Lite; # 2009
Test::SimpleUnit
Test::Extreme
use TestConfigs;use TestAPI;use TestOutput;
run_tests 'TestConfigs', 'TestAPI', 'TestOutput';
Test::Extreme
use Test::Extreme;
sub foo { return 23 };sub test_foo { assert_equals foo, 23 }
Test::Classpackage Meine::Test::Klasse;use base qw(Test::Class);
sub eats : Test(3) {
Meine::Test::Klasse->runtests
Test::Classpackage Meine::Test::Klasse;
sub eats : Test(3) {
package main;Meine::Test::Klasse->runtests;
Test::Class
BEGIN { chdir 't' if -d 't'; require Meine::Test::Klasse;}
Meine::Test::Klasse->runtests;
# Meine/Test/Klasse.pm
Test::Class
sub tischlein_deck_dich : Test (startup) {sub knueppel_aus_dem_sack : Test (shutdown) {
sub neues_tischtuch : Test (setup => 2 ) {sub abraeumkommando : Test (teardown) {
Test::Class::Sugar
use Test::Class::Sugar;
Test::Able
Test::Able
Test::Able package MyTest;
use Test::Able; use Test::More;
startup some_startup => sub { ... }; setup some_setup => sub { ... }; test plan => 1, foo => sub { ok( 1 ); }; test bar => sub { my @runtime_list = 1 .. 42; $_[ 0 ]->meta->current_method->plan( scalar @runtime_list ); ok( 1 ) for @runtime_list; }; teardown some_teardown => sub { ... }; shutdown some_shutdown => sub { ... };
MyTest->run_tests;
Test::Able use Test::Able::Helpers qw( shuffle_methods );
$t->meta->test_methods( [ grep { $_->name !~ /bar/; }
@{ $t->meta->test_methods } ] );
for ( 1 .. 10 ) { $t->shuffle_methods; $t->run_tests;}
Gutes Buch
Linkshttp://www.slideshare.net/lichtkind
search.cpan.org/dist/Test-Simple/lib/Test/Tutorial.pod
.../dist/Test-Able/lib/Test/Able/Cookbook.pm
http://qa.perl.org/testing/
http://www.cpantesters.org/
http://testanything.org
http://docs.racket-lang.org/rackunit
Glückliches Ende