#60 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.
- Download:
- mp4Full Size H.264 Video (13.6 MB)
- m4vSmaller H.264 Video (9.58 MB)
- webmFull Size VP8 Video (31.3 MB)
- ogvFull Size Theora Video (20.4 MB)
good,mocha!
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? :).
Excelent!
@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.
Great! I was hoping for some testing tips soon. Any chance we can look forward to some more? ;)
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.
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.
@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!
Karl, It's ZenTest probably.
@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).
http://pastie.caboo.se/81115
Well... I need a bit help with unit test. Testing counter_cache column.
@Innu, I believe the counter cache column only works when records are saved to the database, so try using "create" instead of new/build.
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.
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
@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.
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.
@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.
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).
Great!
Thanks for the testing video. I really look forward to the next one. Maybe it'll even be rSpec?
Cheers,
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
Hi,
Where does the "build" method come from? I looked in Mocha, Ruby, Rails APIs methods but could not find it?
Thanks
Ryan, i totally agree - tests should be completely isolated from anything else and using fixtures (other than to clear required data) can be a real pain.
Thanks again for a great screencast :)
I'd also be keen to hear your views on testing models with and without database connectivity - I've written an article about it here: http://www.kirkbushell.com/articles/rspec-model-tests
Thanks for this episode Ryan. I have a question here. You talked about some methods in this episode that are provided by has_many: association ( for example- cart.line_items.build, line_item.build_delivery_method, etc.. )What do you mean by that? And is there any documentation for such methods?
I will appreciate your help to make me understand this.
Ryan,
You are such a huge asset to the community. Thanks so much for all your hard work.
@schreyans, googling for that same question got me your question ;), so googled some more, thought you might want me to share it.
search in http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html for build_, much documentation on it! hope this helps :)
know we have them in
I've been playing with Mocha but learning about .build made my life so much simpler!
Thanks yet again!
This is really a terrific deal for a critical article, I seriously discovered your blog by mistake when researching on Msn for some thing diffrent closely connected, in any case prior to I ramble on too a lot I would just like to say simply how much I cherished your article, I
Thank you Ryan.
As usual, you're my first reference on Rails world!
Go ahead so!
I think the test_should_have_zero_for_weight_when_not_shipping test is very weak. weight will return zero simply because there are no line items, with no weights. If you had line_item.build_delivery_method(:shipping => true) instead, the result would still be zero.