Skip to content

Commit

Permalink
added the missing impl of json/events/junit/pretty - still need 'prog…
Browse files Browse the repository at this point in the history
…ress' and 'junit,pretty'
  • Loading branch information
Johnlon committed Oct 15, 2024
1 parent 8edde7f commit 184b68b
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 13 deletions.
2 changes: 1 addition & 1 deletion internal/formatters/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var (
skipped = models.Skipped
undefined = models.Undefined
pending = models.Pending
ambiguous = models.Skipped
ambiguous = models.Ambiguous
)

type sortFeaturesByName []*models.Feature
Expand Down
9 changes: 8 additions & 1 deletion internal/formatters/fmt_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (f *Base) Ambiguous(*messages.Pickle, *messages.PickleStep, *formatters.Ste
// Summary renders summary information.
func (f *Base) Summary() {
var totalSc, passedSc, undefinedSc int
var totalSt, passedSt, failedSt, skippedSt, pendingSt, undefinedSt int
var totalSt, passedSt, failedSt, skippedSt, pendingSt, undefinedSt, ambiguousSt int

pickleResults := f.Storage.MustGetPickleResults()
for _, pr := range pickleResults {
Expand All @@ -114,6 +114,9 @@ func (f *Base) Summary() {
case failed:
prStatus = failed
failedSt++
case ambiguous:
prStatus = ambiguous
ambiguousSt++
case skipped:
skippedSt++
case undefined:
Expand Down Expand Up @@ -144,6 +147,10 @@ func (f *Base) Summary() {
parts = append(parts, yellow(fmt.Sprintf("%d pending", pendingSt)))
steps = append(steps, yellow(fmt.Sprintf("%d pending", pendingSt)))
}
if ambiguousSt > 0 {
parts = append(parts, yellow(fmt.Sprintf("%d ambiguous", ambiguousSt)))
steps = append(steps, yellow(fmt.Sprintf("%d ambiguous", ambiguousSt)))
}
if undefinedSt > 0 {
parts = append(parts, yellow(fmt.Sprintf("%d undefined", undefinedSc)))
steps = append(steps, yellow(fmt.Sprintf("%d undefined", undefinedSt)))
Expand Down
2 changes: 1 addition & 1 deletion internal/formatters/fmt_cucumber.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ func (f *Cuke) buildCukeStep(pickle *messages.Pickle, stepResult models.PickleSt
cukeStep.Result.Error = stepResult.Err.Error()
}

if stepResult.Status == undefined || stepResult.Status == pending {
if stepResult.Status == undefined || stepResult.Status == pending || stepResult.Status == ambiguous {
cukeStep.Match.Location = fmt.Sprintf("%s:%d", pickle.Uri, step.Location.Line)
}

Expand Down
12 changes: 11 additions & 1 deletion internal/formatters/fmt_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (f *Events) step(pickle *messages.Pickle, pickleStep *messages.PickleStep)
pickleStepResults := f.Storage.MustGetPickleStepResultsByPickleID(pickle.Id)
for _, stepResult := range pickleStepResults {
switch stepResult.Status {
case passed, failed, undefined, pending:
case passed, failed, undefined, pending, ambiguous:
status = stepResult.Status.String()
}
}
Expand Down Expand Up @@ -318,6 +318,16 @@ func (f *Events) Pending(pickle *messages.Pickle, step *messages.PickleStep, mat
f.step(pickle, step)
}

// Ambiguous captures ambiguous step.
func (f *Events) Ambiguous(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition, err error) {
f.Base.Ambiguous(pickle, step, match, err)

f.Lock.Lock()
defer f.Lock.Unlock()

f.step(pickle, step)
}

func (f *Events) scenarioLocation(pickle *messages.Pickle) string {
feature := f.Storage.MustGetFeature(pickle.Uri)
scenario := feature.FindScenario(pickle.AstNodeIds[0])
Expand Down
6 changes: 6 additions & 0 deletions internal/formatters/fmt_junit.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ func (f *JUnit) buildJUNITPackageSuite() JunitPackageSuite {
tc.Failure = &junitFailure{
Message: fmt.Sprintf("Step %s: %s", pickleStep.Text, stepResult.Err),
}
case ambiguous:
tc.Status = ambiguous.String()
tc.Error = append(tc.Error, &junitError{
Type: "ambiguous",
Message: fmt.Sprintf("Step %s", pickleStep.Text),
})
case skipped:
tc.Error = append(tc.Error, &junitError{
Type: "skipped",
Expand Down
109 changes: 105 additions & 4 deletions internal/formatters/fmt_output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func Test_FmtOutput(t *testing.T) {

featureFiles, err := listFmtOutputTestsFeatureFiles()
require.Nil(t, err)
formatters := []string{"cucumber", "events", "junit", "pretty", "progress", "junit,pretty"}
// formatters := []string{"cucumber", "events", "junit", "pretty", "progress", "junit,pretty"}
formatters := []string{"pretty"} //, "junit", "pretty", "progress", "junit,pretty"}
for _, fmtName := range formatters {
for _, featureFile := range featureFiles {
testName := fmt.Sprintf("%s/%s", fmtName, featureFile)
Expand Down Expand Up @@ -144,12 +145,15 @@ func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) {
ctx.Step(`^(?:a )?failing step`, failingStepDef)
ctx.Step(`^(?:a )?pending step$`, pendingStepDef)
ctx.Step(`^(?:a )?passing step$`, passingStepDef)
ctx.Step(`^ambiguous step.*$`, ambiguousStepDef)
ctx.Step(`^ambiguous step$`, ambiguousStepDef)
ctx.Step(`^odd (\d+) and even (\d+) number$`, oddEvenStepDef)
ctx.Step(`^(?:a )?a step with a single attachment call for multiple attachments$`, stepWithSingleAttachmentCall)
ctx.Step(`^(?:a )?a step with multiple attachment calls$`, stepWithMultipleAttachmentCalls)
}

return func(t *testing.T) {
fmt.Printf("fmt_output_test for format %10s : sample file %v\n", fmtName, featureFilePath)
expectOutputPath := strings.Replace(featureFilePath, "features", fmtName, 1)
expectOutputPath = strings.TrimSuffix(expectOutputPath, path.Ext(expectOutputPath))
if _, err := os.Stat(expectOutputPath); err != nil {
Expand All @@ -167,6 +171,7 @@ func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) {
Format: fmtName,
Paths: []string{featureFilePath},
Output: out,
Strict: true,
}

godog.TestSuite{
Expand All @@ -178,9 +183,13 @@ func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) {
// normalise on unix line ending so expected vs actual works cross platform
expected := normalise(string(expectedOutput))
actual := normalise(buf.String())

assert.Equalf(t, expected, actual, "path: %s", expectOutputPath)

// display as a side by side listing as the output of the assert is all one line with embedded newlines and useless
if expected != actual {
println("diff")
fmt.Printf("Error: fmt: %s, path: %s\n", fmtName, expectOutputPath)
compareLists(expected, actual)
}
}
}
Expand All @@ -195,9 +204,17 @@ func normalise(s string) string {
return normalised
}

func passingStepDef() error { return nil }
func passingStepDef() error {
return nil
}

func oddEvenStepDef(odd, even int) error { return oddOrEven(odd, even) }
func ambiguousStepDef() error {
return nil
}

func oddEvenStepDef(odd, even int) error {
return oddOrEven(odd, even)
}

func oddOrEven(odd, even int) error {
if odd%2 == 0 {
Expand Down Expand Up @@ -242,3 +259,87 @@ func stepWithMultipleAttachmentCalls(ctx context.Context) (context.Context, erro

return ctx, nil
}

// wrapString wraps a string into chunks of the given width.
func wrapString(s string, width int) []string {
var result []string
for len(s) > width {
result = append(result, s[:width])
s = s[width:]
}
result = append(result, s)
return result
}

// compareLists compares two lists of strings and prints them with wrapped text.
func compareLists(expected, actual string) {
list1 := strings.Split(expected, "\n")
list2 := strings.Split(actual, "\n")

// Get the length of the longer list
maxLength := len(list1)
if len(list2) > maxLength {
maxLength = len(list2)
}

colWid := 60
fmtTitle := fmt.Sprintf("%%4s: %%-%ds | %%-%ds\n", colWid, colWid)
fmtData := fmt.Sprintf("%%4d: %%-%ds | %%-%ds %%s\n", colWid, colWid)

fmt.Printf(fmtTitle, "#", "expected", "actual")

for i := 0; i < maxLength; i++ {
var val1, val2 string

// Get the value from list1 if it exists
if i < len(list1) {
val1 = list1[i]
} else {
val1 = "N/A"
}

// Get the value from list2 if it exists
if i < len(list2) {
val2 = list2[i]
} else {
val2 = "N/A"
}

// Wrap both strings into slices of strings with fixed width
wrapped1 := wrapString(val1, colWid)
wrapped2 := wrapString(val2, colWid)

// Find the number of wrapped lines needed for the current pair
maxWrappedLines := len(wrapped1)
if len(wrapped2) > maxWrappedLines {
maxWrappedLines = len(wrapped2)
}

// Print the wrapped lines with alignment
for j := 0; j < maxWrappedLines; j++ {
var line1, line2 string

// Get the wrapped line or use an empty string if it doesn't exist
if j < len(wrapped1) {
line1 = wrapped1[j]
} else {
line1 = ""
}

if j < len(wrapped2) {
line2 = wrapped2[j]
} else {
line2 = ""
}

status := "same"
// if val1 != val2 {
if line1 != line2 {
status = "different"
}

// Print the wrapped lines with fixed-width column
fmt.Printf(fmtData, i+1, line1, line2, status)
}
}
}
13 changes: 13 additions & 0 deletions internal/formatters/fmt_pretty.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ func (f *Pretty) Failed(pickle *messages.Pickle, step *messages.PickleStep, matc
f.printStep(pickle, step)
}

// Failed captures failed step.
func (f *Pretty) Ambiguous(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition, err error) {
f.Base.Ambiguous(pickle, step, match, err)

f.Lock.Lock()
defer f.Lock.Unlock()

f.printStep(pickle, step)
}

// Pending captures pending step.
func (f *Pretty) Pending(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition) {
f.Base.Pending(pickle, step, match)
Expand Down Expand Up @@ -269,6 +279,9 @@ func (f *Pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in
case result.Status == failed:
errorMsg = result.Err.Error()
clr = result.Status.Color()
case result.Status == ambiguous:
errorMsg = result.Err.Error()
clr = result.Status.Color()
case result.Status == undefined || result.Status == pending:
clr = result.Status.Color()
case result.Status == skipped && clr == nil:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,39 @@
}
}
]
},
{
"id": "some-scenarios;ambiguous",
"keyword": "Scenario",
"name": "ambiguous",
"description": "",
"line": 16,
"type": "scenario",
"steps": [
{
"keyword": "When ",
"name": "ambiguous step",
"line": 17,
"match": {
"location": "formatter-tests/features/some_scenarions_including_failing.feature:17"
},
"result": {
"status": "ambiguous",
"error_message": "ambiguous step definition, step text: ambiguous step\n\tmatches:\n\t\t^ambiguous step.*$\n\t\t^ambiguous step$"
}
},
{
"keyword": "Then ",
"name": "passing step",
"line": 18,
"match": {
"location": "fmt_output_test.go:XXX"
},
"result": {
"status": "skipped"
}
}
]
}
]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/some_scenarions_including_failing.feature:1","source":"Feature: some scenarios\n\n Scenario: failing\n Given passing step\n When failing step\n Then passing step\n\n Scenario: pending\n When pending step\n Then passing step\n\n Scenario: undefined\n When undefined\n Then passing step\n"}
{"event":"TestSource","location":"formatter-tests/features/some_scenarions_including_failing.feature:1","source":"Feature: some scenarios\n\n Scenario: failing\n Given passing step\n When failing step\n Then passing step\n\n Scenario: pending\n When pending step\n Then passing step\n\n Scenario: undefined\n When undefined\n Then passing step\n\n Scenario: ambiguous\n When ambiguous step\n Then passing step\n"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:3","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:4","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:4","timestamp":-6795364578871}
Expand All @@ -26,4 +26,11 @@
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:14","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:14","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:12","timestamp":-6795364578871,"status":"undefined"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:16","timestamp":-6795364578871}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:17","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:17","timestamp":-6795364578871,"status":"ambiguous","summary":"ambiguous step definition, step text: ambiguous step\n\tmatches:\n\t\t^ambiguous step.*$\n\t\t^ambiguous step$"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:18","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:18","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:18","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:16","timestamp":-6795364578871,"status":"ambiguous"}
{"event":"TestRunFinished","status":"failed","timestamp":-6795364578871,"snippets":"You can implement step definitions for undefined steps with these snippets:\n\nfunc undefined() error {\n\treturn godog.ErrPending\n}\n\nfunc InitializeScenario(ctx *godog.ScenarioContext) {\n\tctx.Step(`^undefined$`, undefined)\n}\n","memory":""}
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ Feature: some scenarios
Scenario: undefined
When undefined
Then passing step

Scenario: ambiguous
When ambiguous step
Then passing step
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="junit" tests="3" skipped="0" failures="1" errors="2" time="0">
<testsuite name="some scenarios" tests="3" skipped="0" failures="1" errors="2" time="0">
<testsuites name="junit" tests="4" skipped="0" failures="1" errors="2" time="0">
<testsuite name="some scenarios" tests="4" skipped="0" failures="1" errors="2" time="0">
<testcase name="failing" status="failed" time="0">
<failure message="Step failing step: step failed"></failure>
<error message="Step passing step" type="skipped"></error>
Expand All @@ -13,5 +13,9 @@
<error message="Step undefined" type="undefined"></error>
<error message="Step passing step" type="skipped"></error>
</testcase>
<testcase name="ambiguous" status="ambiguous" time="0">
<error message="Step ambiguous step" type="ambiguous"></error>
<error message="Step passing step" type="skipped"></error>
</testcase>
</testsuite>
</testsuites>
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@
<yellow>When</yellow> <yellow>undefined</yellow>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

<bold-white>Scenario:</bold-white> ambiguous <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:16</bold-black>
<yellow>When</yellow> <yellow>ambiguous step</yellow>
<bold-red>ambiguous step definition, step text: ambiguous step
matches:
^ambiguous step.*$
^ambiguous step$</bold-red>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:XXX -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>

--- <red>Failed steps:</red>

<red>Scenario: failing</red> <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:3</bold-black>
<red>When failing step</red> <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:5</bold-black>
<red>Error: </red><bold-red>step failed</bold-red>


3 scenarios (<red>1 failed</red>, <yellow>1 pending</yellow>, <yellow>1 undefined</yellow>)
7 steps (<green>1 passed</green>, <red>1 failed</red>, <yellow>1 pending</yellow>, <yellow>1 undefined</yellow>, <cyan>3 skipped</cyan>)
4 scenarios (<red>1 failed</red>, <yellow>1 pending</yellow>, <yellow>1 ambiguous</yellow>, <yellow>1 undefined</yellow>)
9 steps (<green>1 passed</green>, <red>1 failed</red>, <yellow>1 pending</yellow>, <yellow>1 ambiguous</yellow>, <yellow>1 undefined</yellow>, <cyan>4 skipped</cyan>)
0s

<yellow>You can implement step definitions for undefined steps with these snippets:</yellow>
Expand Down

0 comments on commit 184b68b

Please sign in to comment.