RSpec is fantastic. It’s so phenomenal that I can’t imagine my development without it anymore. It’s extremely easy to use, fun to write specifications and see how they turn green as you progress. But… at some point, when you have several hundreds of specs, using almost all documented features and excited to max, you may start facing serious problems. They aren’t easy to debug and may lead to a disappointment, unless you are prepared and armed with knowledge.
Load first, then execute. What I discovered was that RSpec loads all specifications upon startup and then executes them one-by-one. It means several things to us, the developers:
- All constants you define in your specifications are global. You will get Ruby warnings on constant redefinitions, but it may not save you from unexpected glitches, when you expect one value, but get a completely different one.
- All methods you define outside your specifications are global. It may affect your specifications in the same way as global constants – the functionality you expect from your helper methods may not be as expected. There are several solutions to this: 1) use modules with unique names to hold your helper methods and include them into your specifications, 2) use specifications hierarchy (my next post is about it) to group specifications that need helper methods.
Partials on Classes and Modules are BAD. It may sound bizarre, but they are. When you stub your Classes and Modules, you do it globally. Whatever you do in one specification or an example is visible in every following. Yes, right, NO ISOLATION. So, when you stub your model’s finders to return a mock, they do return this mock later in other specifications and examples that follow, even though you don’t expect it, and especially when you don’t expect it. It was a huge AHA moment for me.
RSpec loads (runs) specifications in recently-changed last order. It means that it runs specifications you changed last at the end. Now take a break and mull it over. Having everything above in mind, do you still think that you really have a green light? What if you ran you first specification (that you wrote first and never changed since then) after everything else? The only way to know is to try running every specification in your collection last, but of course, it’s not possible. The lack of complete isolation of one spec from another puts a big question mark after “is RSpec as useful as it seems”. My own answer is “yes”, but you need to know about all this to be on the safe side.
To summarize, here’s a quick NO-NO list of mine:
- Never use Partials with Classes and Modules
- Never define constants in or outside specifications
- Never define methods outside specifications
I hope sincerely that this information helps you make your RSpec experience smooth as silk and you’ll avoid the road blocks I experienced during the last few weeks.