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

NAME

DBIx::MoCo::Fixture - A fixture for testing model components of DBIx::MoCo

SYNOPSIS

  ## fixtures/entry.yml
  model: My::Bookmark::Entry
  records:
    first:
      id: 1
      title: Hatena Bookmark
      url: http://b.hatena.ne.jp/

    second:
      id: 2
      title: Yahoo
      url: http://www.yahoo.co.jp/

  ## t/entry.t
  use DBIx::MoCo::Fixture;
  use My::Bookmark::Entry;
  use Test::More tests => 2;

  my $f = fixtures(qw/entry/);
  is My::Bookmark::Entry->retrieve(1)->title, $f->{entry}->{first}->{title};
  is My::Bookmark::Entry->retrieve(2)->title, $f->{entry}->{second}->{title};

DESCRIPTION

A fixture loader for DBIx::MoCo. See DBIx::MoCo::Manual::Testing for more details.

METHODS

fixtures

  my $f = fixtures(qw/entry bookmark/, { yaml_dir => "../fixtures" })

Automatically loads ../fixtures/entry.yml and ../fixtures/bookmark.yml to the database.

NOTE: All records for the specified model will be once removed when <fixtures()> called. Do not use fixtures when your model is connected to the production database.

More Details on How to Use DBIx::MoCo::Fixture

Testing with Fixtures

To test your model classes efficiently and strictly, you should use real data which will be used in your production environment. DBIx::MoCo has Rails-like feature for testing, that is, fixtures, and it helps you to automatically set up test data into database.

Tables and model classes

Here you're going to perform testing for the tables and model classes below:

Tables:

  CREATE TABLE user (
    id   INTEGER PRIMARY KEY,
    name varchar(255)
  );

  CREATE TABLE entry (
    id      INTEGER PRIMARY KEY,
    user_id INTEGER,
    title   varchar(255),
    body    text
  )

Model classes:

  package Blog::MoCo::User;
  use strict;
  use warnings;
  use base qw (Blog::MoCo);
  use Blog::MoCo::Entry;

  __PACKAGE__->table('user');
  __PACKAGE__->has_many(
      entries => 'Blog::MoCo::Entry',
      { key => { id => 'user_id' } }
  );

  package Blog::MoCo::Entry;
  use strict;
  use warnings;
  use base qw 'Blog::MoCo';
  use Blog::MoCo::User;

  __PACKAGE__->table('entry');
  __PACKAGE__->has_a(
      user => 'Blog::MoCo::User',
      { key => { user_id => 'id'} }
  );

Setting up fixtures

Fixtures must be written in YAML and the file must have .yml extension.

Here's the structure of a fixture.

  model: Your::MoCo::Class
  records:
    record_name1:
      column1: foo
      column2: bar
    record_name2:
      column1: baz
      column2: quux
model (mandate, unchangeable)

A name of a model which is correspondent to a fixture.

records (mandate, unchangeable)

This field contains actual data to be inserted into your database.

record_name1, record_name2 ... (changeable along with your convinience)

Names of each records. You can use this names as keys of a hash reference to the data in the fixture.

column1, column2 ... (this names must be correspondent to the actual column names)

Names of each actual columns. This field contains the data of the column.

Well, fixtures() method loads fixtures from fixtures directory which is located in the same level of *.t scripts directory. You can make the method to retrieve fixtures from other directory by passing optional parameters as below:

  my $f = fixtures(qw(user entry), { yaml_dir => "../fixtures" });

Now you can write fixtures for testing like below:

user.yml

  model: Blog::MoCo::User
  records:
    first:
      id: 1
      name: jkondo

    second:
      id: 2
      name: naoya

entry.yml

  model: Blog::MoCo::Entry
  records:
    first:
      id: 1
      user_id: 1
      title: Hello World!
      body: I'm fine!

    second:
      id: 2
      user_id: 1
      title: Cinnamon
      body: The cutest dog ever!!!

Test Script

Finally, we'll start working on a test script using the fixtures above.

  use strict;
  use warnings;
  use Test::More;
  use FindBin::libs;

  use Blog::MoCo::User;
  use Blog::MoCo::Entry;

  use DBIx::MoCo::Fixture;

  # fixture() is exported from DBIx::MoCo::Fixture
  my $fixtures = fixtures(qw(user entry));

  plan tests => 8;

  # Verifying if the data from db and from fixture are equal
  is(Blog::MoCo::User->retrieve(1)->name,   $fixtures->{user}{first}{name});
  is(Blog::MoCo::User->retrieve(2)->name,   $fixtures->{user}{second}{name});
  is(Blog::MoCo::Entry->retrieve(1)->title, $fixtures->{entry}{first}{title});
  is(Blog::MoCo::Entry->retrieve(2)->title, $fixtures->{entry}{second}{title});
  is(Blog::MoCo::Entry->retrieve(1)->body,  $fixtures->{entry}{first}{body});
  is(Blog::MoCo::Entry->retrieve(2)->body,  $fixtures->{entry}{second}{body});

  # Verifying if has_a and has_many relationships work well
  is(
      Blog::MoCo::User->retrieve(1)->entries->find(sub { $_->id == 1})->title,
      $fixtures->{entry}{first}{title}
  );
  is(
      Blog::MoCo::Entry->retrieve(1)->user->name,
      $fixtures->{user}{first}{name}
  );

After you pass the names of fixtures into fixture() method and execute it, this method automatically loads the fixtures and inserts the data into your database. The return value of the method is a hash reference whose keys are same as the names of the record names in fixtures you see above.

In this way, you can easily test your model classes by verifying if the data from database is equal to one from the fixture.

AUTHOR

Naoya Ito <naoya@bloghackers.net>

SEE ALSO

DBIx::MoCo, Kwalify

ACKNOWLEDGEMENT

It borrowed many codes from Test::Fixture::DBIC::Schema.

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.