Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a useful implementation of something compatible with testing.T #571

Merged
merged 9 commits into from Apr 29, 2024
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,9 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt

## Unreleased

### Added
- Provide testing.T-compatible interface on test context, allowing usage of assertion libraries such as testify's assert/require - ([571](https://github.com/cucumber/godog/pull/571) - [mrsheepuk](https://github.com/mrsheepuk))

## [v0.14.0]
### Added
- Improve ErrSkip handling, add test for Summary and operations order ([584](https://github.com/cucumber/godog/pull/584) - [vearutop](https://github.com/vearutop))
Expand Down
31 changes: 6 additions & 25 deletions README.md
Expand Up @@ -495,31 +495,12 @@ If you want to filter scenarios by tags, you can use the `-t=<expression>` or `-
A more extensive example can be [found here](/_examples/assert-godogs).

```go
func thereShouldBeRemaining(remaining int) error {
return assertExpectedAndActual(
assert.Equal, Godogs, remaining,
"Expected %d godogs to be remaining, but there is %d", remaining, Godogs,
)
}

// assertExpectedAndActual is a helper function to allow the step function to call
// assertion functions where you want to compare an expected and an actual value.
func assertExpectedAndActual(a expectedAndActualAssertion, expected, actual interface{}, msgAndArgs ...interface{}) error {
var t asserter
a(&t, expected, actual, msgAndArgs...)
return t.err
}

type expectedAndActualAssertion func(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool

// asserter is used to be able to retrieve the error reported by the called assertion
type asserter struct {
err error
}

// Errorf is used by the called assertion to report an error
func (a *asserter) Errorf(format string, args ...interface{}) {
a.err = fmt.Errorf(format, args...)
func thereShouldBeRemaining(ctx context.Context, remaining int) error {
assert.Equal(
godog.T(ctx), Godogs, remaining,
"Expected %d godogs to be remaining, but there is %d", remaining, Godogs,
)
return nil
}
```

Expand Down
59 changes: 9 additions & 50 deletions _examples/assert-godogs/godogs_test.go
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"fmt"
"os"
"testing"

Expand Down Expand Up @@ -36,31 +35,22 @@ func thereAreGodogs(available int) error {
return nil
}

func iEat(num int) error {
err := assertExpectedAndActual(
assert.GreaterOrEqual, Godogs, num,
"You cannot eat %d godogs, there are %d available", num, Godogs,
)
if err != nil {
return err
func iEat(ctx context.Context, num int) error {
if !assert.GreaterOrEqual(godog.T(ctx), Godogs, num, "You cannot eat %d godogs, there are %d available", num, Godogs) {
return nil
}

Godogs -= num
return nil
}

func thereShouldBeRemaining(remaining int) error {
return assertExpectedAndActual(
assert.Equal, Godogs, remaining,
"Expected %d godogs to be remaining, but there is %d", remaining, Godogs,
)
func thereShouldBeRemaining(ctx context.Context, remaining int) error {
assert.Equal(godog.T(ctx), Godogs, remaining, "Expected %d godogs to be remaining, but there is %d", remaining, Godogs)
return nil
}

func thereShouldBeNoneRemaining() error {
return assertActual(
assert.Empty, Godogs,
"Expected none godogs to be remaining, but there is %d", Godogs,
)
func thereShouldBeNoneRemaining(ctx context.Context) error {
assert.Empty(godog.T(ctx), Godogs, "Expected none godogs to be remaining, but there is %d", Godogs)
return nil
}

func InitializeScenario(ctx *godog.ScenarioContext) {
Expand All @@ -74,34 +64,3 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^there should be (\d+) remaining$`, thereShouldBeRemaining)
ctx.Step(`^there should be none remaining$`, thereShouldBeNoneRemaining)
}

// assertExpectedAndActual is a helper function to allow the step function to call
// assertion functions where you want to compare an expected and an actual value.
func assertExpectedAndActual(a expectedAndActualAssertion, expected, actual interface{}, msgAndArgs ...interface{}) error {
var t asserter
a(&t, expected, actual, msgAndArgs...)
return t.err
}

type expectedAndActualAssertion func(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool

// assertActual is a helper function to allow the step function to call
// assertion functions where you want to compare an actual value to a
// predined state like nil, empty or true/false.
func assertActual(a actualAssertion, actual interface{}, msgAndArgs ...interface{}) error {
var t asserter
a(&t, actual, msgAndArgs...)
return t.err
}

type actualAssertion func(t assert.TestingT, actual interface{}, msgAndArgs ...interface{}) bool

// asserter is used to be able to retrieve the error reported by the called assertion
type asserter struct {
err error
}

// Errorf is used by the called assertion to report an error
func (a *asserter) Errorf(format string, args ...interface{}) {
a.err = fmt.Errorf(format, args...)
}
4 changes: 2 additions & 2 deletions features/formatter/events.feature
Expand Up @@ -13,7 +13,7 @@ Feature: event stream formatter
"""

Scenario: should process simple scenario
Given a feature path "features/load.feature:26"
Given a feature path "features/load.feature:27"
When I run feature suite with formatter "events"
Then the following events should be fired:
"""
Expand All @@ -34,7 +34,7 @@ Feature: event stream formatter
"""

Scenario: should process outline scenario
Given a feature path "features/load.feature:34"
Given a feature path "features/load.feature:35"
When I run feature suite with formatter "events"
Then the following events should be fired:
"""
Expand Down
7 changes: 4 additions & 3 deletions features/formatter/pretty.feature
Expand Up @@ -350,7 +350,7 @@ Feature: pretty formatter
Scenario: Should scenarios identified with path:line and preserve the order.
Given a feature path "features/load.feature:6"
And a feature path "features/multistep.feature:6"
And a feature path "features/load.feature:26"
And a feature path "features/load.feature:27"
And a feature path "features/multistep.feature:23"
When I run feature suite with formatter "pretty"
Then the rendered output will be as follows:
Expand All @@ -363,7 +363,7 @@ Feature: pretty formatter
Scenario: load features within path # features/load.feature:6
Given a feature path "features" # suite_context_test.go:0 -> *godogFeaturesScenario
When I parse features # suite_context_test.go:0 -> *godogFeaturesScenario
Then I should have 13 feature files: # suite_context_test.go:0 -> *godogFeaturesScenario
Then I should have 14 feature files: # suite_context_test.go:0 -> *godogFeaturesScenario
\"\"\"
features/background.feature
features/events.feature
Expand All @@ -378,6 +378,7 @@ Feature: pretty formatter
features/run.feature
features/snippets.feature
features/tags.feature
features/testingt.feature
\"\"\"

Feature: run features with nested steps
Expand Down Expand Up @@ -407,7 +408,7 @@ Feature: pretty formatter
As a test suite
I need to be able to load features

Scenario: load a specific feature file # features/load.feature:26
Scenario: load a specific feature file # features/load.feature:27
Given a feature path "features/load.feature" # suite_context_test.go:0 -> *godogFeaturesScenario
When I parse features # suite_context_test.go:0 -> *godogFeaturesScenario
Then I should have 1 feature file: # suite_context_test.go:0 -> *godogFeaturesScenario
Expand Down
3 changes: 2 additions & 1 deletion features/lang.feature
Expand Up @@ -8,7 +8,7 @@ Savybė: užkrauti savybes
Scenarijus: savybių užkrovimas iš aplanko
Duota savybių aplankas "features"
Kai aš išskaitau savybes
Tada aš turėčiau turėti 13 savybių failus:
Tada aš turėčiau turėti 14 savybių failus:
"""
features/background.feature
features/events.feature
Expand All @@ -23,4 +23,5 @@ Savybė: užkrauti savybes
features/run.feature
features/snippets.feature
features/tags.feature
features/testingt.feature
"""
3 changes: 2 additions & 1 deletion features/load.feature
Expand Up @@ -6,7 +6,7 @@ Feature: load features
Scenario: load features within path
Given a feature path "features"
When I parse features
Then I should have 13 feature files:
Then I should have 14 feature files:
"""
features/background.feature
features/events.feature
Expand All @@ -21,6 +21,7 @@ Feature: load features
features/run.feature
features/snippets.feature
features/tags.feature
features/testingt.feature
"""

Scenario: load a specific feature file
Expand Down