Skip to content

Support Multiple given/setup Blocks #2190

@akefirad

Description

@akefirad

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:

  1. 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.
  2. The second reason which is more important is that it's not possible to use @RepeatUntilFailure in @Stepwise tests. We use this nice feature (repeat until failure) a lot to debug flaky tests.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions