SlideShare une entreprise Scribd logo
1  sur  45
Télécharger pour lire hors ligne
  OO tests for OO code
       Nice performance boost
       Easy-to-organize test suites




http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  Plenty!




http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
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
use Test::Class::Most!
         parent => 'My::Test::Class’;!

     sub some_test : Tests { ... }!




http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
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
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
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
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
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
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
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
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
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
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
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
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
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
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
prove -lv -It/lib !
       t/lib/TestsFor/Person.pm !

     # INIT { Test::Class->runtests }!




http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
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
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
$ 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
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
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
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
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
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
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
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
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
  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
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
     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
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
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
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
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
# 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
# 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
# Do This!!
     use Test::Class::Load ‘t/lib’;!




http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  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
     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
     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
     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

Contenu connexe

Tendances

Nedap Rails Workshop
Nedap Rails WorkshopNedap Rails Workshop
Nedap Rails Workshop
Andre Foeken
 
Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2
nottings
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 

Tendances (20)

Nedap Rails Workshop
Nedap Rails WorkshopNedap Rails Workshop
Nedap Rails Workshop
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
Solr and Lucene at Etsy - By Gregg Donovan
Solr and Lucene at Etsy - By Gregg DonovanSolr and Lucene at Etsy - By Gregg Donovan
Solr and Lucene at Etsy - By Gregg Donovan
 
Solr & Lucene at Etsy
Solr & Lucene at EtsySolr & Lucene at Etsy
Solr & Lucene at Etsy
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
Solr & Lucene @ Etsy by Gregg Donovan
Solr & Lucene @ Etsy by Gregg DonovanSolr & Lucene @ Etsy by Gregg Donovan
Solr & Lucene @ Etsy by Gregg Donovan
 
Getting Testy With Perl6
Getting Testy With Perl6Getting Testy With Perl6
Getting Testy With Perl6
 
Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2
 
Testing in Laravel
Testing in LaravelTesting in Laravel
Testing in Laravel
 
Javascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyJavascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the Ugly
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
 
Top 10 php classic traps confoo
Top 10 php classic traps confooTop 10 php classic traps confoo
Top 10 php classic traps confoo
 
Living with garbage
Living with garbageLiving with garbage
Living with garbage
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System Design
 
Solr Anti-Patterns: Presented by Rafał Kuć, Sematext
Solr Anti-Patterns: Presented by Rafał Kuć, SematextSolr Anti-Patterns: Presented by Rafał Kuć, Sematext
Solr Anti-Patterns: Presented by Rafał Kuć, Sematext
 
Simulator customizing & testing for Xcode 9
Simulator customizing & testing for Xcode 9Simulator customizing & testing for Xcode 9
Simulator customizing & testing for Xcode 9
 
Porting Java To Scala
Porting Java To Scala Porting Java To Scala
Porting Java To Scala
 
Testing stateful, concurrent, and async systems using test.check
Testing stateful, concurrent, and async systems using test.checkTesting stateful, concurrent, and async systems using test.check
Testing stateful, concurrent, and async systems using test.check
 
Evolving Tests
Evolving TestsEvolving Tests
Evolving Tests
 

En vedette

Reliable tests with selenium web driver
Reliable tests with selenium web driverReliable tests with selenium web driver
Reliable tests with selenium web driver
PawelPabich
 
JavaScript Testing VIA Selenium
JavaScript Testing VIA SeleniumJavaScript Testing VIA Selenium
JavaScript Testing VIA Selenium
Adam Christian
 
Testing at Yammer with FooUnit, Jellyfish, and Sauce Labs
Testing at Yammer with FooUnit, Jellyfish, and Sauce LabsTesting at Yammer with FooUnit, Jellyfish, and Sauce Labs
Testing at Yammer with FooUnit, Jellyfish, and Sauce Labs
Sauce Labs
 
Mobile Test Automation at eBay
Mobile Test Automation at eBayMobile Test Automation at eBay
Mobile Test Automation at eBay
Dominik Dary
 

En vedette (14)

(Seleniumcamp) Selenium RC for QA Engineer
(Seleniumcamp) Selenium RC for QA Engineer(Seleniumcamp) Selenium RC for QA Engineer
(Seleniumcamp) Selenium RC for QA Engineer
 
Selenium for Designers
Selenium for DesignersSelenium for Designers
Selenium for Designers
 
Selenium Page Objects101
Selenium Page Objects101Selenium Page Objects101
Selenium Page Objects101
 
Reliable tests with selenium web driver
Reliable tests with selenium web driverReliable tests with selenium web driver
Reliable tests with selenium web driver
 
Funcargs & other fun with pytest
Funcargs & other fun with pytestFuncargs & other fun with pytest
Funcargs & other fun with pytest
 
Large scale automation with jenkins
Large scale automation with jenkinsLarge scale automation with jenkins
Large scale automation with jenkins
 
JavaScript Testing VIA Selenium
JavaScript Testing VIA SeleniumJavaScript Testing VIA Selenium
JavaScript Testing VIA Selenium
 
Testing at Yammer with FooUnit, Jellyfish, and Sauce Labs
Testing at Yammer with FooUnit, Jellyfish, and Sauce LabsTesting at Yammer with FooUnit, Jellyfish, and Sauce Labs
Testing at Yammer with FooUnit, Jellyfish, and Sauce Labs
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
 
Continuous Integration, the minimum viable product
Continuous Integration, the minimum viable productContinuous Integration, the minimum viable product
Continuous Integration, the minimum viable product
 
Selenium Users Anonymous
Selenium Users AnonymousSelenium Users Anonymous
Selenium Users Anonymous
 
Mobile Test Automation at eBay
Mobile Test Automation at eBayMobile Test Automation at eBay
Mobile Test Automation at eBay
 
Continuous Deployment - Lean LA
Continuous Deployment - Lean LAContinuous Deployment - Lean LA
Continuous Deployment - Lean LA
 
Creating Maintainable Automated Acceptance Tests
Creating Maintainable Automated Acceptance TestsCreating Maintainable Automated Acceptance Tests
Creating Maintainable Automated Acceptance Tests
 

Similaire à A Whirlwind Tour of Test::Class

Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in Ruby
ConFoo
 
Intro To Moose
Intro To MooseIntro To Moose
Intro To Moose
cPanel
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 

Similaire à A Whirlwind Tour of Test::Class (20)

The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.
 
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'
 
Testing With Test::Class
Testing With Test::ClassTesting With Test::Class
Testing With Test::Class
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in Ruby
 
Metaprogramming
MetaprogrammingMetaprogramming
Metaprogramming
 
Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
Intro To Moose
Intro To MooseIntro To Moose
Intro To Moose
 
Puppetizing Multitier Architecture - PuppetConf 2014
Puppetizing Multitier Architecture - PuppetConf 2014Puppetizing Multitier Architecture - PuppetConf 2014
Puppetizing Multitier Architecture - PuppetConf 2014
 
Introduction To Moose
Introduction To MooseIntroduction To Moose
Introduction To Moose
 
How would you describe Swift in three words?
How would you describe Swift in three words?How would you describe Swift in three words?
How would you describe Swift in three words?
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares DornellesA linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
 
Ruby Programming Language
Ruby Programming LanguageRuby Programming Language
Ruby Programming Language
 
Testing Code and Assuring Quality
Testing Code and Assuring QualityTesting Code and Assuring Quality
Testing Code and Assuring Quality
 
Advanced modulinos trial
Advanced modulinos trialAdvanced modulinos trial
Advanced modulinos trial
 

Plus de Curtis Poe

Plus de Curtis Poe (19)

How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
life-off-earth.pptx
life-off-earth.pptxlife-off-earth.pptx
life-off-earth.pptx
 
Corinna-2023.pptx
Corinna-2023.pptxCorinna-2023.pptx
Corinna-2023.pptx
 
Corinna Status 2022.pptx
Corinna Status 2022.pptxCorinna Status 2022.pptx
Corinna Status 2022.pptx
 
Rummaging in the clOOset
Rummaging in the clOOsetRummaging in the clOOset
Rummaging in the clOOset
 
Rescuing a-legacy-codebase
Rescuing a-legacy-codebaseRescuing a-legacy-codebase
Rescuing a-legacy-codebase
 
Perl 6 For Mere Mortals
Perl 6 For Mere MortalsPerl 6 For Mere Mortals
Perl 6 For Mere Mortals
 
Disappearing Managers, YAPC::EU 2014, Bulgaria, Keynote
Disappearing Managers, YAPC::EU 2014, Bulgaria, KeynoteDisappearing Managers, YAPC::EU 2014, Bulgaria, Keynote
Disappearing Managers, YAPC::EU 2014, Bulgaria, Keynote
 
How to Fake a Database Design
How to Fake a Database DesignHow to Fake a Database Design
How to Fake a Database Design
 
Are Managers An Endangered Species?
Are Managers An Endangered Species?Are Managers An Endangered Species?
Are Managers An Endangered Species?
 
The Lies We Tell About Software Testing
The Lies We Tell About Software TestingThe Lies We Tell About Software Testing
The Lies We Tell About Software Testing
 
A/B Testing - What your mother didn't tell you
A/B Testing - What your mother didn't tell youA/B Testing - What your mother didn't tell you
A/B Testing - What your mother didn't tell you
 
Test::Class::Moose
Test::Class::MooseTest::Class::Moose
Test::Class::Moose
 
Agile Companies Go P.O.P.
Agile Companies Go P.O.P.Agile Companies Go P.O.P.
Agile Companies Go P.O.P.
 
Econ101
Econ101Econ101
Econ101
 
Logic Progamming in Perl
Logic Progamming in PerlLogic Progamming in Perl
Logic Progamming in Perl
 
Inheritance Versus Roles - The In-Depth Version
Inheritance Versus Roles - The In-Depth VersionInheritance Versus Roles - The In-Depth Version
Inheritance Versus Roles - The In-Depth Version
 
Inheritance Versus Roles
Inheritance Versus RolesInheritance Versus Roles
Inheritance Versus Roles
 
Turbo Charged Test Suites
Turbo Charged Test SuitesTurbo Charged Test Suites
Turbo Charged Test Suites
 

Dernier

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 

A Whirlwind Tour of Test::Class

  • 1.
  • 2.   OO tests for OO code   Nice performance boost   Easy-to-organize test suites http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  • 4. 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
  • 5. use Test::Class::Most! parent => 'My::Test::Class’;! sub some_test : Tests { ... }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  • 6. 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
  • 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. 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
  • 11. 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
  • 12. 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
  • 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. 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
  • 20. prove -lv -It/lib ! t/lib/TestsFor/Person.pm ! # INIT { Test::Class->runtests }! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  • 21. 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
  • 22. 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
  • 23. $ 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
  • 24. 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
  • 25. 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
  • 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. 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
  • 31. 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
  • 32.   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
  • 33. 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
  • 34.   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
  • 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 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
  • 37. 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
  • 38. 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
  • 39. # 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
  • 40. # 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
  • 41. # Do This!! use Test::Class::Load ‘t/lib’;! http://www.slideshare.net/Ovid/a-whirlwind-tour-of-testclass
  • 42.   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
  • 43.   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
  • 44.   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
  • 45.   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