views:

51

answers:

1

I'd like to know the best way to approach testing ruby mixin modules, in this case for use with ActiveRecord models, but really this is a general quesiton that applies to any class that you are extending with a mixin.

Is it better to attempt to stub all of the necessary functionality of the Class that your mixin is extending, or just test the real class as present and extended in your app?

Stubbing would remove external dependencies for the tests, but it fails to test the mixin under real circumstances. If the test fail, it could be either your implementation or the class you are extending that changed or broke. If testing with a stubbed class your tests may pass but the functionality could be broken if the class you are extending changes.

Opinions?

+5  A: 

It's not completely clear to me what you're asking, but I'm going to assume it's something along the lines of, "If I have a class, and I extend that class with a module, where should I test the functionality provided by the module?"

Personally, when I write a module for use as a mixin, I try to make sure it has fairly robust testing independent of whatever classes I might eventually plan to mix it in to. Typically I'll define a class in the test suite that does nothing but extend to module, and then write tests to ensure that the test class has all the expected functionality. (You can see examples of this in my Classy gem, which is just a collection of mixin modules.) If the module were meant to extend ActiveRecord or some other class I didn't have any control over, I'd define as vanilla an ActiveRecord class as possible and work with that, though ideally I'd try to keep my module's functionality orthogonal from ActiveRecord's when possible.

If changes to ActiveRecord cause your tests to break, then there's a question of what your goals are in writing your module. If you want it to be generally available and useful to the public, then you probably want it to work with the newest version, and those failing tests are accurately reporting bugs that need fixing. If you only want it to work with whatever version you're running locally for your own project, then you can just run the tests against that version and you don't have to worry about it changing.

Assuming I had control over the class being mixed in to, I probably wouldn't test the functionality from the module too extensively in the tests for the class - that's what the module tests are for. I would have a test case or two to make sure that it generally works, and I would test any specific interactions or intricacies specific to the class being tested, and probably leave it at that.

John Hyland
Not a lot more to be said after that, +1
Yar
+1 Totally agree, this is exactly what I do.
nas