cucumber / godog

Cucumber for golang
MIT License
2.31k stars 251 forks source link

Before-Step hook not invoked for multisteps #486

Closed wichert closed 1 year ago

wichert commented 2 years ago

I have a before-Step hook to replace variables in steps. You can use it do things like this:

Scenario: Demonstrate variables
  Given I set "name" to "Zaphod"
  I login as ${name}

Normally variables are set by other steps, and they provide a convenient way to pass some context around between API calls. One use case is to test an API where I need to create a parent and a child object. I can do that using variables like so:

Scenario: Test creation of books
  Given I create an author named "Jane Doe"
  When I create a book "Intro to godog" for author ${author_id}
  Then the API returned succeeded

Doing this many times becomes tedious, especially when you need to go down more levels. To solve that I want to leverage a multistep:

ctx.Step("there exists an author with a book", func(context.Context) godog.Steps {
    return godog.Steps{
        `I create an author named "Jane Doe"`,
        `I create a book "Intro to godog" for author ${author_id}`,
        "the API returned succeeded",
    }
}

so I can just start my tests like this:

Scenario: Test creation of books
  Given there exists an author with a book
  ...

This is failing, because my StepContext.Before is never invoked for steps returned by a multistep.

📦 Which tool/library version are you using?

godog v0.12.4

wichert commented 2 years ago

@vearutop I would like to contribute a fix for this, but I'm not sure how best to approach this. Do you have any hints?

vearutop commented 2 years ago

I was briefly looking at this issue today in the morning and can confirm it exists.

Here is where BeforeStep is invoked https://github.com/cucumber/godog/blob/b2672bb93363c73a3d1a14f1a97784f70a78e176/suite.go#L136, it happens only for "root-level" steps. And here are multisteps are being invoked: https://github.com/cucumber/godog/blob/b2672bb93363c73a3d1a14f1a97784f70a78e176/suite.go#L354.

I think implementation strategy could be to change def.Run(ctx) into a suite method that would receive def and ctx and wrap a call with hooks. Maybe we can just use (s *suite) runStep for that (not sure if there are any caveats or implications).