Loading Test Data with YAML Fixtures
Problem
It's important that your test database contains known data that is common to each test case for the model being tested. You don't want your tests to pass or fail depending on what's in the database when they run; that defeats the whole purpose of testing. You have created data to test the boundary conditions of your application, and you want an efficient way to load that data into your database without using SQL.
Solution
Use YAML to create a file containing test fixtures to be loaded into your test database.
Your database contains a single books table as created by the following migration:
db/migrate/001_build_db.rb:
class BuildDb < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.column :title, :string
t.column :CNPJ, :string
t.column :ean, :string
t.column :upc, :string
t.column :edition, :string
end
end
def self.down
drop_table :books
end end
Create a Book model using the Rails generate script (notice the test scaffolding that's created by this command):
$ ruby script/generate model book
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/book.rb
create test/unit/book_test.rb
create test/fixtures/books.yml
Now, create a fixture containing your test data in the books.yml file under the test/fixtures directory:
test/fixtures/books.yml:
perl_cookbook:
id: 1
title: Perl Cookbook
CNPJ: 957824732X
ean: 9789578247321
upc: 636920527114
edition: 1
java_cookbook:
id: 2
title: Java Cookbook
CNPJ: 9867794141
ean: 9789867794147
upc: 236920522114
edition: 1
mysql_cookbook:
id: 3
title: MySQL Cookbook
CNPJ: 059652708X
ean: 9780596527082
upc: 636920527084
edition: 2
Fixtures are loaded by the Test::Unit module by passing the name of the fixture file, without the extension, as a symbol to the fixtures method. The following unit test class shows the books fixtures being loaded with a test confirming success:
test/unit/book_test.rb:
require File.dirname(__FILE__) + '/../test_helper'
class BookTest < Test::Unit::TestCase
fixtures :books
def test_fixtures_loaded
perl_book = books(:perl_cookbook)
assert_kind_of Book, perl_book
end end
Discussion
YAML is a data serialization format designed to be easily readable and writable by humans, as well as by scripting languages such as Python and Ruby. YAML is often used for data serialization and configuration settings, where it serves as a more transparent alternative to XML or a custom configuration language.
Before it runs each test case, the Test::Unit module uses the solution's fixture file (books.yml) to initialize the books table of the test database. In other words, each test case starts with a fresh copy of the test data, just as it appears in the YAML fixture. This way, tests can be isolated with no danger of side effects.
The test_fixtures_loaded test case of the BookTest class tests that the book fixtures are loaded successfully and that an Active Record Book object is created. Individual records in a YAML fixture are labeled for convenient reference. You can use the books fixture accessor method to return book objects by passing it one of the fixture labels. In the solution, we return an object representing the Perl Cookbook by calling books(:perl_cookbook). The assertion tests that this object is, in fact, an instance of the Book class. The following output shows the successful results of running the test:
$ ruby ./test/unit/book_test.rb
Loaded suite test/unit/book_test Started
.
Finished in 0.05485 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
See Also
|