Skip to content

Commit

Permalink
Provide a useful implementation of something compatible with testing.T (
Browse files Browse the repository at this point in the history
#571)

* Attempting to provide a useful implementation of something compatible with testing.T

* Handle Fail calls on the TestingT in the right place

* Provide as much of testing.T as possible + tidy up

* Add initial tests for testingT support

* Check compatibility with testing.T and friends

Co-authored-by: Piotr Bocheński <bochenski.piotr@gmail.com>

* Update assert-godogs example to show new usage. Rename 'GetTestingT(ctx)' to 'T(ctx)'

* Update changelog and readme with new usage

* Improve test coverage

* Review updates

---------

Co-authored-by: Piotr Bocheński <bochenski.piotr@gmail.com>
  • Loading branch information
mrsheepuk and b0ch3nski committed Apr 29, 2024
1 parent 10407bc commit 7017c73
Show file tree
Hide file tree
Showing 12 changed files with 562 additions and 90 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit 7017c73

Please sign in to comment.