First example there: test_new_customer_defaults. Really, it needs 3 saved models to test this? FactoryGirl isn't solution here. It's just hiding the problem.
If you need a complex network of collaborators to test a method, the answer is not to obscure the creation of those collaborators, it's to refactor so that each object talks only to its immediate neighbours, and then stub the heck out of them. If it absolutely has to be something that acts like an ActiveModel, then use mock_model().
The Rails Tutorial (railstutorial.org) uses Factory Girl and integration tests for just about everything, which is a fast enough approach for its toy application, but I've found that when your application gets more complex your test suite takes forever to run, and setting up the tests gets more and more painful (especially when you start dealing with external APIs).
Does anyone have any opinions on the best resource for teaching effective unit testing in Rails? I'd love to speed up my test suite while not losing coverage.
[1]: http://objectsonrails.com/
I'm not sure if it's the best resource, though. I'd love to hear other opinions.
FactoryGirl.define do
factory :user do
association :account, :strategy => :build
end
end
Otherwise when you build a user, the account association will still get persisted to the database.Even if you do this, though, you're still spinning up a whole network of real objects in what is supposed to be a unit test.
Edited to add: Using FactoryGirl to generate a cache only addresses the performance issues without addressing the complexity-hiding problem.
Factories are slow. Yes, they really are. Persisting everything along a chain of associations will always be slower than properly isolating the dependencies of the unit under test, SSD or not. It's easier to enjoy Ruby when not constantly waiting minutes for tests to run.
Factories increase the over-all complexity of your app. Are you kidding me? Yes, they do. Expertise and huge, easy gains have nothing to do with reducing complexity and more often (but not always) increase it. A test suite where every test depends on state in a database is more complex than one that tests units in isolation.
None of these points are arguing against Factory Girl, which is a great tool for doing what it does; they are arguing against integrating with the database in "unit" tests.
"Watch out everybody, he's hitting the database!!!"
Ruby is a great language that I love, but this is one of those cases where Ruby's conciseness and readability hide a TON of complexity. And complexity in tests is death.
I've seen it for myself -- there's a lot of technical debt interest in those tests. It looks manageable at the beginning, especially within the scope of a blog post, but when the app grows and grows and grows, the tests fail.
However I more and more agree with the general notion that your unit test should not hit the DB. However, Rails works against that. Avdi Grimm's "Object's on Rails" (http://objectsonrails.com/) has some interesting suggestions on how to get some good test isolation out of Rails.
You can use build instead of create to avoid the db, as per previous comments. You don't have to use it at all if writing a simple unit test.
But for teeing up complex scenarios prior to a fat integration test, it rocks.