FactoryGirl vs. Bare Domain Objects
I’ve been doing a fair amount of research into testing and what are the best and fasted way to test. Recently, someone at work brought up the fact that using factories can drastically slow down your test suite. Especially when, like us, you create other factories within factories (ie. I need an advertiser for a campaign, so when I use Factory.build(:campaign), it also does Factory.create(:advertiser)). I tried using Factory.stub (check out this article), but it still would create in the background and I couldn’t change that without wrecking all of our other tests. I decided to start testing with bare domain objects, saving nothing to the database (when possible). Here is a comparison of using FactoryGirl vs. bare domain objects:
FactoryGirl
context '#validate flight dates with FactoryGirl' do setup do @campaign = FactoryGirl.build(:campaign, id: 1234, flight_start: Date.new(2014,01,28), flight_end: Date.new(2014,01,28)) end should 'be valid if campaign has the same flight_start and flight_end' do assert_true @campaign.valid? end should 'be invalid if flight_end is before flight_start' do @campaign.flight_end = Date.new(2014,01,27) assert_false @campaign.valid? assert @campaign.errors.full_messages.include?('Flight start must be earlier than campaign flight end date') end end
Bare Domain Objects
context '#validate flight dates with Bare Domain Objects' do should 'be valid if campaign has the same flight_start and flight_end' do campaign = Campaign.new(name: 'UNICORNS!!!', flight_start: Date.new(2014,01,28), flight_end: Date.new(2014,01,28)) campaign.valid? assert_false campaign.errors.full_messages.include?('Flight start must be earlier than campaign flight end date') end should 'be invalid if flight_end is before flight_start' do campaign = Campaign.new(name: 'UNICORNS!!!', flight_start: Date.new(2014,01,28), flight_end: Date.new(2014,01,27)) campaign.valid? assert campaign.errors.full_messages.include?('Flight start must be earlier than campaign flight end date') end end
Not so different, right? Takes less time since I’m not writing to the database and the only major difference is that I don’t assert that the object is valid. Instead I check to see if it is adding my error message. This helps simplify tests, even for more complicated objects.