Every intro to testing tutorial out there will have you write tests at multiple levels of abstraction. With larger test suites, this can get quite unwieldy as your readers are forced to abstract on the fly. As Ruby devs, it’s our mission to increase readibility and conciseness at every turn.
Multiple levels of abstraction
Here’s an original spec file I had for a Rails app I’m building. Context: this is testing the dataset creation feature in which a dataset requires a name, and two separate files.
We can see quite clearly that even with just one scenarios, it’s initially hard to figure out exactly whats going on in this test. The reader is forced to abstract each step on the fly.
The first step to breaking down this multi-level test is to separate it out into phases. Thoughbot approaches this by defining all their tests into four phases. We’ll follow that convention for this exercise by separating out each step within a scenario into either the setup, exercise, verify or teardown phase. In this case we don’t need to teardown any part of our test so we’ll stick with just the first three phases. Here’s what I get:
Now that we have a good separation of behavior in our scenarios, we can start to abstract the logic into concise methods.
Single layer of abstraction
This refactored spec abstracts each piece of functionality into specific methods that improve readibility and reduces context-switching for readers. The reader can now read each scenario and understand each step logically. The cost of implementing this refactor is not cheap, but I argue that the test suite is better organized, easier to read, and easier to change later on.
What are your thoughts on single level test abstractions and what other methods have you implemented in your test suites?