Cucumber steps often involve asserting a condition or the opposite of it. For example:
Not only is it boring to write steps like this: it also has the downside of introducing duplication into our test steps. If the DOM changes, we are forced to update both steps.
Even worse, if the DOM changes and we forget to update the negative assertion, it will always pass since the element doesn’t even exist!
Let’s give it another shot, but this time we will encapsulate the DOM references:
The code is easier to read, and we solved a potential maintainability issue, nice! It’s possible to add a little touch of regular expressions to combine both steps into one:
If we write “should not see” then the group will match and the
should_not variable will contain
" not". If we write “should see” then the group won’t capture anything and
should_not will be
nil. This allows us to make a simple conditional check.
We can leverage Ruby’s expressiveness and take it a bit further:
Shorter, but not necessarily easier to understand. Fortunately, we can create our own custom RSpec matcher to encapsulate this pattern and make it easier to reuse and understand:
Finally, we are able to express the step in a very concise and readable way:
No magic here , just clever naming
to_or has been a very helpful addition to our projects, allowing us to write simple steps that read like English. You can just copy the
PositiveNegativeExpectationHandler to a support file in your project (like
features/support/to_or.rb) and start using it right away