Last active
August 29, 2015 13:57
-
-
Save ntl/9352526 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 onproducts
? If you had to join against actualratings
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.