The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

DBIx::Class::Migration::Tutorial::Testing - Test Your Database

GOAL

Let's take an interlude from creating migrations and turn to writing test cases for your database.

It would help if you are familiar with Test::Most and Test::DBIx::Class and with general Perl testing procedures. You could also benefit from reviewing our fixtures hook class Test::DBIx::Class::FixtureCommand::Population.

Test your 1-2 Upgrade

When doing upgrades it would be great to have some automated tests in place so that whoever does the upgrade can immediately verify that all is well. Let's add a test case now!

    touch t/upgrade-1to2.t

Then open the new files in the editor of choice and enter the following code:

    #!/usr/bin/env perl

    use Test::Most;
    use Test::DBIx::Class
      -schema_class=>'MusicBase::Schema',
      -fixture_class => '::Population',
      qw(Artist Country);

    plan skip_all => 'not correct schema version'
      if Schema->schema_version != 2;

    fixtures_ok ['all_tables'];

    is Country->count, 3, 'Correct Number of Countries';
    ok Artist->first->has_country, 'Artist has a country';

    done_testing;

This creates a basic test case that only runs for version 2 of the schema (this is just testing that the version 2 update was correct after all). It uses Test::DBIx::Class to automatically deploy a temporary test database (by default it creates a SQLite in-memory database) which reflects the current schema and then we populate the all_tables fixtures using the utility class DBIx::Class::Migration::Population which is part of the DBIx::Class::Migration distribution. (In this case, since we are using Test::DBIx::Class, we are using the fixture hook Test::DBIx::Class::FixtureCommand::Population).

Before we can run the test case, we need to update our dist.ini file. Open this is a text editor and change it to look like this:

    name    = DBIx-Class-Migration
    author  = John Napiorkowski <jjnapiork@cpan.org>
    license = Perl_5
    copyright_holder = John Napiorkowski
    copyright_year   = 2012
    abstract = Tutorial Application for DBIx-Class-Migration

    version = 0.001

    [@Basic]
    [Prereqs]
    DBIx::Class = 0
    DBIx::Class::Migration = 0

    [Prereqs / TestRequires]
    Test::Most = 0
    Test::DBIx::Class = 0

We just added a new section "[Prereqs / TestRequires]" and listed the two testing modules. Great, now install the new dependencies:

    dzil listdeps | cpanm

Perfect, we are now fully up to date and anyone that checks out our code can also be sure to have all the right dependencies. Let's run the test case:

    $ prove -lv t/upgrade-1to2.t 
    t/upgrade-1to2.t .. 
    Restored set all_tables to database
    ok 1 - Correct Number of Tests
    ok 2 - Artist has a country
    1..2
    ok
    All tests successful.
    Files=1, Tests=2,  1 wallclock secs ( ... )
    Result: PASS

So hopefully that was easier database testing than you might be used too. :)

Additional Domain Logic Testing

Let's create another test for the Artist ResultSet class. You might have wondered about this code, which you added way back at the start of the tutorial:

lib/MusicBase/Schema/ResultSet/Artist.pm

    package MusicBase::Schema::ResultSet::Artist;

    use strict;
    use warnings;
    use base 'DBIx::Class::ResultSet';

    sub has_more_than_one_cds {
      my $me = (my $self = shift)->current_source_alias;
      $self->search(
        {},
        {
          join=>['cd_rs'],
          '+select'=> [ { count => 'cd_rs.cd_id', -as => 'cd_count'} ],
          '+as'=> ['cd_count'],
          group_by=>["$me.artist_id"],
          having => { cd_count => { '>', 1 } }
        }
      );
    }

    1;

This is a bit of logic that just returns the set of Artist with more than one cd. This is the kind of custom resultset logic your application may require and therefore you should have a test case. Let's build one:

    touch t/more-than-1.t

Then open t/more-than-1.t in your text editor and add this code:

    #!/usr/bin/env perl

    use Test::Most;
    use Test::DBIx::Class
      -schema_class=>'MusicBase::Schema',
      -fixture_class => '::Population',
      qw(Artist);

    fixtures_ok ['all_tables'];

    ok my $more_than_one_rs =  Artist->has_more_than_one_cds,
     'Got some artists';

    is $more_than_one_rs->count, 1,
      'Got expected number of artists with more than one CD';

    done_testing;

If you go back to the original fixture data, you'll see we only have one Artist in the all_tables fixture set that has more than one CD (Michael Jackson).

Obviously this is a pretty minimal test case, but it at least gets you started. let's run it:

    $ prove -lv t/more-than-1.t 
    t/more-than-1.t .. 
    Restored set all_tables to database
    ok 1 - Got some artists
    ok 2 - Got expected number of artists with more than one CD
    1..2
    ok
    All tests successful.
    Files=1, Tests=2,  1 wallclock secs ( ... )
    Result: PASS

That's it for Testing!

SUMMARY

This was a short section, but important. We explored how straightforward it is to create meaningful test cases using our generated fixtures, if you use the right tools to help you. We also explored the idea of limiting test cases to certain database versions, which will be an important thing for you to remember as you continue moving forward with your database changes.

NEXT STEPS

Proceed to DBIx::Class::Migration::Tutorial::ThirdMigration

AUTHOR

See DBIx::Class::Migration for author information

COPYRIGHT & LICENSE

See DBIx::Class::Migration for copyright and license information