I love fabricators. We use the awesome fabrication gem that lets you do some pretty neat things in Rails specs.
For example, we have a page that lists users in alphabetical order. The retrieval is implemented in a controller.
def index
@users = User.asc(:name)
end
The fabricator for a User generates a global sequence to give each user a unique name.
Fabricator(:user) do
name { Fabricate.sequence(:name) { |i| "Joe #{i}" } }
end
To test the above-mentioned controller, we would fabricate a couple users and ensure that they are returned in the correct order.
it "returns users in alphabetical order" do
user1 = Fabricate :user
user2 = Fabricate :user
get :index
assigns(:users).should eq [user1, user2]
end
What could possibly go wrong here?
I made a beginner mistake that just looks like someone else’s fault (specs fail depending on which order you run them). To get a failed test we fabricate 8 users before this spec is run. The next two users that are fabricated are Joe 9 and Joe 10. When sorted alphabetically Joe 10 comes before Joe 9, duh. It’s a good lesson in not relying on external behavior for tests – in this case we should not rely on knowing how names are generated in a fabricator to test that the users are sorted by name. Instead, we should assign names explicitly.
it "returns users in alphabetical order" do
user1 = Fabricate :user, name: "A"
user2 = Fabricate :user, name: "B"
get :index
assigns(:users).should eq [user1, user2]
end