Releases: daniel-hall/RequirementsKit
Optional Setup Closure for When StatementHandlers
This release adds optional setup closures for "When" StatementHandlers, adding on to the support for setup closures in "Expect" and "Then" StatementHandlers from the last release. See previous release notes for full details on how these setup closures work and why they are useful!
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!
v2.1.0 — Highlight Test Failures in Requirements File
This release adds a new feature which highlights the statement in a requirements file that failed. So if a test fails on the statement Given the user is logged in
, clicking on the test failure will jump to that .feature file and highlight that line. This makes it easy to directly see which requirements and statements are broken or not implemented.
To turn this off and jump instead to the statement handling code that failed, then add this property to your test configuration class:
var shouldDisplayFailuresOnRequirement = false
- This release also makes XCTest expectation-related methods available on the configuration class for using in statement handlers.
v2.0.0 — Dynamic Test Generation!
This is a major new update that changes how requirements-based test targets are set up and executed. Now, RequirementsKit will dynamically generate an XCTestCase class for every .feature
(Gherkin) or .requirements
(ReqsML) file in your target. Each generated XCTestCase will have generated test methods, one for each rule or requirement in the file. Each test method will execute all the examples for that rule or requirement.
This approach provides the following huge benefits:
- Now each file and requirement appears separately in the Xcode testing panel. This makes it easy to see at a glance which files and requirements passed or failed
- Individual files or requirements can now also be re-run from the sidebar as well by clicking the "play" button next to the test case or test method name
- Requirements-based UI tests will now support running in parallel. Each
.feature
or.requirements
file will be executed in a separate simulator instance concurrently
In order to config a test target for using RequirementsKit now the steps have changes:
- Create the test target as usual in Xcode
- Ensure your requirements folder with all the files for different testable requirements is added to the test target
- Delate all the boilerplate test code and all test cases. Create a single class that subclasses
RequirementsTestConfiguration
. You will be prompted to satisfy protocol requirements by specifying an array of statement handlers, a setUp method that runs between examples, optional default timeout, etc. - IMPORTANT: In the info.plist section of your test target, add a new key called "PrincipalClass" (it will autocomplete). The value should be the fully qualified name of the class you created above, e.g.
MyUITests.MyUITestConfiguration
That's it! Now the test cases and methods will be generated for all your requirements and will execute the matching statement handlers you provided.
This release also fixes a bug in the parsing of Gherkin tags
Various Improvements
-
Made the
XCTestCase.testRequirements(in directory:String?
parameter default to nil for the most common case of just discovering all requirements -
Call the
beforeEachExample
closure before each Example is run -
StatementHandler
can now be created with one of more String statements to match -
Fixed the static factory methods on
StatementHandler
to take throwing closures -
Added factory method overloads for accepting handler closures that don’t use any input. This is a very common case that should always require explicitly ignoring an input parameter, e.g.
{ _ in }
Initial Release
RequirementsKit is an expansion and evolution of the previous TestKit library which can:
- Parse functional requirements from multiple source syntaxes (currently Gherkin and ReqsML)
- Test requirements using XCTest and plugging into the standard Xcode test results
- Automatically discover all requirements under a directory and validate them
RequirementsKit is intended in the near future to include more tools for managing requirements, including an editor for searching, filtering and updating requirements across multiple files and directories according to their labels, and translating between Gherkin and ReqsML formats.