Optional Setup Closure for Expect / Then StatementHandlers
This release adds an optional convenience: the ability to specify a setup step for Expect / Then handlers. It is fairly common for requirements to look something like this:
Given the user is on the setting screen
When the user selects the privacy option
Then an analytics event is sent with the payload
| actionType: navigate |
| destination: privacy |
In this case it is difficult to set up mocking and expectations before reaching the Then an analytics event is sent with the payload
step and asserting that expectations were met.
A common workaround is to add a somewhat redundant and awkward additional Given step, such as:
Given an analytics event will be expected with the payload
| actionType: navigate |
| destination: privacy |
And the user is on the setting screen
When the user selects the privacy option
Then an analytics event is sent with the payload
| actionType: navigate |
| destination: privacy |
This allows the preconditions to be correctly established before simulating the tap and asserting the expectation, however it is not a natural way of writing or reading requirements, and is also quite redundant. A key principle I have learned in requirements-driven development / BDD is to let people express requirements in as natural and comfortable a way as possible. This also makes the requirements more readable and understandable to future collaborators. We can do a little more work on the implementation side to enable this better communication of intent.
With this release, you can now specify a second trailing closure called "setup" with a Then / Expect statement handler. This closure will run when the example starts, with the other Given handlers (actually, right before them).
So for this example, you can keep the naturally expressed requirement:
Given the user is on the setting screen
When the user selects the privacy option
Then an analytics event is sent with the payload
| actionType: navigate |
| destination: privacy |
And in your test implementation you can do something like the following:
var statementHandlers: [StatementHandler] {
.then("an analytics event is sent with the payload") { input in
XCTAssertEqual(self.lastSentEvent.payload, input.statement.data.keyValues)
} setup: {
// Here we can perform a setup step that will run at the beginning of the Example with the Given steps, before
// we actually execute the above "Then"statement
self.eventAPI = MockEventAPI(delegate: self)
}
}
Hat tip to @tinder-owenthomas for suggesting this functionality!