Publicité
Publicité

Contenu connexe

Publicité
Publicité

A Whirlwind Tour of Test::Class

  1.   OO tests for OO code   Nice performance boost   Easy-to-organize test suites http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  2.   Plenty! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  3. use strict;! use warnings;! use Test::Exception 0.88;! use Test::Differences 0.500;! use Test::Deep 0.106;! use Test::Warn 0.11;! use Test::More 0.88;! use parent 'My::Test::Class’;! sub some_test : Tests { ... }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  4. use Test::Class::Most! parent => 'My::Test::Class’;! sub some_test : Tests { ... }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  5. lib/! | Person/! | `-- Employee.pm! `-- Person.pm! t/! | lib/! | | My/! | | | Test/! | | | `-- Class.pm! | | TestsFor/! | | | Person/! | | | `-- Employee.pm! | | `-- Person.pm! `-- test_class_tests.t! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  6. package My::Test::Class;! use Test::Class::Most ! attributes => ['class'];! INIT { Test::Class->runtests }! sub startup : Tests(startup) {…}! sub setup : Tests(setup) {}! sub teardown : Tests(teardown) {}! sub shutdown : Tests(shutdown) {}! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  7. package My::Test::Class;! use Test::Class::Most ! attributes => ['class'];! INIT { Test::Class->runtests }! sub startup : Tests(startup) {…}! sub setup : Tests(setup) {}! sub teardown : Tests(teardown) {}! sub shutdown : Tests(shutdown) {}! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  8. package My::Test::Class;! use Test::Class::Most ! attributes => ['class'];! INIT { Test::Class->runtests }! sub startup : Tests(startup) {…}! sub setup : Tests(setup) {}! sub teardown : Tests(teardown) {}! sub shutdown : Tests(shutdown) {}! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  9. package My::Test::Class;! use Test::Class::Most ! attributes => ['class'];! INIT { Test::Class->runtests }! sub startup : Tests(startup) {…}! sub setup : Tests(setup) {}! sub teardown : Tests(teardown) {}! sub shutdown : Tests(shutdown) {}! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  10. sub startup : Tests(startup) {! my $test = shift;! return if $test->class;! my $class = ref $test;! $class =~ s/^TestsFor:://;! eval "use $class";! die $@ if $@;! $test->class($class);! }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  11. package Person; use Moose;! has ‘first_name’ => ( is => 'ro', isa => 'Str' );! has ‘last_name’ => ( is => 'ro', isa => 'Str' );! sub full_name {! my $self = shift;! return $self->first_name . ' ' ! . $self->last_name;! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  12. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  13. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  14. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  15. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  16. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  17. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  18. package TestsFor::Person;! use Test::Class::Most parent =>'My::Test::Class';! sub constructor : Tests(3) {! my $test = shift;! my $class = $test->class;! can_ok $class, 'new'; ok my $person = $class->new, ! '... and the constructor should succeed';! isa_ok $person, $class, ! '... and the object it returns';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  19. prove -lv -It/lib ! t/lib/TestsFor/Person.pm ! # INIT { Test::Class->runtests }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  20. t/TestsFor/Person.pm .. # ! # TestsFor::Person->constructor! 1..3! ok 1 - Person->can('new')! ok 2 - ... and the constructor should succeed! ok 3 - ... and the object it returns isa Person! ok! All tests successful.! Files=1, Tests=3, 0 wallclock secs! Result: PASS! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  21. package TestsFor::Person;! Use Test::Class::Most parent => ‘My::Test::Class’;! sub constructor : Tests(3) { … }! sub full_name : Tests(4) { my $test = shift;! my $person = $test->class->new(! first_name => 'Adrian',! last_name => 'Howard',! );! is $person->first_name, 'Adrian', 'first_name correct';! is $person->last_name, 'Howard', 'last_name correct';! can_ok $person, 'full_name';! is $person->full_name, 'Adrian Howard',! '... and it should return the correct fullname';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  22. $ prove –vl -It/lib t/TestsFor/Person.pm! t/TestsFor/Person.pm .. # ! # TestsFor::Person->constructor! 1..7! ok 1 - Person->can('new’)! ok 2 - ... and the constructor should succeed! ok 3 - ... and the object it returns isa Person! # ! # TestsFor::Person->full_name! ok 4 - first_name correct! ok 5 - last_name correct! ok 6 - Person->can('full_name')! ok 7 - ... and it should return the correct fullname! ok! All tests successful.! Files=1, Tests=7, 0 wallclock secs! Result: PASS! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  23. package Person::Employee; use Moose;! extends 'Person';! has ‘employee_number’ => ( ! is => ‘ro’, ! isa => ‘Int’,! );! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  24. package TestsFor::Person::Employee;! use Test::Class::Most parent => 'TestsFor::Person';! sub employee_number : Tests(2) { my $test = shift;! my $employee = $test->class->new(! first_name => 'John',! last_name => 'Public',! employee_number => 17,! );! can_ok $employee, 'employee_number’;! is $employee->employee_number, 17, ! '... the employee number is correct';! }! 1;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  25. t/TestsFor/Person/Employee.pm .. # ! # ! # TestsFor::Person::Employee->constructor! # TestsFor::Person->constructor! ok 10 - Person->can('new')! 1..16! ok 11 - ... and the constructor should ok 1 - Person::Employee->can('new')! succeed! ok 2 - ... and the constructor should succeed! ok 12 - ... and the object it returns isa ok 3 - ... and the object it returns isa Person! Person::Employee! # ! # ! # TestsFor::Person->full_name! # TestsFor::Person::Employee->employee_number! ok 13 - first_name correct! ok 4 - Person::Employee- ok 14 - last_name correct! >can('employee_number')! ok 15 - Person->can('full_name')! ok 5 - ... the employee number is correct! ok 16 - ... and it should return the correct # ! fullname! # TestsFor::Person::Employee->full_name! ok! ok 6 - first_name correct! All tests successful.! ok 7 - last_name correct! Files=1, Tests=16, 0 wallclock secs! ok 8 - Person::Employee->can('full_name')! Result: PASS! ok 9 - ... and it should return the correct fullname! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  26. t/TestsFor/Person/Employee.pm .. # ! # ! # TestsFor::Person::Employee->constructor! # TestsFor::Person->constructor! ok 10 - Person->can('new')! 1..16! ok 11 - ... and the constructor should ok 1 - Person::Employee->can('new')! succeed! ok 2 - ... and the constructor should succeed! ok 12 - ... and the object it returns isa ok 3 - ... and the object it returns isa Person! Person::Employee! # ! # ! # TestsFor::Person->full_name! # TestsFor::Person::Employee->employee_number! ok 13 - first_name correct! ok 4 - Person::Employee- ok 14 - last_name correct! >can('employee_number')! ok 15 - Person->can('full_name')! ok 5 - ... the employee number is correct! ok 16 - ... and it should return the correct # ! fullname! # TestsFor::Person::Employee->full_name! ok! ok 6 - first_name correct! All tests successful.! ok 7 - last_name correct! Files=1, Tests=16, 0 wallclock secs! ok 8 - Person::Employee->can('full_name')! Result: PASS! ok 9 - ... and it should return the correct fullname! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  27. t/TestsFor/Person/Employee.pm .. # ! # ! # TestsFor::Person::Employee->constructor! # TestsFor::Person->constructor! ok 10 - Person->can('new')! 1..16! ok 11 - ... and the constructor should ok 1 - Person::Employee->can('new')! succeed! ok 2 - ... and the constructor should succeed! ok 12 - ... and the object it returns isa ok 3 - ... and the object it returns isa Person! Person::Employee! # ! # ! # TestsFor::Person->full_name! # TestsFor::Person::Employee->employee_number! ok 13 - first_name correct! ok 4 - Person::Employee- ok 14 - last_name correct! >can('employee_number')! ok 15 - Person->can('full_name')! ok 5 - ... the employee number is correct! ok 16 - ... and it should return the correct # ! fullname! # TestsFor::Person::Employee->full_name! ok! ok 6 - first_name correct! All tests successful.! ok 7 - last_name correct! Files=1, Tests=16, 0 wallclock secs! ok 8 - Person::Employee->can('full_name')! Result: PASS! ok 9 - ... and it should return the correct fullname! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  28. t/TestsFor/Person/Employee.pm .. # ! # ! # TestsFor::Person::Employee->constructor! # TestsFor::Person->constructor! ok 10 - Person->can('new')! 1..16! ok 11 - ... and the constructor should ok 1 - Person::Employee->can('new')! succeed! ok 2 - ... and the constructor should succeed! ok 12 - ... and the object it returns isa ok 3 - ... and the object it returns isa Person! Person::Employee! # ! # ! # TestsFor::Person->full_name! # TestsFor::Person::Employee->employee_number! ok 13 - first_name correct! ok 4 - Person::Employee- ok 14 - last_name correct! >can('employee_number')! ok 15 - Person->can('full_name')! ok 5 - ... the employee number is correct! ok 16 - ... and it should return the correct # ! fullname! # TestsFor::Person::Employee->full_name! ok! ok 6 - first_name correct! All tests successful.! ok 7 - last_name correct! Files=1, Tests=16, 0 wallclock secs! ok 8 - Person::Employee->can('full_name')! Result: PASS! ok 9 - ... and it should return the correct fullname! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  29. t/TestsFor/Person/Employee.pm .. # ! # ! # TestsFor::Person::Employee->constructor! # TestsFor::Person->constructor! ok 10 - Person->can('new')! 1..16! ok 11 - ... and the constructor should ok 1 - Person::Employee->can('new')! succeed! ok 2 - ... and the constructor should succeed! ok 12 - ... and the object it returns isa ok 3 - ... and the object it returns isa Person! Person::Employee! # ! # ! # TestsFor::Person->full_name! # TestsFor::Person::Employee->employee_number! ok 13 - first_name correct! ok 4 - Person::Employee- ok 14 - last_name correct! >can('employee_number')! ok 15 - Person->can('full_name')! ok 5 - ... the employee number is correct! ok 16 - ... and it should return the correct # ! fullname! # TestsFor::Person::Employee->full_name! ok! ok 6 - first_name correct! All tests successful.! ok 7 - last_name correct! Files=1, Tests=16, 0 wallclock secs! ok 8 - Person::Employee->can('full_name')! Result: PASS! ok 9 - ... and it should return the correct fullname! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  30. sub startup : Tests(startup) {! my $test = shift;! return if $test->class;! my $class = ref $test;! $class =~ s/^TestsFor:://;! eval "use $class";! die $@ if $@;! $test->class($class);! }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  31.   TestsFor::Person::Employee inherits TestsFor::Person’s tests   We don’t hard-code the class name   Inherited test methods rock! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  32. Attribute Name Phase Tests(startup)! When the test class starts Tests(setup)! Before each test method Tests(teardown)! After each test method Tests(shutdown)! When the test class finishes http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  33.   Connect to a database (often in startup)   Set up fixtures/transactions (setup)   Clean fixtures/rollbacks (teardown)   Disconnect from database (shutdown)   (They’re a better place for object construction) http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  34. package TestsFor::Customer;! package TestsFor::Person::Employee;! use Test::Class::Most! use Test::Class::Most! parent => ‘My::Test::Class’,! parent => ‘TestsFor::Customer’,! attributes => [‘dbh’];! attributes => [‘employee’];! sub aaa_connect_to_db : Tests(setup) {! sub bbb_employee : Tests(setup) {! my $test = shift;! my $test = shift;! my $dbh = DBI->connect(…);! my $employee = $test->dbh->…;! # or $test->{dbh} = $dbh;! $test->employee($employee);! $test->dbh($dbh);! }! }! sub kill_employee : Tests {! sub some_test : Tests {! my $test = shift;! my $test = shift;! my $employee = $test->employee;! my $dbh = $test->dbh;! can_ok( $employee, ‘suffocate’ );! …! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  35. package TestsFor::Customer;! package TestsFor::Person::Employee;! use Test::Class::Most! use Test::Class::Most! parent => ‘My::Test::Class’,! parent => ‘TestsFor::Customer’,! attributes => [‘dbh’];! attributes => [‘employee’];! sub aaa_connect_to_db : Tests(setup) {! sub bbb_employee : Tests(setup) {! my $test = shift;! my $test = shift;! my $dbh = DBI->connect(…);! my $employee = $test->dbh->…;! # or $test->{dbh} = $dbh;! $test->employee($employee);! $test->dbh($dbh);! }! }! sub kill_employee : Tests {! sub some_test : Tests {! my $test = shift;! my $test = shift;! my $employee = $test->employee;! my $dbh = $test->dbh;! can_ok( $employee, ‘suffocate’ );! …! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  36. package TestsFor::Customer;! package TestsFor::Person::Employee;! use Test::Class::Most! use Test::Class::Most! parent => ‘My::Test::Class’,! parent => ‘TestsFor::Customer’,! attributes => [‘dbh’];! attributes => [‘employee’];! sub setup : Tests(setup) {! sub setup : Tests(setup) {! my $test = shift;! my $test = shift;! my $dbh = DBI->connect(…);! $test->SUPER::setup;! # or $test->{dbh} = $dbh;! my $employee = $test->dbh->…;! $test->dbh($dbh);! $test->employee($employee);! }! }! sub some_test : Tests {! sub kill_employee : Tests {! my $test = shift;! my $test = shift;! my $dbh = $test->dbh;! my $employee = $test->employee;! …! can_ok( $employee, ‘suffocate’ );! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  37. Before Tests After Tests sub startup:Test(startup) {! sub teardown:Test(teardown){! my $test = shift;! my $test = shift;! $test->SUPER::startup;! # finish your teardown! # finish your startup! $test->SUPER::teardown;! }! }! sub setup : Test(setup) {! sub shutdown:Test(shutdown){! my $test = shift;! my $test = shift;! $test->SUPER::setup;! # finish your shutdown! # finish your setup! $test->SUPER::shutdown;! }! }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  38. # t/test_class_tests.t! # Don’t Do This!! use lib ‘t/lib’;! use TestsFor::Person;! use TestsFor::Person::Employee;! Test::Class->runtests;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  39. # Don’t Do This because you’ll forget one!! use lib ‘t/lib’;! use TestsFor::Person;! use TestsFor::Person::Employee;! use TestsFor::Database;! use TestsFor::PurchaseOrder;! use TestsFor::Alibi;! use TestsFor::Embezzlement;! use TestsFor::PaddingMySlides;! Test::Class->runtests;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  40. # Do This!! use Test::Class::Load ‘t/lib’;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  41.   Finds your test classes for you   My example relies on INIT { Test::Class->runtests } in My::Test::Class.   Run the test suite: prove -l t/test_class_tests.t!   Or a single test class: prove -lv -It/lib t/TestsFor/Person.pm http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  42.   Name test classes after their classes (if possible)   Name test methods after their methods (if possible)   … you can’t name a method new()!   Create your own base test class   … with stub test control methods   Name test control methods after their attribute   Don’t put tests in your test control methods   Do not hardcode the name of the class to test! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  43.   Part 1: Getting started with Test::Class   Part 2: Inheriting Test::Class tests   Part 3: Making your testing life easier   Part 4: Using test control methods   Part 5: Test::Class Tricks http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  44.   Beginning Perl, Wrox Press   Introduction to Perl   CPAN   Modules   Objects (Moose!)   Testing   PSGI+Plack   DBIx::Class   Catalyst   And more! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass

Notes de l'éditeur

  1. Single versus multiple processesTests that don’t map to classesDetailed testing strategiesWhy some of this presentation works
Publicité