1=head1 NAME
2
3DBIx::Class::Migration::Tutorial::Testing - Test Your Database
4
5=head1 GOAL
6
7Let's take an interlude from creating migrations and turn to writing test
8cases for your database.
9
10It would help if you are familiar with L<Test::Most> and L<Test::DBIx::Class>
11and with general Perl testing procedures.  You could also benefit from reviewing
12our fixtures hook class L<Test::DBIx::Class::FixtureCommand::Population>.
13
14=head1 Test your 1-2 Upgrade
15
16When doing upgrades it would be great to have some automated tests in place so
17that whoever does the upgrade can immediately verify that all is well.  Let's
18add a test case now!
19
20    touch t/upgrade-1to2.t
21
22Then open the new files in the editor of choice and enter the following code:
23
24    #!/usr/bin/env perl
25
26    use Test::Most;
27    use Test::DBIx::Class
28      -schema_class=>'MusicBase::Schema',
29      -fixture_class => '::Population',
30      qw(Artist Country);
31
32    plan skip_all => 'not correct schema version'
33      if Schema->schema_version != 2;
34
35    fixtures_ok ['all_tables'];
36
37    is Country->count, 3, 'Correct Number of Countries';
38    ok Artist->first->has_country, 'Artist has a country';
39
40    done_testing;
41
42This creates a basic test case that only runs for version 2 of the schema (this
43is just testing that the version 2 update was correct after all).  It uses
44L<Test::DBIx::Class> to automatically deploy a temporary test database (by
45default it creates a C<SQLite> in-memory database) which reflects the current
46schema and then we populate the C<all_tables> fixtures using the utility class
47L<DBIx::Class::Migration::Population> which is part of the L<DBIx::Class::Migration>
48distribution.  (In this case, since we are using L<Test::DBIx::Class>, we are
49using the fixture hook L<Test::DBIx::Class::FixtureCommand::Population>).
50
51Before we can run the test case, we need to update our C<dist.ini>
52file.  Open this is a text editor and change it to look like this:
53
54    name    = DBIx-Class-Migration
55    author  = John Napiorkowski <jjnapiork@cpan.org>
56    license = Perl_5
57    copyright_holder = John Napiorkowski
58    copyright_year   = 2012
59    abstract = Tutorial Application for DBIx-Class-Migration
60
61    version = 0.001
62
63    [@Basic]
64    [Prereqs]
65    DBIx::Class = 0
66    DBIx::Class::Migration = 0
67
68    [Prereqs / TestRequires]
69    Test::Most = 0
70    Test::DBIx::Class = 0
71
72We just added a new section "[Prereqs / TestRequires]" and listed the two
73testing modules.  Great, now install the new dependencies:
74
75    dzil listdeps | cpanm
76
77Perfect, we are now fully up to date and anyone that checks out our code can
78also be sure to have all the right dependencies.  Let's run the test case:
79
80    $ prove -lv t/upgrade-1to2.t
81    t/upgrade-1to2.t ..
82    Restored set all_tables to database
83    ok 1 - Correct Number of Tests
84    ok 2 - Artist has a country
85    1..2
86    ok
87    All tests successful.
88    Files=1, Tests=2,  1 wallclock secs ( ... )
89    Result: PASS
90
91So hopefully that was easier database testing than you might be used too. :)
92
93=head1 Additional Domain Logic Testing
94
95Let's create another test for the Artist ResultSet class.  You might have
96wondered about this code, which you added way back at the start of the
97tutorial:
98
99C<lib/MusicBase/Schema/ResultSet/Artist.pm>
100
101    package MusicBase::Schema::ResultSet::Artist;
102
103    use strict;
104    use warnings;
105    use base 'DBIx::Class::ResultSet';
106
107    sub has_more_than_one_cds {
108      my $me = (my $self = shift)->current_source_alias;
109      $self->search(
110        {},
111        {
112          join=>['cd_rs'],
113          '+select'=> [ { count => 'cd_rs.cd_id', -as => 'cd_count'} ],
114          '+as'=> ['cd_count'],
115          group_by=>["$me.artist_id"],
116          having => { cd_count => { '>', 1 } }
117        }
118      );
119    }
120
121    1;
122
123This is a bit of logic that just returns the set of Artist with more than one
124cd.  This is the kind of custom resultset logic your application may require
125and therefore you should have a test case.  Let's build one:
126
127    touch t/more-than-1.t
128
129Then open C<t/more-than-1.t> in your text editor and add this code:
130
131    #!/usr/bin/env perl
132
133    use Test::Most;
134    use Test::DBIx::Class
135      -schema_class=>'MusicBase::Schema',
136      -fixture_class => '::Population',
137      qw(Artist);
138
139    fixtures_ok ['all_tables'];
140
141    ok my $more_than_one_rs =  Artist->has_more_than_one_cds,
142     'Got some artists';
143
144    is $more_than_one_rs->count, 1,
145      'Got expected number of artists with more than one CD';
146
147    done_testing;
148
149If you go back to the original fixture data, you'll see we only have one Artist
150in the C<all_tables> fixture set that has more than one CD (Michael Jackson).
151
152Obviously this is a pretty minimal test case, but it at least gets you started.
153let's run it:
154
155    $ prove -lv t/more-than-1.t
156    t/more-than-1.t ..
157    Restored set all_tables to database
158    ok 1 - Got some artists
159    ok 2 - Got expected number of artists with more than one CD
160    1..2
161    ok
162    All tests successful.
163    Files=1, Tests=2,  1 wallclock secs ( ... )
164    Result: PASS
165
166That's it for Testing!
167
168=head1 SUMMARY
169
170This was a short section, but important.  We explored how straightforward it is
171to create meaningful test cases using our generated fixtures, if you use the
172right tools to help you.  We also explored the idea of limiting test cases to
173certain database versions, which will be an important thing for you to remember
174as you continue moving forward with your database changes.
175
176=head1 NEXT STEPS
177
178Proceed to L<DBIx::Class::Migration::Tutorial::ThirdMigration>
179
180=head1 AUTHOR
181
182See L<DBIx::Class::Migration> for author information
183
184=head1 COPYRIGHT & LICENSE
185
186See L<DBIx::Class::Migration> for copyright and license information
187
188=cut
189
190