There are two popular styles of formatting test descriptions:
it('should do something') and
it('does something'). Which style should you use? Is any of them objectively better, or is it just a matter of personal taste?
To help us decide, let’s take a look at
does test styles from three points of view:
Let’s compare how tests for the same functionality, written in
does styles, could print out in a console.
Guest User should have temporary account should not have permanent account should be able to read posts should not be able to create posts
Guest User has temporary account does not have permanent account can read posts cannot create posts
The most visible difference is that the
should word acts as a “bullet point”, a constant delimiter forming a neat list. This is purely a matter of taste. Some people claim that this improves readability, making tests more “scannable”. For other people (me included) this is just a noise, that doesn’t add any useful information – and makes tests less readable.
The second, less visible difference, is how the two styles impact negations. In the
should style, negation is standardized – a test always starts with either
should not prefix, so it is immediately obvious if this is a positive or negative case. In the
does style, positive and negative cases are named differently each time (e.g.
does not have,
does not write etc.). For some people, a standardized way of negation makes tests easier to comprehend. My personal opinion is that to comprehend full implications of the test you still need to understand what exactly is being negated, so the standardized negation prefix doesn’t help much here, it only makes the description longer.
Summarizing: from the standpoint of test output readability, I prefer the
does version, although it is a matter of personal taste, and there are no objective arguments for or against either style.
Documentation vs specification
There is a subtle, interesting distinction between the
does styles. One leans more towards specification, while the other towards documentation.
should phrase naturally fits new requirements. It sounds good when you specify a functionality that doesn’t yet exist in the system:
The system should allow a user to view his payment history,
The sign up should require a valid email etc.
On the other hand,
should makes poor documentation. In a user manual, it sounds much better to write
An eraser tool cleans the canvas than
An eraser tool should clean the canvas. An end user expects that you’ll tell him how your system works, what it actually does not what it should do. (
An eraser should clean the canvas – Should? So it may not clean it? Under what circumstances?)
This leads us to an interesting question: how do we treat our tests? As a specification, or as a documentation?
If you do TDD, then you write tests first, for the functionality that doesn’t yet exist. It feels natural, then, to treat them as a specification (BDD-style frameworks even explicitly call the tests “specs”). On the other hand, you don’t throw the tests away after you write the code – you leave them to act as a documentation, to helping future you and your team members remember how the system works.
So which phase is more important? On the one hand, the specification phase is crucial, because it is the phase that drives the design of the system. On the other hand, the documentation phase is much longer. You write your code once, but then you live with it often for years (re-reading it, refactoring, explaining to new team members and so on).
Personally, I lean towards the documentation (
does) approach. To me, it feels more natural to read during the code maintenance phase (which, as I mentioned above, is much longer that the code creation phase) and, from my experience, using the documentation style doesn’t really hinder my ability to design code by listening to the tests during the specification phase.
Purposeful ambiguity vs clear intent
The last subtle difference between the
does test styles lies in the perceived level of ambiguity.
does style is uncompromising, with a clear, decisive intent. The system does that thing. If it doesn’t (if a test fails), it means that the system is broken, that there is a bug in the code.
should style leaves more room for discussion. If you say “The system does that” there is no room for argument. If you say “The system should do that” it opens the system for questions like “Should it really? Are we sure?”. (Such an open approach is advocated by inventor of BDD, Dan North in his introductory post).
should style also impacts how we treat failed tests. If the system only
should do something, a failed test doesn’t necessarily mean that there is a bug in the code. It may as well mean that our previous assumption of what the system should do is incorrect, and that we should discuss requirements. Some people even go as far as to claim that even in the case of a regular bug the
does style is a lie, because it says that the system does something, while it actually does not at the moment – thus the
should style is more correct.
As far as specifying intent goes, I prefer the
should style over the
Should is more honest and it’s a better discussion starter, what’s really important if you want to be agile about your requirements.
So which style should I use?
As you can see, this is mostly the matter of very fine nuances, and in a big part purely of individual taste. Personally, I lean slightly towards the
it does style. It’s less noisy and much nicer to read, and with a proper mental attitude I can still stay as open for a discussion as in the
should case. However, I’m not dogmatic about it. I’m OK to work with any of the styles, as long as it’s consistently used throughout the project.
I won’t try to convince you towards either the
does style. Choose whichever feels better to you and lets you reason more comfortably about the behavior of your system. I just hope that the above analysis will help you decide in a more conscious manner.
I’d really like to know what works for you. Which test description style do you prefer? Please share below in the comments!