-
Notifications
You must be signed in to change notification settings - Fork 476
Description
Is your feature request related to a problem?
It's really hard to write heavy integration tests without multiple given blocks. Either the given block becomes very big and unreadable or one has to use @Stepwise annotation.
We use Spock extensively for our integration tests which cover full flows (e.g. purchase flow: get an offer, place an order, do the payment, generating contracts and documents, send emails, etc etc).
Since all of these tests are real HTTP requests, they are pretty slow (compared to unit tests), some of the steps can be almost a second to complete.
If you wanna keep tests totally isolated, either you have to generate the test data (i.e. putting the offer in the database to be able to place an order) every time for every test (which becomes cumbersome and unmaintainable pretty quickly) or use the existing functionality to get the system into the right state (i.e. call POST /api/offer before calling POST /api/order) which makes the test exponentially slower.
The best alternative at the moment is to use @Stepwise tests (which we do) and it works just fine 👍.
Describe the solution you'd like
Ideally it'd be wonderful to merge different steps of a test into a single test method and avoid using @Stepwise, for two reasons:
- That means a single spec can cover more than one scenario (AFAIK). Otherwise, if you have multiple scenarios you have to create different specs with different names which make navigation a bit unintuitive.
- The second reason which is more important is that it's not possible to use
@RepeatUntilFailurein@Stepwisetests. We use this nice feature (repeat until failure) a lot to debug flaky tests. - Sometimes it's not even possible to merge all "setup" logic into one since some of the interactions might be executed out of order.
More specifically I'm thinking about something like this:
def 'test purchase flow'() {
given: 'a valid request to get an offer'
// some test data to get an offer
when: 'send a request to get an offer'
// send POST /api/offer
then: 'response should be correct'
// assert the response is correct
given: 'a valid request to place an order'
// some test data to place an order
when: 'send a request to place an order'
// send POST /api/order
then: 'response should be correct'
// assert the response is correct
...
}Describe alternatives you've considered
Currently it is possible to merge all steps into one single test, but the challenge is that either you have to make the given block very big or put the "setup" logic of each step in their "when" block which is not quite idiomatic in Spock.
I guess I understand why multiple given block is not supported, but I was wondering if there's a way to address this limitation?
Thanks.
Additional context
No response