#60
Jul 20, 2007

Testing without Fixtures

Tests which rely heavily on fixtures are brittle and can be difficult to maintain. This episode will show a couple techniques for creating tests which don't use fixtures.
Tags: testing
Download (14.3 MB, 9:49)
alternative download for iPod & Apple TV (12.2 MB, 9:49)
# cart_test.rb
def test_total_weight_should_be_sum_of_line_item_weights
  cart = Cart.new
  cart.line_items.build.stubs(:weight).returns(7)
  cart.line_items.build.stubs(:weight).returns(3)
  assert_equal 10, cart.total_weight
end

# line_item_test.rb
def test_should_have_zero_for_weight_when_not_shipping
  line_item = LineItem.new
  line_item.build_delivery_method(:shipping => false)
  assert_equal 0, line_item.weight
end

def test_should_have_weight_of_product_times_quantity_when_shipping
  line_item = LineItem.new(:quantity => 3)
  line_item.build_delivery_method(:shipping => true)
  line_item.build_product(:weight => 5)
  assert_equal 15, line_item.weight
end

RSS Feed for Episode Comments 25 comments

1. chineseGuy Jul 20, 2007 at 01:33

good,mocha!


2. InMan Jul 20, 2007 at 01:56

Something new for me :).
Well, its easier to read some tests...
With fixtures, its faster to make tests :P.

How about you.. using fixtures or doing like you showed? :).


3. Carlos Brando Jul 20, 2007 at 03:40

Excelent!


4. Ryan Bates Jul 20, 2007 at 07:24

@InMan, I don't use fixtures at all in the model (unit test) layer. However, I still use fixtures in the controller and view layers (functional tests) just so the site has some filler data. Those tests don't rely very heavily on the data inside the fixtures so it's not much of a problem.


5. Peter Jul 20, 2007 at 07:28

Great! I was hoping for some testing tips soon. Any chance we can look forward to some more? ;)


6. Barry Hess Jul 20, 2007 at 07:53

Thanks for this Railscast. I've been trying to crack the egg of fixtureless testing...looking for a primer. Now to find something that improves my controller testing experience.


7. Robert Dempsey Jul 20, 2007 at 08:29

Thanks for another great Railscast. I can never stress enough (to everyone) the need for testing apps. The more info that is there to help make it easier for all of us, the better off we all are. Thanks again.


8. Tom Porter Jul 20, 2007 at 08:51

Ryan, Thanks for your tireless work on these railscasts. You create them faster than I can watch them!


9. Karl Smith Jul 20, 2007 at 10:40

@Ryan: What you you using to run those 'auto-tests'? Looks interesting.

I would like to add that I started skipping fixtures as well, mainly from the point that after a couple of weeks, I can never remember what data was where or how I named the fixture records. So I create a protected method at the bottom of the test case and simply build the records there:

protected
    def create_broadcast_month(options = {})
      BroadcastMonth.create({
        :end_date => Date.new(2007,12,13),
        :start_date => Date.new(2007,1,1)
         }.merge(options))
    end

Secondly, I really like using the db for all tests. I know it's slower, but I have caught db problems in the tests that I would not have seen if it was not r/w to the db.

Thanks for another great rcast!


10. Karl Jul 20, 2007 at 10:53

Karl, It's ZenTest probably.


11. Carl Porth Jul 20, 2007 at 12:55

@Barry: In controllers, there are lots of tricks using mocha to get rid of fixtures. For example, if you want to test your create action, you can use the any_instance method.

Product.any_instance.stubs(:valid?).returns(true)

That way you can test how the controller behaves without depending on how the model behaves (bypassing validations).


12. Innu Jul 22, 2007 at 03:41

http://pastie.caboo.se/81115

Well... I need a bit help with unit test. Testing counter_cache column.


13. Ryan Bates Jul 22, 2007 at 08:17

@Innu, I believe the counter cache column only works when records are saved to the database, so try using "create" instead of new/build.


14. Innu Jul 22, 2007 at 09:31

Ryan. Yeh.
Sometimes I just ask weird questions :). Now I looked and got it. Edited paste too.

Without fixtures, code and understanding is clearer. Thanks for that railscast.


15. dudzjosh Jul 22, 2007 at 17:31

Hey really like the screen cast, just wondering what your thoughts are on Rspec vs Test::Unit.

I've pretty much started using only RSpec now and I really like the behavior driven approach.

Also it comes in built with stubbing and mocking.

When I used test unit I based some of my test structure on the Peepcode screencast on testing (really highly recommend). One of the things that it mentions to do is to stick class variables in to your test helper file with a hash of all values that will make a specific model valid. eg @@user_default_values = {:name => 'joe'}, this way you can make sure that these hashes are creating valid instances with a test in your test units and can reuse them in others tests such as functional tests or whatever. I suppose the only thing is the clarity issue with this technique where you have to look at a couple of files if you need to know exactly what your tests are doing.

Cheers


16. Ryan Bates Jul 22, 2007 at 18:35

@dudzjosh, I normally use rSpec as well, and was tempted to use it for this screencast but decided to stick with what's built into Rails. You can apply basically the same principles no matter the framework.

While I do use rSpec, I still use Mocha for mocking/stubbing. I've had problems with their built in framework.

Also, I don't use mocking/stubbing nearly as much in the controller/view layers as they recommend. I find it's a lot of work with very little benefit. But that's more of my personal opinion so I probably won't make a screencast on it.


17. vlad Jul 23, 2007 at 00:33

i agree that fixtures can be pretty brittle when there are a lot of interweaving dependencies between them, but testing without fixtures seems less DRY. seems like a case of choosing the lesser evil.


18. Ryan Bates Jul 23, 2007 at 07:27

@vlad, true, it is less dry. But, I'm finding the DRY principle isn't nearly as important in testing. There are some cases keeping tests DRY can improve readability and maintainability, but other times it will lead to brittle tests which share too much. Tests should be self contained so changing one doesn't effect another.


19. vlad Jul 23, 2007 at 10:48

good point, and i guess dryness is mainly important in case you want to change something somewhere but forget to also change it somewhere else. i guess with tests that isn't a huge deal because the worst that'll happen is that some test will fail. i guess it's much worse when something that is shared by a lot of tests breaks them all at once (and possibly in different ways).


20. Neil Jul 24, 2007 at 04:34

Great thanks!


21. jonathan Jul 24, 2007 at 12:18

Great!

Thanks for the testing video. I really look forward to the next one. Maybe it'll even be rSpec?

Cheers,


22. Gnrl LFO Oct 01, 2007 at 03:03

OMG!!! This is so sexy!!!


23. kino May 23, 2008 at 01:55

As is shown in the writings of Aristotle, our sense perceptions would thereby be made to contradict, so far as regards philosophy, the Antinomies, and the discipline of pure reason occupies part of the sphere of time concerning the existence of the Antinomies in general.


24. Mark Schmatz Jul 04, 2008 at 12:52

Hi Ryan!

Very good job! All of your screencasts are excellent! Maybe you want to tag all of your Mocha related casts with 'mocha'. For me, this would be helpful since I'm currently very interested in testing and mocking.

I'm a researcher at the University of Bonn, Germany where I and my colleagues are leaders of our Agile Software Development / Extreme Programming Lab.

Best regards,
Mark


25. Greg H Sep 02, 2008 at 13:53

Hi,

Where does the "build" method come from? I looked in Mocha, Ruby, Rails APIs methods but could not find it?

Thanks

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player