ActiveFactory
A fixture replacement library. With it your specs will become more declarative, uniform and terse.
Feedback will be highly appreciated
Introduction
ActiveFactory allows you declaratively define which objects you want to have in a database for your spec. You can also define associations between the objects and redefine default values. Additionally ActiveFactory automatically defines accessor methods for the objects. The scope of the methods is limited to current spec. So they will not affect you other specs.
it "Task.incomplete returns only incomplete tasks" do
models { project - tasks({:complete => 0}, {:complete => 1}) }
project.tasks.incomplete.should == [tasks[0]]
end
it "project displays incomplete tasks" do
models { my - project - task(:complete => 0) }
visit project_path(project)
page.should have_content task.title
end
These specs require the following configuration:
class ActiveFactory::Define
factory :my, :class => User do
username "my_name"
password "my_password"
before_save do
model.save!
context.emulate_sign_in model
end
end
factory :project do
title { "Project #{index} title" }
due { Time.now }
end
factory :task do
title { "Task #{index} title" }
end
end
In the configuration you specify default attribute values for an object, and in a specific test you may reassign the values for the needs of the test. Optional block after_build specifies actions that should be done after object was initialized but before saving it. If you want to create by the same factory several objects with different values, you may use blocks. Method index in those blocks returns index of the object being created.
Installation
ActiveFactory requires Rails 3 and RSpec 2.
rails plugin install git@github.com:tarasevich/active_factory.git
rails g active_factory:install
Now you are ready to add you factories spec/define_factories.rb and use models {} block in your specs.
Copyright © 2010-2011 Alexey Tarasevich, released under the MIT license
Some Examples
Consider we have factory declarations from introduction secion.
describe ProjectController do
it "creates a new project" do
models { my ; project_ }
post :create, :project => project_
Project.all.map(&:title).should == [project_[:title]]
end
...
In previous example factory my
in models
block causes to emulate login. project_
declares corresponding method inside the spec. Syntax with uderscore indicates that it’s should be just hash with values taken from the factory declaration. In our case it will be {:title => "Project 0 title"}
it "modifies a project's title" do
models { my - project }
put :update, :id => project.id, :project => project_(:title => "New Title")
project.reload.title.should == "New Title"
end
In this example we again use my
to create a user and log in with it. Additionally we create Project
instance using project
factory and define method project
locally for the spec. Finally we use minus sign to create association between user my
and project
. Active factory iterates through associations of User
model and chooses the one that has Project
on the other side. project_(h)
is just syntax sugar for project_.merge(h)