My Adventures as an Apprentice Developer
During my first interview for this role I said a really dumb thing. It was one of those things that comes out of your mouth before you’ve even had a chance to filter: “I suck at RSpec”.
I can’t believe I said that! And, to make matters worse, I said it to someone that I was hoping would hire me and train me up. But it was, and still kind of is, true…I really do suck at RSpec.
This week I was assigned a new piece of functionality to implement. That meant, amongst other things, a brand new RSpec file.
I’m OK at taking an existing test suite and modifying or adding to it. But…from scratch? That’s a whole other thing. I know what to test, but creating the structure and knowing what goes where does my head in. There seems to be so many rules, and very few of them are documented.
I began by just dumping out everything I wanted to test. It was long and unstructured but the tests passed. However, I knew my Pull Request would get rejected unless I refactored it and made use of the features provided by RSpec. It was time to face my demons and get my head around some of this stuff.
So, with the help of Code School, Stack Overflow, and, of course, my awesome team mates; I have produced a spec that is simple and streamlined and easy to follow.
Many times I have googled for a true beginners guide to RSpec and failed. All such tutorials are pitched at a more intermediate level. So, for what it’s worth, here are the RSpec “rules” I have managed to figure out so far…
context
and describe
don’t actually do anything other than give structure to your file. They are technically the same thing, but they are each used in a slightly different way. However you use them, make sure it is consistent. Choose a convention (or follow that of your company) and stick with it.
Describe is often used to group together examples of a piece of functionality (a method, a controller action, etc). It says what were are testing.
ruby
describe User do
describe "#current?" do
Context blocks are used within describe blocks to set up different scenarios for your tests (A.K.A. “examples”). They group together examples that share a particular state or belong to a particular scenario, such as a valid user, invalid user, etc. If you are using a before block to set up a scenario, it will usually follow a context block.
let
is simply a way of making objects available to your examples. When you type
ruby
let(:user) { User.first }
You are defining a method that returns a User instance. Your examples can refer to that instance simply by calling “user” as if it were a pre-defined variable. This must be done outside of the examples (i.e. in a context or a describe block) so that they are available by the time the example runs.
The it
blocks are the examples, they contain the actual test. There are some smarts that you can employ to make use of the subject and reduce code but that is best saved for another day. Code School explains it so much better than I ever could in Level 3 of “Testing with RSpec”.
I am starting to see why people love RSpec. It allows you to structure your tests in a logical way that enhances readability.
A lot of this structure comes down to personal preference, which is why a definitive “Dummies Guide to RSpec” is so hard to come by. There is no one right way to lay out your examples, contexts, etc. However, it is important to reconcile your preferred structure with that of your teammates so that your project’s specs aren’t a mishmash of different styles.
And that’s pretty much it. The next time I am given a blank slate and have to write some tests I’m not going to feel quite as apprehensive. I’ll put it out there: I still have a lot to learn when it comes to RSpec. But I feel like I suck a little bit less now.