Skip to content

Instantly share code, notes, and snippets.

@ntl
Last active August 29, 2015 13:57
Show Gist options
  • Save ntl/9352526 to your computer and use it in GitHub Desktop.
Save ntl/9352526 to your computer and use it in GitHub Desktop.
# The controller; yeah it's not great but I want to show the tests
class ProductsController < ApplicationController
def index
if params[:min_rating]
@products = Product.where("average_rating >= ?", params[:min_rating])
else
@products = Product.to_a
end
end
end
# The test with factories:
class ProductsControllerTest < ActiveSupport::TestCase
test "searching with a minimum rating filter" do
# Every controller test has to create its' data independently, or else
# shove common FactoryGirl.create calls into shared test setup.
#
# This gets really bloated and slow, *really* fast.
p1 = FactoryGirl.create :product, average_rating: 3
p2 = FactoryGirl.create :product, average_rating: 4
get :index, min_rating: 4
assert_equal [p2], assigns(:products)
end
end
# The test with fixtures:
class ProductsControllerTest < ActiveSupport::TestCase
test "searching with a minimum rating filter" do
# *Zero* ceremony behind test setup means I can spit out a ton
# of controller tests with as much ease as I could unit tests.
get :index, min_rating: 4
assert_equal [p2], assigns(:products)
end
end
# test/fixtures/products.yml
sweater:
name: "Corduroy sweater"
average_rating: 3
cost: 45
scarf:
name: "Purple scarf"
average_rating: 4
cost: 88
@ntl
Copy link
Author

ntl commented Mar 4, 2014

The key is understanding that the fixtures in test/fixtures/products.yml can (and should) be reused pervasively throughout your test suite. It is work to maintain your fixtures, but once you invest that effort, controllers -- and really all your application logic living above your models -- are a breeze to test.

By the way, the test that uses fixtures will be unbelievably fast. Persistence in your tests doesn't have to be slow. Factories, however, are extremely slow in cases where you have to hit the db. Fixtures run in a nice transaction and don't have to get rebuilt between tests.

Also, can you imagine what would happen if you didn't have an average_rating column on products? If you had to join against actual ratings rows? The fixtures approach would have no problem with it, but suddenly, life with factories got much harder.

A few fixtures per model can go a long way; when devs start creating new fixtures for every mutation, things get ugly fast. But those are bad fixture sets, not a problem with the feature itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment