Сравнить коммиты

...

43 коммитов

Автор SHA1 Сообщение Дата
Softonik
6087fc101c AST: файл Magefile.go пропускается при поиске имени пакета
Некоторые проверки провалились
test / test (1.16.x) (push) Has been cancelled
test / test (1.17.x) (push) Has been cancelled
test / test (oldstable) (push) Has been cancelled
test / test (stable) (push) Has been cancelled
2025-06-06 17:06:26 +03:00
Softonik
f5ec4cadce +Magefile.go
Ожидается выполнение проверок
test / test (1.16.x) (push) Waiting to run
test / test (1.17.x) (push) Waiting to run
test / test (oldstable) (push) Waiting to run
test / test (stable) (push) Waiting to run
2025-06-06 16:12:53 +03:00
Softonik
ccc4a42649 AST: из Base скопирован/поправлен генератор функций:
с прямой последовательностью и добавлением шагов в тестовые файлы
2025-06-06 16:10:49 +03:00
Softonik
59344caf33 AST: тесты вынесены во вложенный пакет, чтобы не было циклической зависимости 2025-06-06 15:52:32 +03:00
Softonik
56522e757a + Сценарий: Добавление шага с параметрами строкой 2025-06-06 15:15:44 +03:00
Softonik
bda4071975 ++ Сценарии: Добавление шага 2025-06-05 06:44:44 +03:00
Softonik
af6027bad2 + Сценарий: Добавление функции к существующей + без дубликаций 2025-06-05 03:50:32 +03:00
Softonik
9ad168ae70 + Сценарий: Добавление функции с параметрами: int, string 2025-06-05 03:29:34 +03:00
Softonik
4a15650887 + Сценарий: Добавление функции с параметрами: int 2025-06-05 03:02:37 +03:00
Softonik
6f2a5fef98 + Сценарий: Добавление сгенерированных функций в test-файл 2025-06-05 02:08:33 +03:00
Softonik
4e3e82b79e Добавлено godog_and_gomega + сопутствующие обновления модулей и кода 2025-06-04 23:20:51 +03:00
Softonik
26dafa0117 +Для русских сценариев генерируются русские функции 2025-06-04 22:53:47 +03:00
Softonik
3b25e9eb02 Сокращён вывод результатов 2025-06-04 22:29:13 +03:00
Softonik
78bab577c5 Добавлен формат AST 2025-06-03 05:03:20 +03:00
Softonik
0c030e0a6c Модуль переименован для публикации 2025-06-03 04:16:23 +03:00
Softonik
1b9806b25b чистка 2025-06-03 03:30:46 +03:00
Softonik
d2686eb13d чистка 2025-06-03 03:12:20 +03:00
Softonik
f0399fda41 Добавлена поддержка focused-тестов во множестве feature-файлов 2025-06-03 03:11:14 +03:00
Softonik
13639e7df7 Добавлена поддержка тестов с f-тегом 2025-06-03 03:06:08 +03:00
Softonik
60442133fc Тесты: отключены хрупкие тесты, проверяющие общее их количество 2025-06-03 02:58:55 +03:00
Dominik Gedon
74fa488023
Replace deprecated ::set-output (#681)
As per the deprecation warning and explanation at https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2025-03-24 11:05:30 +01:00
Tighearnán Carroll
4a4fd8ab3a
fix(errors): Fix expected Step argument count for steps with context.Context (#679)
* fix(errors): print correct number of expected steps when step has  defined

* add unit test

* remove duplicate part from unit test

* update changelog
2025-03-19 23:04:06 +00:00
renovate[bot]
e03da742a5
fix(deps): update module github.com/spf13/pflag to v1.0.6 (#675)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 23:24:31 +00:00
Ahmadreza
14fe127e3d
Update honnef.co/go/tools/cmd/staticcheck version in Makefile (#670) 2024-12-19 11:12:33 +01:00
Viacheslav Poturaev
e55eab64f7
Add details to "step is undefined" error (#669)
* Add details to "step is undefined" error

* Update changelog
2024-12-10 16:54:49 +01:00
GrindStone
da4633a421
Localisation support (#665)
* Add dialect options to support localisation

* Add test for ParseFeatures support for localisation
2024-11-14 10:42:18 +01:00
Tighearnán Carroll
c5a88f62c2
fix(formatter): On concurrent execution, execute formatter at end of Scenario (#645)
* fix(formatter): add onflush logger only print output at end of scenario when running concurrently

* add to changelog

* fix tests

* fix scenario outline output for the Pretty formatter

* fix casing for linter

* add coverage for new storage function

* relate suite back to where it was originally

* better type assertion on flush log

* var name for asserted formatter that doesn't clash with stdlib's fmt

* add coverage to summary

* only defer flush func when running concurrently

* much more concise way of deferring the flush

---------

Co-authored-by: Viacheslav Poturaev <vearutop@gmail.com>
2024-11-08 17:05:40 +01:00
renovate[bot]
9b699ff9a8
fix(deps): update module github.com/cucumber/godog to v0.15.0 (#661)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-02 01:42:01 +00:00
Viacheslav Poturaev
dc6950b1e3 Update CHANGELOG.md 2024-10-31 19:06:21 +01:00
John Lonergan
ecd2dfebbd
Ambiguous step detection - add support to all formatters (#648)
* added the missing impl of json/events/junit/pretty - still need 'progress' and 'junit,pretty'

* added tests for "progress formatter"

* switched from tabs to spaces in the ambiguous steps error message

* rename some_scenarions_including_failing
to     some_scenarios_including_failing

* changelog
2024-10-16 15:41:47 +01:00
John Lonergan
223efc3b14
Fix some type checks on the signatures of nested step handlers (#647)
* at some point someone changed the return type for nested steps from []string to godog.Steps but they forgot to adjust the type checks. The existing type checks were lax and unable to distinguish  []string from godog.Steps but in a couple of places in the code the value is coerced to godog.Steps and so if someone returned []string then the code would blow up. Additionally there were some tests aroudn these types but they also had not been updated but the test was passing for the wrong reason - the particular test expected an error but the cause of the error wasn't the one the code expected.

* CHANGELOG.md

* use chatgpt to regen the top of the code based on the new tests

* use chatgpt to regen the top of the code based on the new tests

* corrected the error messages of the param checks to indicate that the problem is the function signature and not the args being passed to the function, also added numerous extra assertions on the precise error messages returned. Now that the precise error is being verified in the test I have improved certain error messages to that more accurate detail is included in the errors

* added further constraints to the step arg mapping tests

* removed redundant test

* include a step error result in the reported error even when the ctx is nil
2024-10-15 13:25:13 +01:00
John Lonergan
8edde7f30c
Bugfix afterscenario attachments (#646)
* Minor doc and comment corrections

* Fixed bug where it was impossible to make attachments from 'after scenario' hook, also removed some dud comments.

* typo
2024-10-06 02:12:56 +01:00
John Lonergan
1e7c45eb78
Minor doc and comment corrections (#644) 2024-10-05 02:40:42 +01:00
M.P. Korstanje
6e4f452389
Replace more slack with discord
See:
- https://github.com/cucumber/common/issues/2195
- https://github.com/orgs/cucumber/discussions/2197
2024-08-09 16:58:01 +02:00
M.P. Korstanje
9b51734429
Replace slack with discord
See:
- https://github.com/cucumber/common/issues/2195
- https://github.com/orgs/cucumber/discussions/2197
2024-08-09 16:51:01 +02:00
John Lonergan
901da7fa3d
fixed a bug where the attachments are extracted from the context too early, this prevented AfterStep from making attachments (#637)
* fixed a bug where the attachments are extracted from the context too early, this prevented AfterStep from making attachments
2024-07-23 17:22:51 +01:00
John Lonergan
bcf6bce793
ambiguous step def detection akin to cucumber jvm (#636)
* added basic detection for ambiguous steps, but causes an error and not yet recorded in the reports as 'Ambiguous', and no test cases figured out yet

* added initial support for detection of ambiguous steps - further work take a look at how cuke jvm report ambiguous steps and sets the step status to 'ambiguous' rather than my current solution which just blows the test up as a regular step error

* added suite_context_test and also introduced missing 'ambiguous' status to make cucumber jvm'

* update CHANGELOG for ambiguous step defs

* missed file from commit

* added internal/formatters/fmt_multi_test.go

* add tests for other peoples code

* added "ambigous" to the help text

* tests

* added some more tests for attachments

* Update internal/flags/flags.go

Co-authored-by: Viacheslav Poturaev <nanopeni@gmail.com>

---------

Co-authored-by: Viacheslav Poturaev <nanopeni@gmail.com>
2024-07-01 10:28:39 +01:00
John Lonergan
3abb346b28
provisional: Attachments now uses base64 padding not raw mode (#629)
* corrected base64 encoding of attachments to use padding as that's what cuke JVM does
2024-05-31 21:33:57 +01:00
John Lonergan
9558224cce
Additional code review observations on Attach() functionality from https://github.com/cucumber/godog/pull/623 (#628)
* support multiple calls to the Attach() function from a single step

* run_progress_test.go changed so it's not sensitive to the name of the clone target directory

* applied code review comments also added _example/attachments

* applied code review comments also added _example/attachments

* applied code review comments also added _example/attachments
2024-05-30 02:29:14 +00:00
John Lonergan
f85def32ee
Moved CHANGHELOG entry to correct location (#626) 2024-05-29 09:19:33 +02:00
John Lonergan
201e526078
added support for Attachments (aka Embedddings) (#623)
* added support for attachments in the cucumber json and events output formats - done by sneaking the attachment into the context.Context object.
2024-05-29 00:02:08 +01:00
Viacheslav Poturaev
4ade3314e8
Update CI and Makefile (#619) 2024-05-02 14:51:52 +02:00
renovate[bot]
c3756d1aa2
fix(deps): update module github.com/cucumber/godog to v0.14.1 (#618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-30 14:31:36 +00:00
127 изменённых файлов: 4679 добавлений и 840 удалений

5
.github/workflows/gorelease.yml предоставленный
Просмотреть файл

@ -9,13 +9,12 @@ concurrency:
cancel-in-progress: true
env:
GO_VERSION: 1.19.x
GO_VERSION: stable
jobs:
gorelease:
runs-on: ubuntu-latest
steps:
- name: Install Go stable
if: env.GO_VERSION != 'tip'
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
@ -34,7 +33,7 @@ jobs:
OUTPUT=$(gorelease 2>&1 || exit 0)
echo "${OUTPUT}"
OUTPUT="${OUTPUT//$'\n'/%0A}"
echo "::set-output name=report::$OUTPUT"
echo "report=$OUTPUT" >> $GITHUB_OUTPUT
- name: Comment Report
continue-on-error: true
uses: marocchino/sticky-pull-request-comment@v2

2
.github/workflows/release-assets.yml предоставленный
Просмотреть файл

@ -15,7 +15,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.20.x
go-version: stable
- name: Checkout code
uses: actions/checkout@v4
- name: Build artifacts

8
.github/workflows/test.yml предоставленный
Просмотреть файл

@ -8,7 +8,7 @@ jobs:
test:
strategy:
matrix:
go-version: [ 1.16.x, 1.17.x, 1.19.x, 1.20.x, 1.21.x ] # Lowest supported and current stable versions.
go-version: [ 1.16.x, 1.17.x, oldstable, stable ] # Lowest supported and current stable versions.
runs-on: ubuntu-latest
steps:
- name: Install Go
@ -29,10 +29,10 @@ jobs:
- name: Run gofmt
run: gofmt -d -e . 2>&1 | tee outfile && test -z "$(cat outfile)" && rm outfile
- name: Run staticcheck
if: matrix.go-version == '1.20.x'
if: matrix.go-version == 'stable'
uses: dominikh/staticcheck-action@v1.3.1
with:
version: "2023.1.3"
version: "latest"
install-go: false
cache-key: ${{ matrix.go }}
@ -49,7 +49,7 @@ jobs:
go install ./cmd/godog
godog -f progress --strict
- name: Report on code coverage
if: matrix.go-version == '1.17.x'
if: matrix.go-version == 'stable'
uses: codecov/codecov-action@v4
with:
file: ./coverage.txt

2
.gitignore предоставленный
Просмотреть файл

@ -9,3 +9,5 @@ Gopkg.toml
.vscode
_artifacts
vendor

Просмотреть файл

@ -8,6 +8,26 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt
## Unreleased
### Added
- Step text is added to "step is undefined" error - ([669](https://github.com/cucumber/godog/pull/669) - [vearutop](https://github.com/vearutop))
### Changed
- Replace deprecated `::set-output` - ([681](https://github.com/cucumber/godog/pull/681) - [nodeg](https://github.com/nodeg))
### Fixed
- fix(errors): fix(errors): Fix expected Step argument count for steps with `context.Context` ([679](https://github.com/cucumber/godog/pull/679) - [tigh-latte](https://github.com/tigh-latte))
- fix(formatter): On concurrent execution, execute formatter at end of Scenario - ([645](https://github.com/cucumber/godog/pull/645) - [tigh-latte](https://github.com/tigh-latte))
## [v0.15.0]
### Added
- Improved the type checking of step return types and improved the error messages - ([647](https://github.com/cucumber/godog/pull/647) - [johnlon](https://github.com/johnlon))
- Ambiguous step definitions will now be detected when strict mode is activated - ([636](https://github.com/cucumber/godog/pull/636)/([648](https://github.com/cucumber/godog/pull/648) - [johnlon](https://github.com/johnlon))
- Provide support for attachments / embeddings including a new example in the examples dir - ([623](https://github.com/cucumber/godog/pull/623) - [johnlon](https://github.com/johnlon))
### Changed
- Formatters now have a `Close` method and associated `io.Writer` changed to `io.WriteCloser`.
## [v0.14.1]
### Added
@ -231,6 +251,7 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt
### Changed
- Changed code references to DATA-DOG/godog to cucumber/godog to help get things building correctly. ([mxygem](https://github.com/mxygem))
[v0.15.0]: https://github.com/cucumber/godog/compare/v0.14.1...v0.15.0
[v0.14.1]: https://github.com/cucumber/godog/compare/v0.14.0...v0.14.1
[v0.14.0]: https://github.com/cucumber/godog/compare/v0.13.0...v0.14.0
[v0.13.0]: https://github.com/cucumber/godog/compare/v0.12.6...v0.13.0

Просмотреть файл

@ -7,7 +7,7 @@ to give you a grounding in some of the basic concepts. You could also watch [thi
We want you to feel safe to make mistakes, and ask questions. If anything in this guide or anywhere else in the codebase doesn't make sense to you, please let us know! It's through your feedback that we can make this codebase more welcoming, so we'll be glad to hear thoughts.
You can chat with us in the [#committers-go](https://cucumberbdd.slack.com/archives/CA5NJPDJ4) channel in our [community Slack], or feel free to [raise an issue] if you're experiencing any friction trying make your contribution.
You can chat with us in the `#committers` channel in our [community Discord](https://cucumber.io/docs/community/get-in-touch/#discord), or feel free to [raise an issue] if you're experiencing any friction trying make your contribution.
## Setup
@ -20,7 +20,7 @@ Once that's done, try running the tests:
If everything passes, you're ready to hack!
[install go]: https://golang.org/doc/install
[community Slack]: https://cucumber.io/community#slack
[community Discord]: https://cucumber.io/community#discord
[raise an issue]: https://github.com/cucumber/godog/issues/new/choose
## Changing dependencies

138
Magefile.go Обычный файл
Просмотреть файл

@ -0,0 +1,138 @@
//go:build mage
// +build mage
package main
import (
// mage:import
. "magefile/docker"
)
var (
GolangVolume = "golang.upstream"
)
func init() {
AppName = "godog"
ImageName = "my/go"
}
func Test() {
TestNative()
}
func TestNative() {
Bash(`sudo docker run -ti --rm \
-h host \
--net=bridge \
-v /etc/localtime:/etc/localtime:ro \
-v ` + GolangVolume + `:/usr/local/go:ro \
\
-v /gopath:/gopath:rw \
-v ${PWD}:/app \
\
-e GOPATH=/gopath \
-e GOCACHE=/gopath/gocache \
\
-w /app \
-u 1000 \
\
--entrypoint=/bin/bash \
\
` + ImageName + " -c '" + `\
go test -race -count=1 ./... \
'`)
}
func TestMakefile() {
Bash(`sudo docker run -ti --rm \
-h host \
--net=bridge \
-v /etc/localtime:/etc/localtime:ro \
-v ` + GolangVolume + `:/usr/local/go:ro \
\
-v /gopath:/gopath:rw \
-v ${PWD}:/app \
\
-e GOPATH=/gopath \
-e GOCACHE=/gopath/gocache \
\
-w /app \
-u 1000 \
\
--entrypoint=/bin/bash \
\
` + ImageName + " -c '" + `set -x; \
make test \
'`)
}
func TestSnippets() {
Bash(`sudo docker run -ti --rm \
-h host \
--net=bridge \
-v /etc/localtime:/etc/localtime:ro \
-v ` + GolangVolume + `:/usr/local/go:ro \
\
-v /gopath:/gopath:rw \
-v ${PWD}:/app \
\
-e GOPATH=/gopath \
-e GOCACHE=/gopath/gocache \
\
-w /app \
-u 1000 \
\
--entrypoint=/bin/bash \
\
` + ImageName + " -c '" + `set -x; \
godog run -f progress -c 4 \
features/snippets.feature \
'`)
}
func TestTags() {
Bash(`sudo docker run -ti --rm \
-h host \
--net=bridge \
-v /etc/localtime:/etc/localtime:ro \
-v ` + GolangVolume + `:/usr/local/go:ro \
\
-v /gopath:/gopath:rw \
-v ${PWD}:/app \
\
-e GOPATH=/gopath \
-e GOCACHE=/gopath/gocache \
\
-w /app \
-u 1000 \
\
--entrypoint=/bin/bash \
\
` + ImageName + " -c '" + `set -x; \
godog run -f progress -c 4 \
features/tags.feature \
'`)
}
func Install() {
Bash(`sudo docker run -ti --rm \
-h host \
--net=bridge \
-v /etc/localtime:/etc/localtime:ro \
-v ` + GolangVolume + `:/usr/local/go:ro \
\
-v /gopath:/gopath:rw \
-v ${PWD}:/app \
\
-e GOPATH=/gopath \
-e GOCACHE=/gopath/gocache \
\
-w /app \
-u 1000 \
\
--entrypoint=/bin/bash \
\
` + ImageName + " -c '" + `set -x; \
go install ./cmd/godog \
'`)
}

Просмотреть файл

@ -2,21 +2,32 @@
VERS ?= $(shell git symbolic-ref -q --short HEAD || git describe --tags --exact-match)
FOUND_GO_VERSION := $(shell go version)
EXPECTED_GO_VERSION = 1.17
GO_MAJOR_VERSION = $(shell go version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
GO_MINOR_VERSION = $(shell go version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
MINIMUM_SUPPORTED_GO_MAJOR_VERSION = 1
MINIMUM_SUPPORTED_GO_MINOR_VERSION = 16
GO_VERSION_VALIDATION_ERR_MSG = Go version $(GO_MAJOR_VERSION).$(GO_MINOR_VERSION) is not supported, please update to at least $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION).$(MINIMUM_SUPPORTED_GO_MINOR_VERSION)
.PHONY: check-go-version
check-go-version:
@$(if $(findstring ${EXPECTED_GO_VERSION}, ${FOUND_GO_VERSION}),(exit 0),(echo Wrong go version! Please install ${EXPECTED_GO_VERSION}; exit 1))
@if [ $(GO_MAJOR_VERSION) -gt $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION) ]; then \
exit 0 ;\
elif [ $(GO_MAJOR_VERSION) -lt $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION) ]; then \
echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\
exit 1; \
elif [ $(GO_MINOR_VERSION) -lt $(MINIMUM_SUPPORTED_GO_MINOR_VERSION) ] ; then \
echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\
exit 1; \
fi
test: check-go-version
@echo "running all tests"
@go install ./...
@go fmt ./...
@go run honnef.co/go/tools/cmd/staticcheck@v0.2.2 github.com/cucumber/godog
@go run honnef.co/go/tools/cmd/staticcheck@v0.2.2 github.com/cucumber/godog/cmd/godog
@go run honnef.co/go/tools/cmd/staticcheck@v0.5.1 git.golang1.ru/softonik/godog
@go run honnef.co/go/tools/cmd/staticcheck@v0.5.1 git.golang1.ru/softonik/godog/cmd/godog
go vet ./...
go test -race ./...
godog -f progress -c 4
go run ./cmd/godog -f progress -c 4
gherkin:
@if [ -z "$(VERS)" ]; then echo "Provide gherkin version like: 'VERS=commit-hash'"; exit 1; fi
@ -58,7 +69,7 @@ artifacts:
define _build
mkdir $(ARTIFACT_DIR)/godog-$(VERS)-$1-$2
env GOOS=$1 GOARCH=$2 go build -ldflags "-X github.com/cucumber/godog.Version=$(VERS)" -o $(ARTIFACT_DIR)/godog-$(VERS)-$1-$2/godog ./cmd/godog
env GOOS=$1 GOARCH=$2 go build -ldflags "-X git.golang1.ru/softonik/godog.Version=$(VERS)" -o $(ARTIFACT_DIR)/godog-$(VERS)-$1-$2/godog ./cmd/godog
cp README.md $(ARTIFACT_DIR)/godog-$(VERS)-$1-$2/README.md
cp LICENSE $(ARTIFACT_DIR)/godog-$(VERS)-$1-$2/LICENSE
cd $(ARTIFACT_DIR) && tar -c --use-compress-program="pigz --fast" -f godog-$(VERS)-$1-$2.tar.gz godog-$(VERS)-$1-$2 && cd ..

Просмотреть файл

@ -1,4 +1,3 @@
[![#StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://vshymanskyy.github.io/StandWithUkraine)
[![Build Status](https://github.com/cucumber/godog/workflows/test/badge.svg)](https://github.com/cucumber/godog/actions?query=branch%main+workflow%3Atest)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/cucumber/godog)](https://pkg.go.dev/github.com/cucumber/godog)
[![codecov](https://codecov.io/gh/cucumber/godog/branch/master/graph/badge.svg)](https://codecov.io/gh/cucumber/godog)
@ -50,13 +49,7 @@ See the [releasing guide] for release flow details.
## Getting help
We have a [community Slack] where you can chat with other users, developers, and BDD practitioners.
Here are some useful channels to try:
- [#help-godog](https://cucumberbdd.slack.com/archives/CTNL1JCVA) - General Godog Adoption Help
- [#committers-go](https://cucumberbdd.slack.com/archives/CA5NJPDJ4) - Golang focused Cucumber Contributors
- [#committers](https://cucumberbdd.slack.com/archives/C62D0FK0E) - General Cucumber Contributors
We have a [community Discord](https://cucumber.io/docs/community/get-in-touch/#discord) where you can chat with other users, developers, and BDD practitioners.
## Examples
@ -292,6 +285,10 @@ When steps are orthogonal and small, you can combine them just like you do with
`TestFeatures` acts as a regular Go test, so you can leverage your IDE facilities to run and debug it.
### Attachments
An example showing how to make attachments (aka embeddings) to the results is shown in [_examples/attachments](/_examples/attachments/)
## Code of Conduct
Everyone interacting in this codebase and issue tracker is expected to follow the Cucumber [code of conduct](https://github.com/cucumber/cucumber/blob/master/CODE_OF_CONDUCT.md).
@ -579,4 +576,7 @@ A simple example can be [found here](/_examples/custom-formatter).
[license]: https://en.wikipedia.org/wiki/MIT_License "The MIT license"
[contributing guide]: https://github.com/cucumber/godog/blob/main/CONTRIBUTING.md
[releasing guide]: https://github.com/cucumber/godog/blob/main/RELEASING.md
[community Slack]: https://cucumber.io/community#slack
[community Discord]: https://cucumber.io/community#discord

Просмотреть файл

@ -42,7 +42,7 @@ Cucumber Godog follows [Semantic Versioning]. Version numbers are in the format
- Click "Publish release" to make the release public.
6. **Announce the Release:**
- Make an announcement on relevant communication channels (e.g., [community Slack]) about the new release.
- Make an announcement on relevant communication channels (e.g., [community Discord]) about the new release.
## Additional Considerations
@ -60,7 +60,7 @@ Cucumber Godog follows [Semantic Versioning]. Version numbers are in the format
Following these guidelines, including manual testing with external libraries, will help ensure a thorough release process for Cucumber Godog, allowing detection and resolution of potential backwards compatibility issues before tagging the release.
[community Slack]: https://cucumber.io/community#slack
[community Discord]: https://cucumber.io/community#discord
[website]: https://cucumber.github.io/godog/
[Releases]: https://github.com/cucumber/godog/releases
[Semantic Versioning]: http://semver.org

Просмотреть файл

@ -44,7 +44,7 @@ Now we have described a success case and an error when the request method is not
Execute `godog run`. You should see the following result, which says that all of our
steps are yet undefined and provide us with the snippets to implement them.
![Screenshot](https://raw.github.com/cucumber/godog/master/_examples/api/screenshots/undefined.png)
![Screenshot](https://raw.git.golang1.ru/softonik/godog/master/_examples/api/screenshots/undefined.png)
### Step 3
@ -56,7 +56,7 @@ need to store state within steps (a response), we should introduce a structure w
package main
import (
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
type apiFeature struct {
@ -114,7 +114,7 @@ import (
"reflect"
"testing"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
type apiFeature struct {
@ -228,7 +228,7 @@ import (
"encoding/json"
"net/http"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func getVersion(w http.ResponseWriter, r *http.Request) {
@ -282,7 +282,7 @@ used to respond with the correct constant version number.
Run our tests to see whether everything is happening as we have expected: `go test -v`
![Screenshot](https://raw.github.com/cucumber/godog/master/_examples/api/screenshots/passed.png)
![Screenshot](https://raw.git.golang1.ru/softonik/godog/master/_examples/api/screenshots/passed.png)
### Conclusions

Просмотреть файл

@ -5,7 +5,7 @@ import (
"encoding/json"
"net/http"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func getVersion(w http.ResponseWriter, r *http.Request) {

Просмотреть файл

@ -9,7 +9,7 @@ import (
"reflect"
"testing"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
type apiFeature struct {

Просмотреть файл

@ -5,8 +5,8 @@ import (
"os"
"testing"
"github.com/cucumber/godog"
"github.com/cucumber/godog/colors"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/colors"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)

16
_examples/attachments/README.md Обычный файл
Просмотреть файл

@ -0,0 +1,16 @@
# An example of Making attachments to the reports
The JSON (and in future NDJSON) report formats allow the inclusion of data attachments.
These attachments could be console logs or file data or images for instance.
The example in this directory shows how the godog API is used to add attachments to the JSON report.
## Run the example
You must use the '-v' flag or you will not see the cucumber JSON output.
go test -v attachments_test.go

89
_examples/attachments/attachments_test.go Обычный файл
Просмотреть файл

@ -0,0 +1,89 @@
package attachments_test
// This "demo" doesn't actually get run as a test by the build.
// This "example" shows how to attach data to the cucumber reports
// Run the sample with : go test -v attachments_test.go
// Then review the "embeddings" within the JSON emitted on the console.
import (
"context"
"os"
"testing"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/colors"
)
var opts = godog.Options{
Output: colors.Colored(os.Stdout),
Format: "cucumber", // cucumber json format
}
func TestFeatures(t *testing.T) {
o := opts
o.TestingT = t
status := godog.TestSuite{
Name: "attachments",
Options: &o,
ScenarioInitializer: InitializeScenario,
}.Run()
if status == 2 {
t.SkipNow()
}
if status != 0 {
t.Fatalf("zero status code expected, %d received", status)
}
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("BeforeScenarioAttachment"), FileName: "Step Attachment 1", MediaType: "text/plain"},
)
return ctx, nil
})
ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("AfterScenarioAttachment"), FileName: "Step Attachment 2", MediaType: "text/plain"},
)
return ctx, nil
})
ctx.StepContext().Before(func(ctx context.Context, st *godog.Step) (context.Context, error) {
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("BeforeStepAttachment"), FileName: "Step Attachment 3", MediaType: "text/plain"},
)
return ctx, nil
})
ctx.StepContext().After(func(ctx context.Context, st *godog.Step, status godog.StepResultStatus, err error) (context.Context, error) {
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("AfterStepAttachment"), FileName: "Step Attachment 4", MediaType: "text/plain"},
)
return ctx, nil
})
ctx.Step(`^I have attached two documents in sequence$`, func(ctx context.Context) (context.Context, error) {
// the attached bytes will be base64 encoded by the framework and placed in the embeddings section of the cuke report
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("TheData1"), FileName: "Step Attachment 5", MediaType: "text/plain"},
)
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("{ \"a\" : 1 }"), FileName: "Step Attachment 6", MediaType: "application/json"},
)
return ctx, nil
})
ctx.Step(`^I have attached two documents at once$`, func(ctx context.Context) (context.Context, error) {
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("TheData1"), FileName: "Step Attachment 7", MediaType: "text/plain"},
godog.Attachment{Body: []byte("TheData2"), FileName: "Step Attachment 8", MediaType: "text/plain"},
)
return ctx, nil
})
}

Просмотреть файл

@ -0,0 +1,7 @@
Feature: Attaching content to the cucumber report
The cucumber JSON and NDJSON support the inclusion of attachments.
These can be text or images or any data really.
Scenario: Attaching files to the report
Given I have attached two documents in sequence
And I have attached two documents at once

Просмотреть файл

@ -5,7 +5,7 @@ import (
"io"
"math"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
const (

Просмотреть файл

@ -6,8 +6,8 @@ import (
"os"
"testing"
"github.com/cucumber/godog"
"github.com/cucumber/godog/colors"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/colors"
flag "github.com/spf13/pflag"
)

Просмотреть файл

@ -1,7 +1,7 @@
# An example of API with DB
The following example demonstrates steps how we describe and test our API with DB using **godog**.
To start with, see [API example](https://github.com/cucumber/godog/tree/master/_examples/api) before.
To start with, see [API example](https://git.golang1.ru/softonik/godog/tree/master/_examples/api) before.
We have extended it to be used with database.
The interesting point is, that we have [go-txdb](https://github.com/DATA-DOG/go-txdb) library,

Просмотреть файл

@ -11,7 +11,7 @@ import (
"strings"
txdb "github.com/DATA-DOG/go-txdb"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func init() {

Просмотреть файл

@ -1,14 +1,14 @@
module github.com/cucumber/godog/_examples
module git.golang1.ru/softonik/godog/_examples
go 1.16
replace github.com/cucumber/godog => ../
replace git.golang1.ru/softonik/godog => ../
require (
github.com/DATA-DOG/go-txdb v0.1.6
github.com/cucumber/godog v0.14.0
git.golang1.ru/softonik/godog v0.15.0
github.com/go-sql-driver/mysql v1.7.1
github.com/spf13/pflag v1.0.5
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.8.2
)

Просмотреть файл

@ -45,6 +45,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

Просмотреть файл

@ -15,12 +15,12 @@ import (
"context"
"flag"
"fmt"
"github.com/cucumber/godog/_examples/godogs"
"git.golang1.ru/softonik/godog/_examples/godogs"
"os"
"testing"
"github.com/cucumber/godog"
"github.com/cucumber/godog/colors"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/colors"
)
var opts = godog.Options{

Просмотреть файл

@ -1,4 +1,4 @@
This example is to help reproduce issue [#383](https://github.com/cucumber/godog/issues/383)
This example is to help reproduce issue [#383](https://git.golang1.ru/softonik/godog/issues/383)
To run the example:

Просмотреть файл

@ -2,6 +2,6 @@ module incorrect-project-structure
go 1.13
require github.com/cucumber/godog v0.14.0
require git.golang1.ru/softonik/godog v0.15.0
replace github.com/cucumber/godog => ../../
replace git.golang1.ru/softonik/godog => ../../

Просмотреть файл

@ -1,6 +1,6 @@
package main
import "github.com/cucumber/godog"
import "git.golang1.ru/softonik/godog"
func InitializeScenario(ctx *godog.ScenarioContext) {

28
attachment_test.go Обычный файл
Просмотреть файл

@ -0,0 +1,28 @@
package godog
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func TestAttach(t *testing.T) {
ctx := context.Background()
ctx = Attach(ctx, Attachment{Body: []byte("body1"), FileName: "fileName1", MediaType: "mediaType1"})
ctx = Attach(ctx, Attachment{Body: []byte("body2"), FileName: "fileName2", MediaType: "mediaType2"})
attachments := Attachments(ctx)
assert.Equal(t, 2, len(attachments))
assert.Equal(t, []byte("body1"), attachments[0].Body)
assert.Equal(t, "fileName1", attachments[0].FileName)
assert.Equal(t, "mediaType1", attachments[0].MediaType)
assert.Equal(t, []byte("body2"), attachments[1].Body)
assert.Equal(t, "fileName2", attachments[1].FileName)
assert.Equal(t, "mediaType2", attachments[1].MediaType)
}

Просмотреть файл

@ -5,8 +5,8 @@ import (
"go/build"
"path/filepath"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/builder"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/builder"
"github.com/spf13/cobra"
)
@ -40,7 +40,7 @@ The test runner can be executed with the same flags as when using godog run.`,
func buildCmdRunFunc(cmd *cobra.Command, args []string) error {
fmt.Println(colors.Yellow("Use of godog CLI is deprecated, please use *testing.T instead."))
fmt.Println(colors.Yellow("See https://github.com/cucumber/godog/discussions/478 for details."))
fmt.Println(colors.Yellow("See https://git.golang1.ru/softonik/godog/discussions/478 for details."))
bin, err := filepath.Abs(buildOutput)
if err != nil {

Просмотреть файл

@ -4,7 +4,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/cucumber/godog/internal/flags"
"git.golang1.ru/softonik/godog/internal/flags"
)
var version bool

Просмотреть файл

@ -9,9 +9,9 @@ import (
"github.com/spf13/cobra"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/builder"
"github.com/cucumber/godog/internal/flags"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/builder"
"git.golang1.ru/softonik/godog/internal/flags"
)
var opts flags.Options
@ -44,7 +44,7 @@ buildable go source.`,
func runCmdRunFunc(cmd *cobra.Command, args []string) error {
fmt.Println(colors.Yellow("Use of godog CLI is deprecated, please use *testing.T instead."))
fmt.Println(colors.Yellow("See https://github.com/cucumber/godog/discussions/478 for details."))
fmt.Println(colors.Yellow("See https://git.golang1.ru/softonik/godog/discussions/478 for details."))
osArgs := os.Args[1:]

Просмотреть файл

@ -6,7 +6,7 @@ import (
"github.com/spf13/cobra"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
// CreateVersionCmd creates the version subcommand.

Просмотреть файл

@ -4,7 +4,7 @@ import (
"fmt"
"os"
"github.com/cucumber/godog/cmd/godog/internal"
"git.golang1.ru/softonik/godog/cmd/godog/internal"
)
func main() {

Просмотреть файл

@ -3,7 +3,7 @@ package godog_test
import (
"testing"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func ExampleTestSuite_Run_subtests() {

Просмотреть файл

@ -153,3 +153,43 @@ Feature: undefined step snippets
ctx.Step(`^"([^"]*)", which costs £(\d+)$`, whichCosts)
}
"""
Scenario: Для русских сценариев генерируются русские функции
Given a feature "undefined.feature" file:
"""
# language: ru
Функционал: суперфича
Сценарий: делает что-то полезное
Дано что-то
Когда я делаю ещё что-то
То получается ещё более что-то
"""
When I run feature suite
Then the following steps should be undefined:
"""
получается ещё более что-то
что-то
я делаю ещё что-то
"""
And the undefined step snippets should be:
"""
func получаетсяЕщёБолееЧтото() error {
return godog.ErrPending
}
func чтото() error {
return godog.ErrPending
}
func яДелаюЕщёЧтото() error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^получается ещё более что-то$`, получаетсяЕщёБолееЧтото)
ctx.Step(`^что-то$`, чтото)
ctx.Step(`^я делаю ещё что-то$`, яДелаюЕщёЧтото)
}
"""

Просмотреть файл

@ -125,3 +125,75 @@ Feature: tag filters
"""
a feature path "four"
"""
Scenario: empty filter and scenarios with f-tag - are executed only
Given a feature "normal.feature" file:
"""
Feature: f-tagged
Scenario: one
Given a feature path "one"
Scenario: two
Given a feature path "two"
@f
Scenario: three
Given a feature path "three"
@f
Scenario: four
Given a feature path "four"
"""
When I run feature suite with tags ""
Then the suite should have passed
And I should have 2 scenario registered
And the following steps should be passed:
"""
a feature path "three"
a feature path "four"
"""
Scenario: two feature files and scenarios with f-tag - are executed only
Given a feature "normal.feature" file:
"""
Feature: f-tagged
Scenario: one
Given a feature path "one"
Scenario: two
Given a feature path "two"
@f
Scenario: three
Given a feature path "three"
@f
Scenario: four
Given a feature path "four"
"""
And a feature "another.feature" file:
"""
Feature: non-tagged
Scenario: five
Given a feature path "five"
Scenario: six
Given a feature path "six"
Scenario: seven
Given a feature path "seven"
Scenario: eight
Given a feature path "eight"
"""
When I run feature suite with tags ""
Then the suite should have passed
And I should have 2 scenario registered
And the following steps should be passed:
"""
a feature path "three"
a feature path "four"
"""

Просмотреть файл

@ -8,8 +8,8 @@ import (
"strconv"
"strings"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/utils"
)
// repeats a space n times
@ -121,7 +121,7 @@ func BindFlags(prefix string, set *flag.FlagSet, opt *Options) {
set.BoolVar(&opt.ShowStepDefinitions, prefix+"definitions", defShowStepDefinitions, "Print all available step definitions.")
set.BoolVar(&opt.ShowStepDefinitions, prefix+"d", defShowStepDefinitions, "Print all available step definitions.")
set.BoolVar(&opt.StopOnFailure, prefix+"stop-on-failure", defStopOnFailure, "Stop processing on first failed scenario.")
set.BoolVar(&opt.Strict, prefix+"strict", defStrict, "Fail suite when there are pending or undefined steps.")
set.BoolVar(&opt.Strict, prefix+"strict", defStrict, "Fail suite when there are pending or undefined or ambiguous steps.")
set.BoolVar(&opt.NoColors, prefix+"no-colors", defNoColors, "Disable ansi colors.")
set.Var(&randomSeed{&opt.Randomize}, prefix+"random", descRandomOption)
set.BoolVar(&opt.ShowHelp, "godog.help", false, "Show usage help.")
@ -208,7 +208,7 @@ func usage(set *flag.FlagSet, w io.Writer) func() {
// --- GENERAL ---
fmt.Fprintln(w, colors.Yellow("Usage:"))
fmt.Fprintf(w, s(2)+"go test [options]\n\n")
fmt.Fprint(w, s(2)+"go test [options]\n\n")
// --- OPTIONS ---
fmt.Fprintln(w, colors.Yellow("Options:"))

Просмотреть файл

@ -7,8 +7,8 @@ import (
"strings"
"testing"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/formatters"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/formatters"
)
func TestFlagsShouldRandomizeAndGenerateSeed(t *testing.T) {

Просмотреть файл

@ -8,7 +8,7 @@ import (
"github.com/spf13/pflag"
"github.com/cucumber/godog/internal/flags"
"git.golang1.ru/softonik/godog/internal/flags"
)
// Choose randomly assigns a convenient pseudo-random seed value.

Просмотреть файл

@ -3,7 +3,7 @@ package godog
import (
"testing"
"github.com/cucumber/godog/internal/flags"
"git.golang1.ru/softonik/godog/internal/flags"
"github.com/stretchr/testify/assert"
)

10
fmt.go
Просмотреть файл

@ -6,11 +6,11 @@ import (
"strings"
"unicode/utf8"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/formatters"
internal_fmt "github.com/cucumber/godog/internal/formatters"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/storage"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/formatters"
internal_fmt "git.golang1.ru/softonik/godog/internal/formatters"
"git.golang1.ru/softonik/godog/internal/models"
"git.golang1.ru/softonik/godog/internal/storage"
)
// FindFmt searches available formatters registered

Просмотреть файл

@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func Test_FindFmt(t *testing.T) {

Просмотреть файл

@ -70,9 +70,16 @@ type Formatter interface {
Skipped(*messages.Pickle, *messages.PickleStep, *StepDefinition)
Undefined(*messages.Pickle, *messages.PickleStep, *StepDefinition)
Pending(*messages.Pickle, *messages.PickleStep, *StepDefinition)
Ambiguous(*messages.Pickle, *messages.PickleStep, *StepDefinition, error)
Summary()
}
// FlushFormatter is a `Formatter` but can be flushed.
type FlushFormatter interface {
Formatter
Flush()
}
// FormatterFunc builds a formatter with given
// suite name and io.Writer to record output
type FormatterFunc func(string, io.Writer) Formatter

Просмотреть файл

@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func Test_FindFmt(t *testing.T) {

24
go.mod
Просмотреть файл

@ -1,13 +1,27 @@
module github.com/cucumber/godog
module git.golang1.ru/softonik/godog
go 1.16
go 1.24.2
require (
git.golang1.ru/softonik/godog_and_gomega v1.0.0
github.com/cucumber/gherkin/go/v26 v26.2.0
github.com/hashicorp/go-memdb v1.3.4
github.com/hashicorp/go-memdb v1.3.5
github.com/onsi/gomega v1.37.0
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.2
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/text v0.25.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (

51
go.sum
Просмотреть файл

@ -1,26 +1,33 @@
git.golang1.ru/softonik/godog_and_gomega v1.0.0 h1:2BhCJnuCW5mnRRFk7hN0thyz6Zj64udGhjVtVrjvmYQ=
git.golang1.ru/softonik/godog_and_gomega v1.0.0/go.mod h1:Xf4wTfJZU3W8dULgIkyou+dd36zZ8Kw2FPD3cr3dR10=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI=
github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0=
github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI=
github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s=
github.com/cucumber/messages/go/v22 v22.0.0/go.mod h1:aZipXTKc0JnjCsXrJnuZpWhtay93k7Rn3Dee7iyPJjs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI=
github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c=
github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg=
github.com/hashicorp/go-memdb v1.3.5 h1:b3taDMxCBCBVgyRrS1AZVHO14ubMYZB++QpNhBg+Nyo=
github.com/hashicorp/go-memdb v1.3.5/go.mod h1:8IVKKBkVe+fxFgdFOYxzQQNjz+sWCyHCdIC/+5+Vy1Y=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
@ -28,24 +35,30 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0=
github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

Просмотреть файл

@ -9,7 +9,7 @@ import (
var astContextSrc = `package main
import (
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func MyContext(s *godog.Suite) {
@ -18,7 +18,7 @@ func MyContext(s *godog.Suite) {
var astTwoContextSrc = `package lib
import (
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func ApiContext(s *godog.Suite) {

Просмотреть файл

@ -23,13 +23,13 @@ var (
compiler = filepath.Join(tooldir, "compile")
linker = filepath.Join(tooldir, "link")
gopaths = filepath.SplitList(build.Default.GOPATH)
godogImportPath = "github.com/cucumber/godog"
godogImportPath = "git.golang1.ru/softonik/godog"
// godep
runnerTemplate = template.Must(template.New("testmain").Parse(`package main
import (
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
{{if or .TestSuiteContexts .ScenarioContexts}}_test "{{.ImportPath}}"{{end}}
{{if or .XTestSuiteContexts .XScenarioContexts}}_xtest "{{.ImportPath}}_test"{{end}}
{{if or .XTestSuiteContexts .XScenarioContexts}}"testing/internal/testdeps"{{end}}
@ -70,7 +70,7 @@ func main() {
// temp file for import
tempFileTemplate = template.Must(template.New("temp").Parse(`package {{.Name}}
import "github.com/cucumber/godog"
import "git.golang1.ru/softonik/godog"
var _ = godog.Version
`))

Просмотреть файл

@ -12,8 +12,8 @@ import (
"github.com/stretchr/testify/require"
"github.com/cucumber/godog"
"github.com/cucumber/godog/internal/builder"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/internal/builder"
)
func InitializeScenario(ctx *godog.ScenarioContext) {}
@ -51,7 +51,7 @@ var builderTestFile = `package godogs
import (
"fmt"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
func thereAreGodogs(available int) error {
@ -91,7 +91,7 @@ var builderXTestFile = `package godogs_test
import (
"fmt"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
"godogs"
)
@ -138,7 +138,7 @@ func main() {
var emptyBuilderTestFile = `package godogs
import "github.com/cucumber/godog"
import "git.golang1.ru/softonik/godog"
func InitializeScenario(ctx *godog.ScenarioContext) {}
`

Просмотреть файл

@ -39,7 +39,7 @@ built-in formatters are:
flagSet.BoolVarP(&opts.ShowStepDefinitions, prefix+"definitions", "d", opts.ShowStepDefinitions, "print all available step definitions")
flagSet.BoolVar(&opts.StopOnFailure, prefix+"stop-on-failure", opts.StopOnFailure, "stop processing on first failed scenario")
flagSet.BoolVar(&opts.Strict, prefix+"strict", opts.Strict, "fail suite when there are pending or undefined steps")
flagSet.BoolVar(&opts.Strict, prefix+"strict", opts.Strict, "fail suite when there are pending or undefined or ambiguous steps")
flagSet.Int64Var(&opts.Randomize, prefix+"random", opts.Randomize, `randomly shuffle the scenario execution order
--random

Просмотреть файл

@ -6,7 +6,7 @@ import (
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/cucumber/godog/internal/flags"
"git.golang1.ru/softonik/godog/internal/flags"
)
func Test_BindFlagsShouldRespectFlagDefaults(t *testing.T) {

Просмотреть файл

@ -38,7 +38,7 @@ type Options struct {
// Stops on the first failure
StopOnFailure bool
// Fail suite when there are pending or undefined steps
// Fail suite when there are pending or undefined or ambiguous steps
Strict bool
// Forces ansi color stripping
@ -48,6 +48,9 @@ type Options struct {
// from feature files
Tags string
// Dialect to be used to parse feature files. If not set, default to "en".
Dialect string
// The formatter name
Format string

Просмотреть файл

@ -11,9 +11,9 @@ import (
messages "github.com/cucumber/messages/go/v21"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/models"
"git.golang1.ru/softonik/godog/internal/utils"
)
var (
@ -36,6 +36,7 @@ var (
skipped = models.Skipped
undefined = models.Undefined
pending = models.Pending
ambiguous = models.Ambiguous
)
type sortFeaturesByName []*models.Feature

680
internal/formatters/fmt_ast.go Обычный файл
Просмотреть файл

@ -0,0 +1,680 @@
package formatters
import (
"bytes"
"fmt"
"io"
"os"
"sort"
"strconv"
"strings"
"text/template"
"unicode"
"unicode/utf8"
messages "github.com/cucumber/messages/go/v21"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/models"
"git.golang1.ru/softonik/godog/internal/utils"
"git.golang1.ru/softonik/godog/pkg/formatters/ast"
)
func ASTRegister() {
formatters.Format("ast", "Prints every feature with runtime statuses + updates ast.", ASTFormatterFunc)
}
// ASTFormatterFunc implements the FormatterFunc for the AST formatter
func ASTFormatterFunc(suite string, out io.Writer) formatters.Formatter {
return &AST{Base: NewBase(suite, out)}
}
// AST is a formatter for readable output.
type AST struct {
*Base
firstFeature *bool
}
// TestRunStarted is triggered on test start.
func (f *AST) TestRunStarted() {
f.Base.TestRunStarted()
f.Lock.Lock()
defer f.Lock.Unlock()
firstFeature := true
f.firstFeature = &firstFeature
}
// Feature receives gherkin document.
func (f *AST) Feature(gd *messages.GherkinDocument, p string, c []byte) {
f.Lock.Lock()
if !*f.firstFeature {
fmt.Fprintln(f.out, "")
}
*f.firstFeature = false
f.Lock.Unlock()
f.Base.Feature(gd, p, c)
f.Lock.Lock()
defer f.Lock.Unlock()
f.printFeature(gd.Feature)
}
// Pickle takes a gherkin node for formatting.
func (f *AST) Pickle(pickle *messages.Pickle) {
f.Base.Pickle(pickle)
f.Lock.Lock()
defer f.Lock.Unlock()
if len(pickle.Steps) == 0 {
f.printUndefinedPickle(pickle)
return
}
}
// Passed captures passed step.
func (f *AST) Passed(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition) {
f.Base.Passed(pickle, step, match)
f.Lock.Lock()
defer f.Lock.Unlock()
f.printStep(pickle, step)
}
// Skipped captures skipped step.
func (f *AST) Skipped(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition) {
f.Base.Skipped(pickle, step, match)
f.Lock.Lock()
defer f.Lock.Unlock()
f.printStep(pickle, step)
}
// Undefined captures undefined step.
func (f *AST) Undefined(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition) {
f.Base.Undefined(pickle, step, match)
f.Lock.Lock()
defer f.Lock.Unlock()
f.printStep(pickle, step)
}
// Failed captures failed step.
func (f *AST) Failed(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition, err error) {
f.Base.Failed(pickle, step, match, err)
f.Lock.Lock()
defer f.Lock.Unlock()
f.printStep(pickle, step)
}
// Failed captures failed step.
func (f *AST) 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 *AST) Pending(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition) {
f.Base.Pending(pickle, step, match)
f.Lock.Lock()
defer f.Lock.Unlock()
f.printStep(pickle, step)
}
func (f *AST) printFeature(feature *messages.Feature) {
fmt.Fprintln(f.out, keywordAndName(feature.Keyword, feature.Name))
if strings.TrimSpace(feature.Description) != "" {
for _, line := range strings.Split(feature.Description, "\n") {
fmt.Fprintln(f.out, s(f.indent)+strings.TrimSpace(line))
}
}
}
func (f *AST) scenarioLengths(pickle *messages.Pickle) (scenarioHeaderLength int, maxLength int) {
feature := f.Storage.MustGetFeature(pickle.Uri)
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
astBackground := feature.FindBackground(pickle.AstNodeIds[0])
scenarioHeaderLength = f.lengthPickle(astScenario.Keyword, astScenario.Name)
maxLength = f.longestStep(astScenario.Steps, scenarioHeaderLength)
if astBackground != nil {
maxLength = f.longestStep(astBackground.Steps, maxLength)
}
return scenarioHeaderLength, maxLength
}
func (f *AST) printScenarioHeader(pickle *messages.Pickle, astScenario *messages.Scenario, spaceFilling int) {
feature := f.Storage.MustGetFeature(pickle.Uri)
text := s(f.indent) + keywordAndName(astScenario.Keyword, astScenario.Name)
text += s(spaceFilling) + line(feature.Uri, astScenario.Location)
fmt.Fprintln(f.out, "\n"+text)
}
func (f *AST) printUndefinedPickle(pickle *messages.Pickle) {
feature := f.Storage.MustGetFeature(pickle.Uri)
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
astBackground := feature.FindBackground(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle)
if astBackground != nil {
fmt.Fprintln(f.out, "\n"+s(f.indent)+keywordAndName(astBackground.Keyword, astBackground.Name))
for _, step := range astBackground.Steps {
text := s(f.indent*2) + cyan(strings.TrimSpace(step.Keyword)) + " " + cyan(step.Text)
fmt.Fprintln(f.out, text)
}
}
// do not print scenario headers and examples multiple times
if len(astScenario.Examples) > 0 {
exampleTable, exampleRow := feature.FindExample(pickle.AstNodeIds[1])
firstExampleRow := exampleTable.TableBody[0].Id == exampleRow.Id
firstExamplesTable := astScenario.Examples[0].Location.Line == exampleTable.Location.Line
if !(firstExamplesTable && firstExampleRow) {
return
}
}
f.printScenarioHeader(pickle, astScenario, maxLength-scenarioHeaderLength)
for _, examples := range astScenario.Examples {
max := longestExampleRow(examples, cyan, cyan)
fmt.Fprintln(f.out, "")
fmt.Fprintln(f.out, s(f.indent*2)+keywordAndName(examples.Keyword, examples.Name))
f.printTableHeader(examples.TableHeader, max)
for _, row := range examples.TableBody {
f.printTableRow(row, max, cyan)
}
}
}
// Summary renders summary information.
func (f *AST) Summary() {
failedStepResults := f.Storage.MustGetPickleStepResultsByStatus(failed)
if len(failedStepResults) > 0 {
fmt.Fprintln(f.out, "\n--- "+red("Failed steps:")+"\n")
sort.Sort(sortPickleStepResultsByPickleStepID(failedStepResults))
for _, fail := range failedStepResults {
pickle := f.Storage.MustGetPickle(fail.PickleID)
pickleStep := f.Storage.MustGetPickleStep(fail.PickleStepID)
feature := f.Storage.MustGetFeature(pickle.Uri)
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
scenarioDesc := fmt.Sprintf("%s: %s", astScenario.Keyword, pickle.Name)
astStep := feature.FindStep(pickleStep.AstNodeIds[0])
stepDesc := strings.TrimSpace(astStep.Keyword) + " " + pickleStep.Text
fmt.Fprintln(f.out, s(f.indent)+red(scenarioDesc)+line(feature.Uri, astScenario.Location))
fmt.Fprintln(f.out, s(f.indent*2)+red(stepDesc)+line(feature.Uri, astStep.Location))
fmt.Fprint(f.out, s(f.indent*3)+redb(fmt.Sprintf("%+v", fail.Err)))
}
}
f.SummaryBottom()
}
func (f *AST) SummaryBottom() {
var totalSc, passedSc, undefinedSc int
var totalSt, passedSt, failedSt, skippedSt, pendingSt, undefinedSt, ambiguousSt int
pickleResults := f.Storage.MustGetPickleResults()
for _, pr := range pickleResults {
var prStatus models.StepResultStatus
totalSc++
pickleStepResults := f.Storage.MustGetPickleStepResultsByPickleID(pr.PickleID)
if len(pickleStepResults) == 0 {
prStatus = undefined
}
for _, sr := range pickleStepResults {
totalSt++
switch sr.Status {
case passed:
passedSt++
case failed:
prStatus = failed
failedSt++
case ambiguous:
prStatus = ambiguous
ambiguousSt++
case skipped:
skippedSt++
case undefined:
prStatus = undefined
undefinedSt++
case pending:
prStatus = pending
pendingSt++
}
}
if prStatus == passed {
passedSc++
} else if prStatus == undefined {
undefinedSc++
}
}
var steps, parts, scenarios []string
if passedSt > 0 {
steps = append(steps, green(fmt.Sprintf("%d passed", passedSt)))
}
if failedSt > 0 {
parts = append(parts, red(fmt.Sprintf("%d failed", failedSt)))
steps = append(steps, red(fmt.Sprintf("%d failed", failedSt)))
}
if pendingSt > 0 {
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)))
} else if undefinedSc > 0 {
// there may be some scenarios without steps
parts = append(parts, yellow(fmt.Sprintf("%d undefined", undefinedSc)))
}
if skippedSt > 0 {
steps = append(steps, cyan(fmt.Sprintf("%d skipped", skippedSt)))
}
if passedSc > 0 {
scenarios = append(scenarios, green(fmt.Sprintf("%d passed", passedSc)))
}
scenarios = append(scenarios, parts...)
testRunStartedAt := f.Storage.MustGetTestRunStarted().StartedAt
elapsed := utils.TimeNowFunc().Sub(testRunStartedAt)
fmt.Fprintln(f.out, "")
if totalSc == 0 {
fmt.Fprintln(f.out, "No scenarios")
} else {
fmt.Fprintf(f.out, "%d scenarios (%s), ", totalSc, strings.Join(scenarios, ", "))
}
if totalSt == 0 {
fmt.Fprintln(f.out, "No steps")
} else {
fmt.Fprintf(f.out, "%d steps (%s)\n", totalSt, strings.Join(steps, ", "))
}
elapsedString := elapsed.String()
if elapsed.Nanoseconds() == 0 {
// go 1.5 and 1.6 prints 0 instead of 0s, if duration is zero.
elapsedString = "0s"
}
fmt.Fprintln(f.out, elapsedString)
// prints used randomization seed
seed, err := strconv.ParseInt(os.Getenv("GODOG_SEED"), 10, 64)
if err == nil && seed != 0 {
fmt.Fprintln(f.out, "")
fmt.Fprintln(f.out, "Randomized with seed:", colors.Yellow(seed))
}
if text := f.Snippets(); text != "" {
fmt.Fprintln(f.out, "")
fmt.Fprintln(f.out, yellow("You can implement step definitions for undefined steps with these snippets:"))
fmt.Fprintln(f.out, yellow(text))
}
}
func (f *AST) Snippets() string {
undefinedStepResults := f.Storage.MustGetPickleStepResultsByStatus(undefined)
if len(undefinedStepResults) == 0 {
return ""
}
var index int
var snips []undefinedSnippet
// build snippets
for _, u := range undefinedStepResults {
pickleStep := f.Storage.MustGetPickleStep(u.PickleStepID)
steps := []string{pickleStep.Text}
arg := pickleStep.Argument
if u.Def != nil {
steps = u.Def.Undefined
arg = nil
}
for _, step := range steps {
expr := snippetExprCleanup.ReplaceAllString(step, "\\$1")
expr = snippetNumbers.ReplaceAllString(expr, "(\\d+)")
expr = snippetExprQuoted.ReplaceAllString(expr, "$1\"([^\"]*)\"$2")
expr = "^" + strings.TrimSpace(expr) + "$"
name := snippetNumbers.ReplaceAllString(step, " ")
name = snippetExprQuoted.ReplaceAllString(name, " ")
name = strings.TrimSpace(snippetMethodName.ReplaceAllString(name, ""))
var words []string
for i, w := range strings.Split(name, " ") {
switch {
case i != 0:
w = strings.Title(w)
case len(w) > 0:
r := []rune(w)
w = string(unicode.ToLower(r[0])) + string(r[1:])
}
words = append(words, w)
}
name = strings.Join(words, "")
if len(name) == 0 {
index++
name = fmt.Sprintf("StepDefinitioninition%d", index)
}
var found bool
for _, snip := range snips {
if snip.Expr == expr {
found = true
break
}
}
if !found {
s := undefinedSnippet{Method: name, Expr: expr, argument: arg}
snips = append(snips, s)
ast.ДобавитьШаг("`"+expr+"`", name, s.Args())
}
}
}
var buf bytes.Buffer
if err := AST_undefinedSnippetsTpl.Execute(&buf, snips); err != nil {
panic(err)
}
// there may be trailing spaces
return strings.Replace(buf.String(), " \n", "\n", -1)
}
var AST_undefinedSnippetsTpl = template.Must(template.New("snippets").Funcs(snippetHelperFuncs).Parse(`
func InitializeScenario(ctx *godog.ScenarioContext) {}
// ---
{{ range . }}func {{ .Method }}({{ .Args }}) {
}
{{end}}{{ range . }}
ctx.Step({{ backticked .Expr }}, {{ .Method }}){{end}}
`))
func (f *AST) printOutlineExample(pickle *messages.Pickle, step *messages.PickleStep, backgroundSteps int) {
var errorMsg string
var clr = green
feature := f.Storage.MustGetFeature(pickle.Uri)
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle)
exampleTable, exampleRow := feature.FindExample(pickle.AstNodeIds[1])
printExampleHeader := exampleTable.TableBody[0].Id == exampleRow.Id
firstExamplesTable := astScenario.Examples[0].Location.Line == exampleTable.Location.Line
pickleStepResults := f.Storage.MustGetPickleStepResultsByPickleIDUntilStep(pickle.Id, step.Id)
firstExecutedScenarioStep := len(pickleStepResults) == backgroundSteps+1
if firstExamplesTable && printExampleHeader && firstExecutedScenarioStep {
f.printScenarioHeader(pickle, astScenario, maxLength-scenarioHeaderLength)
}
if len(exampleTable.TableBody) == 0 {
// do not print empty examples
return
}
lastStep := len(pickleStepResults) == len(pickle.Steps)
if !lastStep {
// do not print examples unless all steps has finished
return
}
for _, result := range pickleStepResults {
// determine example row status
switch {
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:
clr = cyan
}
if firstExamplesTable && printExampleHeader {
// in first example, we need to print steps
pickleStep := f.Storage.MustGetPickleStep(result.PickleStepID)
astStep := feature.FindStep(pickleStep.AstNodeIds[0])
var text = ""
if result.Def != nil {
if m := outlinePlaceholderRegexp.FindAllStringIndex(astStep.Text, -1); len(m) > 0 {
var pos int
for i := 0; i < len(m); i++ {
pair := m[i]
text += cyan(astStep.Text[pos:pair[0]])
text += cyanb(astStep.Text[pair[0]:pair[1]])
pos = pair[1]
}
text += cyan(astStep.Text[pos:len(astStep.Text)])
} else {
text = cyan(astStep.Text)
}
_, maxLength := f.scenarioLengths(pickle)
stepLength := f.lengthPickleStep(astStep.Keyword, astStep.Text)
text += s(maxLength - stepLength)
text += " " + blackb("# "+DefinitionID(result.Def))
}
// print the step outline
fmt.Fprintln(f.out, s(f.indent*2)+cyan(strings.TrimSpace(astStep.Keyword))+" "+text)
if pickleStep.Argument != nil {
if table := pickleStep.Argument.DataTable; table != nil {
f.printTable(table, cyan)
}
if docString := astStep.DocString; docString != nil {
f.printDocString(docString)
}
}
}
}
max := longestExampleRow(exampleTable, clr, cyan)
// an example table header
if printExampleHeader {
fmt.Fprintln(f.out, "")
fmt.Fprintln(f.out, s(f.indent*2)+keywordAndName(exampleTable.Keyword, exampleTable.Name))
f.printTableHeader(exampleTable.TableHeader, max)
}
f.printTableRow(exampleRow, max, clr)
if errorMsg != "" {
fmt.Fprintln(f.out, s(f.indent*4)+redb(errorMsg))
}
}
func (f *AST) printTableRow(row *messages.TableRow, max []int, clr colors.ColorFunc) {
cells := make([]string, len(row.Cells))
for i, cell := range row.Cells {
val := clr(cell.Value)
ln := utf8.RuneCountInString(val)
cells[i] = val + s(max[i]-ln)
}
fmt.Fprintln(f.out, s(f.indent*3)+"| "+strings.Join(cells, " | ")+" |")
}
func (f *AST) printTableHeader(row *messages.TableRow, max []int) {
f.printTableRow(row, max, cyan)
}
func (f *AST) printStep(pickle *messages.Pickle, pickleStep *messages.PickleStep) {
feature := f.Storage.MustGetFeature(pickle.Uri)
astBackground := feature.FindBackground(pickle.AstNodeIds[0])
astScenario := feature.FindScenario(pickle.AstNodeIds[0])
astRule := feature.FindRule(pickle.AstNodeIds[0])
astStep := feature.FindStep(pickleStep.AstNodeIds[0])
var astBackgroundStep bool
var firstExecutedBackgroundStep bool
var backgroundSteps int
if astBackground != nil {
backgroundSteps = len(astBackground.Steps)
for idx, step := range astBackground.Steps {
if step.Id == pickleStep.AstNodeIds[0] {
astBackgroundStep = true
firstExecutedBackgroundStep = idx == 0
break
}
}
}
firstPickle := isFirstPickleAndNoRule(feature, pickle, astRule) || isFirstScenarioInRule(astRule, astScenario)
if astBackgroundStep && !firstPickle {
return
}
if astBackgroundStep && firstExecutedBackgroundStep {
fmt.Fprintln(f.out, "\n"+s(f.indent)+keywordAndName(astBackground.Keyword, astBackground.Name))
}
if !astBackgroundStep && len(astScenario.Examples) > 0 {
f.printOutlineExample(pickle, pickleStep, backgroundSteps)
return
}
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle)
stepLength := f.lengthPickleStep(astStep.Keyword, pickleStep.Text)
firstExecutedScenarioStep := astScenario.Steps[0].Id == pickleStep.AstNodeIds[0]
if !astBackgroundStep && firstExecutedScenarioStep {
f.printScenarioHeader(pickle, astScenario, maxLength-scenarioHeaderLength)
}
pickleStepResult := f.Storage.MustGetPickleStepResult(pickleStep.Id)
text := s(f.indent*2) + pickleStepResult.Status.Color()(strings.TrimSpace(astStep.Keyword)) + " " + pickleStepResult.Status.Color()(pickleStep.Text)
if pickleStepResult.Def != nil {
text += s(maxLength - stepLength + 1)
text += blackb("# " + DefinitionID(pickleStepResult.Def))
}
fmt.Fprintln(f.out, text)
if pickleStep.Argument != nil {
if table := pickleStep.Argument.DataTable; table != nil {
f.printTable(table, cyan)
}
if docString := astStep.DocString; docString != nil {
f.printDocString(docString)
}
}
if pickleStepResult.Err != nil {
fmt.Fprintln(f.out, s(f.indent*2)+redb(fmt.Sprintf("%+v", pickleStepResult.Err)))
}
if pickleStepResult.Status == pending {
fmt.Fprintln(f.out, s(f.indent*3)+yellow("TODO: write pending definition"))
}
}
func (f *AST) printDocString(docString *messages.DocString) {
var ct string
if len(docString.MediaType) > 0 {
ct = " " + cyan(docString.MediaType)
}
fmt.Fprintln(f.out, s(f.indent*3)+cyan(docString.Delimiter)+ct)
for _, ln := range strings.Split(docString.Content, "\n") {
fmt.Fprintln(f.out, s(f.indent*3)+cyan(ln))
}
fmt.Fprintln(f.out, s(f.indent*3)+cyan(docString.Delimiter))
}
// print table with aligned table cells
// @TODO: need to make example header cells bold
func (f *AST) printTable(t *messages.PickleTable, c colors.ColorFunc) {
maxColLengths := maxColLengths(t, c)
var cols = make([]string, len(t.Rows[0].Cells))
for _, row := range t.Rows {
for i, cell := range row.Cells {
val := c(cell.Value)
colLength := utf8.RuneCountInString(val)
cols[i] = val + s(maxColLengths[i]-colLength)
}
fmt.Fprintln(f.out, s(f.indent*3)+"| "+strings.Join(cols, " | ")+" |")
}
}
func (f *AST) longestStep(steps []*messages.Step, pickleLength int) int {
max := pickleLength
for _, step := range steps {
length := f.lengthPickleStep(step.Keyword, step.Text)
if length > max {
max = length
}
}
return max
}
func (f *AST) lengthPickleStep(keyword, text string) int {
return f.indent*2 + utf8.RuneCountInString(strings.TrimSpace(keyword)+" "+text)
}
func (f *AST) lengthPickle(keyword, name string) int {
return f.indent + utf8.RuneCountInString(strings.TrimSpace(keyword)+": "+name)
}

Просмотреть файл

@ -13,11 +13,11 @@ import (
messages "github.com/cucumber/messages/go/v21"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/storage"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/models"
"git.golang1.ru/softonik/godog/internal/storage"
"git.golang1.ru/softonik/godog/internal/utils"
)
// BaseFormatterFunc implements the FormatterFunc for the base formatter.
@ -85,10 +85,14 @@ func (f *Base) Failed(*messages.Pickle, *messages.PickleStep, *formatters.StepDe
func (f *Base) Pending(*messages.Pickle, *messages.PickleStep, *formatters.StepDefinition) {
}
// Ambiguous captures ambiguous step.
func (f *Base) Ambiguous(*messages.Pickle, *messages.PickleStep, *formatters.StepDefinition, error) {
}
// 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 {
@ -110,6 +114,9 @@ func (f *Base) Summary() {
case failed:
prStatus = failed
failedSt++
case ambiguous:
prStatus = ambiguous
ambiguousSt++
case skipped:
skippedSt++
case undefined:
@ -140,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)))
@ -227,7 +238,8 @@ func (f *Base) Snippets() string {
case i != 0:
w = strings.Title(w)
case len(w) > 0:
w = string(unicode.ToLower(rune(w[0]))) + w[1:]
r := []rune(w)
w = string(unicode.ToLower(r[0])) + string(r[1:])
}
words = append(words, w)
}

Просмотреть файл

@ -7,8 +7,8 @@ import (
"fmt"
"testing"
"github.com/cucumber/godog"
"github.com/cucumber/godog/internal/flags"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/internal/flags"
"github.com/stretchr/testify/assert"
)
@ -42,7 +42,7 @@ And step failed f2s3:4
Scenario: f2s4
When step passed f2s4:1
Then step is undefined f2s4:2
Then something unknown happens f2s4:2
And step passed f2s4:3
`)},
)
@ -116,8 +116,8 @@ scenario "f2s3" passed
step invoked: "f2s4:1", passed
step "step passed f2s4:1" finished with status passed
.Ustep "step is undefined f2s4:2" finished with status undefined
scenario "f2s4" ended with error "step is undefined"
.Ustep "something unknown happens f2s4:2" finished with status undefined
scenario "f2s4" ended with error "step is undefined: something unknown happens f2s4:2"
-step "step passed f2s4:3" finished with status skipped
13
@ -139,12 +139,12 @@ scenario "f2s4" ended with error "step is undefined"
You can implement step definitions for undefined steps with these snippets:
func stepIsUndefinedFS(arg1, arg2, arg3 int) error {
func somethingUnknownHappensFS(arg1, arg2, arg3 int) error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`+"`"+`^step is undefined f(\d+)s(\d+):(\d+)$`+"`"+`, stepIsUndefinedFS)
ctx.Step(`+"`"+`^something unknown happens f(\d+)s(\d+):(\d+)$`+"`"+`, somethingUnknownHappensFS)
}
`, out.String())

Просмотреть файл

@ -7,7 +7,7 @@ import (
"strings"
"testing"
"github.com/cucumber/godog/colors"
"git.golang1.ru/softonik/godog/colors"
)
type csiState int

Просмотреть файл

@ -12,14 +12,15 @@ package formatters
*/
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"sort"
"strings"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/models"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/models"
messages "github.com/cucumber/messages/go/v21"
)
@ -100,7 +101,8 @@ func (f *Cuke) buildCukeElements(pickles []*messages.Pickle) (res []cukeElement)
cukeStep.Result.Duration = &d
if stepResult.Status == undefined ||
stepResult.Status == pending ||
stepResult.Status == skipped {
stepResult.Status == skipped ||
stepResult.Status == ambiguous {
cukeStep.Result.Duration = nil
}
@ -139,6 +141,12 @@ type cukeMatch struct {
Location string `json:"location"`
}
type cukeEmbedding struct {
Name string `json:"name"`
MimeType string `json:"mime_type"`
Data string `json:"data"`
}
type cukeStep struct {
Keyword string `json:"keyword"`
Name string `json:"name"`
@ -147,6 +155,7 @@ type cukeStep struct {
Match cukeMatch `json:"match"`
Result cukeResult `json:"result"`
DataTable []*cukeDataTableRow `json:"rows,omitempty"`
Embeddings []cukeEmbedding `json:"embeddings,omitempty"`
}
type cukeDataTableRow struct {
@ -290,10 +299,25 @@ 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)
}
if stepResult.Attachments != nil {
attachments := []cukeEmbedding{}
for _, a := range stepResult.Attachments {
attachments = append(attachments, cukeEmbedding{
Name: a.Name,
Data: base64.StdEncoding.EncodeToString(a.Data),
MimeType: a.MimeType,
})
}
if len(attachments) > 0 {
cukeStep.Embeddings = attachments
}
}
return cukeStep
}

Просмотреть файл

@ -5,8 +5,8 @@ import (
"fmt"
"io"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/utils"
messages "github.com/cucumber/messages/go/v21"
)
@ -153,6 +153,31 @@ func (f *Events) step(pickle *messages.Pickle, pickleStep *messages.PickleStep)
if pickleStepResult.Err != nil {
errMsg = pickleStepResult.Err.Error()
}
if pickleStepResult.Attachments != nil {
for _, attachment := range pickleStepResult.Attachments {
f.event(&struct {
Event string `json:"event"`
Location string `json:"location"`
Timestamp int64 `json:"timestamp"`
ContentEncoding string `json:"contentEncoding"`
FileName string `json:"fileName"`
MimeType string `json:"mimeType"`
Body string `json:"body"`
}{
"Attachment",
fmt.Sprintf("%s:%d", pickle.Uri, step.Location.Line),
utils.TimeNowFunc().UnixNano() / nanoSec,
messages.AttachmentContentEncoding_BASE64.String(),
attachment.Name,
attachment.MimeType,
string(attachment.Data),
})
}
}
f.event(&struct {
Event string `json:"event"`
Location string `json:"location"`
@ -173,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()
}
}
@ -293,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])

108
internal/formatters/fmt_flushwrap.go Обычный файл
Просмотреть файл

@ -0,0 +1,108 @@
package formatters
import (
"sync"
"git.golang1.ru/softonik/godog/formatters"
messages "github.com/cucumber/messages/go/v21"
)
// WrapOnFlush wrap a `formatters.Formatter` in a `formatters.FlushFormatter`, which only
// executes when `Flush` is called
func WrapOnFlush(fmt formatters.Formatter) formatters.FlushFormatter {
return &onFlushFormatter{
fmt: fmt,
fns: make([]func(), 0),
mu: &sync.Mutex{},
}
}
type onFlushFormatter struct {
fmt formatters.Formatter
fns []func()
mu *sync.Mutex
}
func (o *onFlushFormatter) Pickle(pickle *messages.Pickle) {
o.fns = append(o.fns, func() {
o.fmt.Pickle(pickle)
})
}
func (o *onFlushFormatter) Passed(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition) {
o.fns = append(o.fns, func() {
o.fmt.Passed(pickle, step, definition)
})
}
// Ambiguous implements formatters.Formatter.
func (o *onFlushFormatter) Ambiguous(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition, err error) {
o.fns = append(o.fns, func() {
o.fmt.Ambiguous(pickle, step, definition, err)
})
}
// Defined implements formatters.Formatter.
func (o *onFlushFormatter) Defined(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition) {
o.fns = append(o.fns, func() {
o.fmt.Defined(pickle, step, definition)
})
}
// Failed implements formatters.Formatter.
func (o *onFlushFormatter) Failed(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition, err error) {
o.fns = append(o.fns, func() {
o.fmt.Failed(pickle, step, definition, err)
})
}
// Feature implements formatters.Formatter.
func (o *onFlushFormatter) Feature(pickle *messages.GherkinDocument, p string, c []byte) {
o.fns = append(o.fns, func() {
o.fmt.Feature(pickle, p, c)
})
}
// Pending implements formatters.Formatter.
func (o *onFlushFormatter) Pending(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition) {
o.fns = append(o.fns, func() {
o.fmt.Pending(pickle, step, definition)
})
}
// Skipped implements formatters.Formatter.
func (o *onFlushFormatter) Skipped(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition) {
o.fns = append(o.fns, func() {
o.fmt.Skipped(pickle, step, definition)
})
}
// Summary implements formatters.Formatter.
func (o *onFlushFormatter) Summary() {
o.fns = append(o.fns, func() {
o.fmt.Summary()
})
}
// TestRunStarted implements formatters.Formatter.
func (o *onFlushFormatter) TestRunStarted() {
o.fns = append(o.fns, func() {
o.fmt.TestRunStarted()
})
}
// Undefined implements formatters.Formatter.
func (o *onFlushFormatter) Undefined(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition) {
o.fns = append(o.fns, func() {
o.fmt.Undefined(pickle, step, definition)
})
}
// Flush the logs.
func (o *onFlushFormatter) Flush() {
o.mu.Lock()
defer o.mu.Unlock()
for _, fn := range o.fns {
fn()
}
}

53
internal/formatters/fmt_flushwrap_test.go Обычный файл
Просмотреть файл

@ -0,0 +1,53 @@
package formatters
import (
"testing"
"github.com/stretchr/testify/assert"
)
var flushMock = DummyFormatter{}
func TestFlushWrapOnFormatter(t *testing.T) {
flushMock.tt = t
fmt := WrapOnFlush(&flushMock)
fmt.Feature(document, str, byt)
fmt.TestRunStarted()
fmt.Pickle(pickle)
fmt.Defined(pickle, step, definition)
fmt.Passed(pickle, step, definition)
fmt.Skipped(pickle, step, definition)
fmt.Undefined(pickle, step, definition)
fmt.Failed(pickle, step, definition, err)
fmt.Pending(pickle, step, definition)
fmt.Ambiguous(pickle, step, definition, err)
fmt.Summary()
assert.Equal(t, 0, flushMock.CountFeature)
assert.Equal(t, 0, flushMock.CountTestRunStarted)
assert.Equal(t, 0, flushMock.CountPickle)
assert.Equal(t, 0, flushMock.CountDefined)
assert.Equal(t, 0, flushMock.CountPassed)
assert.Equal(t, 0, flushMock.CountSkipped)
assert.Equal(t, 0, flushMock.CountUndefined)
assert.Equal(t, 0, flushMock.CountFailed)
assert.Equal(t, 0, flushMock.CountPending)
assert.Equal(t, 0, flushMock.CountAmbiguous)
assert.Equal(t, 0, flushMock.CountSummary)
fmt.Flush()
assert.Equal(t, 1, flushMock.CountFeature)
assert.Equal(t, 1, flushMock.CountTestRunStarted)
assert.Equal(t, 1, flushMock.CountPickle)
assert.Equal(t, 1, flushMock.CountDefined)
assert.Equal(t, 1, flushMock.CountPassed)
assert.Equal(t, 1, flushMock.CountSkipped)
assert.Equal(t, 1, flushMock.CountUndefined)
assert.Equal(t, 1, flushMock.CountFailed)
assert.Equal(t, 1, flushMock.CountPending)
assert.Equal(t, 1, flushMock.CountAmbiguous)
assert.Equal(t, 1, flushMock.CountSummary)
}

Просмотреть файл

@ -9,8 +9,8 @@ import (
"strconv"
"time"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/utils"
)
func init() {
@ -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",

Просмотреть файл

@ -3,8 +3,8 @@ package formatters
import (
"io"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/storage"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/storage"
messages "github.com/cucumber/messages/go/v21"
)
@ -97,6 +97,13 @@ func (r repeater) Pending(pickle *messages.Pickle, step *messages.PickleStep, de
}
}
// Ambiguous triggers Ambiguous for all added formatters.
func (r repeater) Ambiguous(pickle *messages.Pickle, step *messages.PickleStep, definition *formatters.StepDefinition, err error) {
for _, f := range r {
f.Ambiguous(pickle, step, definition, err)
}
}
// Summary triggers Summary for all added formatters.
func (r repeater) Summary() {
for _, f := range r {

164
internal/formatters/fmt_multi_test.go Обычный файл
Просмотреть файл

@ -0,0 +1,164 @@
package formatters
import (
"errors"
"testing"
"git.golang1.ru/softonik/godog/formatters"
messages "github.com/cucumber/messages/go/v21"
"github.com/stretchr/testify/assert"
)
var (
mock = DummyFormatter{}
base = BaseFormatter{}
document = &messages.GherkinDocument{}
str = "theString"
byt = []byte("bytes")
pickle = &messages.Pickle{}
step = &messages.PickleStep{}
definition = &formatters.StepDefinition{}
err = errors.New("expected")
)
// TestRepeater tests the delegation of the repeater functions.
func TestRepeater(t *testing.T) {
mock.tt = t
f := make(repeater, 0)
f = append(f, &mock)
f = append(f, &mock)
f = append(f, &base)
f.Feature(document, str, byt)
f.TestRunStarted()
f.Pickle(pickle)
f.Defined(pickle, step, definition)
f.Passed(pickle, step, definition)
f.Skipped(pickle, step, definition)
f.Undefined(pickle, step, definition)
f.Failed(pickle, step, definition, err)
f.Pending(pickle, step, definition)
f.Ambiguous(pickle, step, definition, err)
assert.Equal(t, 2, mock.CountFeature)
assert.Equal(t, 2, mock.CountTestRunStarted)
assert.Equal(t, 2, mock.CountPickle)
assert.Equal(t, 2, mock.CountDefined)
assert.Equal(t, 2, mock.CountPassed)
assert.Equal(t, 2, mock.CountSkipped)
assert.Equal(t, 2, mock.CountUndefined)
assert.Equal(t, 2, mock.CountFailed)
assert.Equal(t, 2, mock.CountPending)
assert.Equal(t, 2, mock.CountAmbiguous)
}
type BaseFormatter struct {
*Base
}
type DummyFormatter struct {
*Base
tt *testing.T
CountFeature int
CountTestRunStarted int
CountPickle int
CountDefined int
CountPassed int
CountSkipped int
CountUndefined int
CountFailed int
CountPending int
CountAmbiguous int
CountSummary int
}
// SetStorage assigns gherkin data storage.
// func (f *DummyFormatter) SetStorage(st *storage.Storage) {
// }
// TestRunStarted is triggered on test start.
func (f *DummyFormatter) TestRunStarted() {
f.CountTestRunStarted++
}
// Feature receives gherkin document.
func (f *DummyFormatter) Feature(d *messages.GherkinDocument, s string, b []byte) {
assert.Equal(f.tt, document, d)
assert.Equal(f.tt, str, s)
assert.Equal(f.tt, byt, b)
f.CountFeature++
}
// Pickle receives scenario.
func (f *DummyFormatter) Pickle(p *messages.Pickle) {
assert.Equal(f.tt, pickle, p)
f.CountPickle++
}
// Defined receives step definition.
func (f *DummyFormatter) Defined(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
f.CountDefined++
}
// Passed captures passed step.
func (f *DummyFormatter) Passed(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
f.CountPassed++
}
// Skipped captures skipped step.
func (f *DummyFormatter) Skipped(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
f.CountSkipped++
}
// Undefined captures undefined step.
func (f *DummyFormatter) Undefined(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
f.CountUndefined++
}
// Failed captures failed step.
func (f *DummyFormatter) Failed(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition, e error) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
assert.Equal(f.tt, err, e)
f.CountFailed++
}
// Pending captures pending step.
func (f *DummyFormatter) Pending(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
f.CountPending++
}
// Ambiguous captures ambiguous step.
func (f *DummyFormatter) Ambiguous(p *messages.Pickle, s *messages.PickleStep, d *formatters.StepDefinition, e error) {
assert.Equal(f.tt, pickle, p)
assert.Equal(f.tt, s, step)
assert.Equal(f.tt, d, definition)
f.CountAmbiguous++
}
// Pickle receives scenario.
func (f *DummyFormatter) Summary() {
f.CountSummary++
}

Просмотреть файл

@ -2,31 +2,33 @@ package formatters_test
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cucumber/godog"
"git.golang1.ru/softonik/godog"
)
const fmtOutputTestsFeatureDir = "formatter-tests/features"
var tT *testing.T
func Test_FmtOutput(t *testing.T) {
tT = t
pkg := os.Getenv("GODOG_TESTED_PACKAGE")
os.Setenv("GODOG_TESTED_PACKAGE", "github.com/cucumber/godog")
os.Setenv("GODOG_TESTED_PACKAGE", "git.golang1.ru/softonik/godog")
featureFiles, err := listFmtOutputTestsFeatureFiles()
require.Nil(t, err)
formatters := []string{"cucumber", "events", "junit", "pretty", "progress", "junit,pretty"}
for _, fmtName := range formatters {
for _, featureFile := range featureFiles {
testName := fmt.Sprintf("%s/%s", fmtName, featureFile)
@ -61,20 +63,104 @@ func listFmtOutputTestsFeatureFiles() (featureFiles []string, err error) {
func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) {
fmtOutputScenarioInitializer := func(ctx *godog.ScenarioContext) {
stepIndex := 0
ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
if strings.Contains(sc.Name, "attachment") {
att := godog.Attachments(ctx)
attCount := len(att)
if attCount != 0 {
assert.FailNowf(tT, "Unexpected attachments: "+sc.Name, "should have been empty, found %d", attCount)
}
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("BeforeScenarioAttachment"), FileName: "Before Scenario Attachment 1", MediaType: "text/plain"},
)
}
return ctx, nil
})
ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
if strings.Contains(sc.Name, "attachment") {
att := godog.Attachments(ctx)
attCount := len(att)
if attCount != 4 {
assert.FailNow(tT, "Unexpected attachments: "+sc.Name, "expected 4, found %d", attCount)
}
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("AfterScenarioAttachment"), FileName: "After Scenario Attachment 2", MediaType: "text/plain"},
)
}
return ctx, nil
})
ctx.StepContext().Before(func(ctx context.Context, st *godog.Step) (context.Context, error) {
stepIndex++
if strings.Contains(st.Text, "attachment") {
att := godog.Attachments(ctx)
attCount := len(att)
// 1 for before scenario ONLY if this is the 1st step
expectedAttCount := 0
if stepIndex == 1 {
expectedAttCount = 1
}
if attCount != expectedAttCount {
assert.FailNow(tT, "Unexpected attachments: "+st.Text, "expected 1, found %d\n%+v", attCount, att)
}
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("BeforeStepAttachment"), FileName: "Before Step Attachment 3", MediaType: "text/plain"},
)
}
return ctx, nil
})
ctx.StepContext().After(func(ctx context.Context, st *godog.Step, status godog.StepResultStatus, err error) (context.Context, error) {
if strings.Contains(st.Text, "attachment") {
att := godog.Attachments(ctx)
attCount := len(att)
// 1 for before scenario ONLY if this is the 1st step
// 1 for before before step
// 2 from from step
expectedAttCount := 3
if stepIndex == 1 {
expectedAttCount = 4
}
if attCount != expectedAttCount {
// 1 from before scenario, 1 from before step, 1 from step
assert.FailNow(tT, "Unexpected attachments: "+st.Text, "expected 4, found %d", attCount)
}
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("AfterStepAttachment"), FileName: "After Step Attachment 4", MediaType: "text/plain"},
)
}
return ctx, nil
})
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 {
t.Skipf("Couldn't find expected output file %q", expectOutputPath)
// the test author needs to write an "expected output" file for any formats they want the test feature to be verified against
t.Skipf("Skipping test for feature '%v' for format '%v', because no 'expected output' file %q", featureFilePath, fmtName, expectOutputPath)
}
expectedOutput, err := ioutil.ReadFile(expectOutputPath)
expectedOutput, err := os.ReadFile(expectOutputPath)
require.NoError(t, err)
var buf bytes.Buffer
@ -84,6 +170,7 @@ func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) {
Format: fmtName,
Paths: []string{featureFilePath},
Output: out,
Strict: true,
}
godog.TestSuite{
@ -92,15 +179,41 @@ func fmtOutputTest(fmtName, testName, featureFilePath string) func(*testing.T) {
Options: &opts,
}.Run()
expected := string(expectedOutput)
actual := buf.String()
// 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 {
fmt.Printf("Error: fmt: %s, path: %s\n", fmtName, expectOutputPath)
compareLists(expected, actual)
}
}
}
func passingStepDef() error { return nil }
func normalise(s string) string {
func oddEvenStepDef(odd, even int) error { return oddOrEven(odd, even) }
m := regexp.MustCompile("fmt_output_test.go:[0-9]+")
normalised := m.ReplaceAllString(s, "fmt_output_test.go:XXX")
normalised = strings.Replace(normalised, "\r\n", "\n", -1)
normalised = strings.Replace(normalised, "\\r\\n", "\\n", -1)
return normalised
}
func passingStepDef() error {
return nil
}
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 {
@ -115,3 +228,118 @@ func oddOrEven(odd, even int) error {
func pendingStepDef() error { return godog.ErrPending }
func failingStepDef() error { return fmt.Errorf("step failed") }
func stepWithSingleAttachmentCall(ctx context.Context) (context.Context, error) {
aCount := len(godog.Attachments(ctx))
if aCount != 2 {
// 1 from before scenario, 1 from before step
assert.FailNowf(tT, "Unexpected Attachments found", "should have been 2, but found %v", aCount)
}
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("TheData1"), FileName: "TheFilename1", MediaType: "text/plain"},
godog.Attachment{Body: []byte("TheData2"), FileName: "TheFilename2", MediaType: "text/plain"},
)
return ctx, nil
}
func stepWithMultipleAttachmentCalls(ctx context.Context) (context.Context, error) {
aCount := len(godog.Attachments(ctx))
if aCount != 1 {
assert.FailNowf(tT, "Unexpected Attachments found", "Expected 1 Attachment, but found %v", aCount)
}
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("TheData1"), FileName: "TheFilename3", MediaType: "text/plain"},
)
ctx = godog.Attach(ctx,
godog.Attachment{Body: []byte("TheData2"), FileName: "TheFilename4", MediaType: "text/plain"},
)
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+2, colWid+2)
fmtData := fmt.Sprintf("%%4d: %%-%ds | %%-%ds %%s\n", colWid+2, colWid+2)
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"
}
delim := "¬"
// Print the wrapped lines with fixed-width column
fmt.Printf(fmtData, i+1, delim+line1+delim, delim+line2+delim, status)
}
}
}

Просмотреть файл

@ -10,9 +10,9 @@ import (
messages "github.com/cucumber/messages/go/v21"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/models"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/models"
)
func init() {
@ -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)
@ -233,7 +243,7 @@ func (f *Pretty) Summary() {
f.Base.Summary()
}
func (f *Pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps int) {
func (f *Pretty) printOutlineExample(pickle *messages.Pickle, step *messages.PickleStep, backgroundSteps int) {
var errorMsg string
var clr = green
@ -245,7 +255,7 @@ func (f *Pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in
printExampleHeader := exampleTable.TableBody[0].Id == exampleRow.Id
firstExamplesTable := astScenario.Examples[0].Location.Line == exampleTable.Location.Line
pickleStepResults := f.Storage.MustGetPickleStepResultsByPickleID(pickle.Id)
pickleStepResults := f.Storage.MustGetPickleStepResultsByPickleIDUntilStep(pickle.Id, step.Id)
firstExecutedScenarioStep := len(pickleStepResults) == backgroundSteps+1
if firstExamplesTable && printExampleHeader && firstExecutedScenarioStep {
@ -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:
@ -406,7 +419,7 @@ func (f *Pretty) printStep(pickle *messages.Pickle, pickleStep *messages.PickleS
}
if !astBackgroundStep && len(astScenario.Examples) > 0 {
f.printOutlineExample(pickle, backgroundSteps)
f.printOutlineExample(pickle, pickleStep, backgroundSteps)
return
}

Просмотреть файл

@ -7,7 +7,7 @@ import (
"sort"
"strings"
"github.com/cucumber/godog/formatters"
"git.golang1.ru/softonik/godog/formatters"
messages "github.com/cucumber/messages/go/v21"
)
@ -42,7 +42,7 @@ func (f *Progress) Summary() {
left := math.Mod(float64(*f.Steps), float64(f.StepsPerRow))
if left != 0 {
if *f.Steps > f.StepsPerRow {
fmt.Fprintf(f.out, s(f.StepsPerRow-int(left))+fmt.Sprintf(" %d\n", *f.Steps))
fmt.Fprint(f.out, s(f.StepsPerRow-int(left))+fmt.Sprintf(" %d\n", *f.Steps))
} else {
fmt.Fprintf(f.out, " %d\n", *f.Steps)
}
@ -98,6 +98,8 @@ func (f *Progress) step(pickleStepID string) {
fmt.Fprint(f.out, red("F"))
case undefined:
fmt.Fprint(f.out, yellow("U"))
case ambiguous:
fmt.Fprint(f.out, yellow("A"))
case pending:
fmt.Fprint(f.out, yellow("P"))
}
@ -149,6 +151,16 @@ func (f *Progress) Failed(pickle *messages.Pickle, step *messages.PickleStep, ma
f.step(step.Id)
}
// Ambiguous steps.
func (f *Progress) 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(step.Id)
}
// Pending captures pending step.
func (f *Progress) Pending(pickle *messages.Pickle, step *messages.PickleStep, match *formatters.StepDefinition) {
f.Base.Pending(pickle, step, match)

Просмотреть файл

@ -0,0 +1,100 @@
[
{
"uri": "formatter-tests/features/scenario_with_attachment.feature",
"id": "feature-with-attachment",
"keyword": "Feature",
"name": "feature with attachment",
"description": " describes\n an attachment\n feature",
"line": 1,
"elements": [
{
"id": "feature-with-attachment;scenario-with-attachment",
"keyword": "Scenario",
"name": "scenario with attachment",
"description": "",
"line": 6,
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "a step with a single attachment call for multiple attachments",
"line": 7,
"match": {
"location": "fmt_output_test.go:119"
},
"result": {
"status": "passed",
"duration": 0
},
"embeddings": [
{
"name": "Before Scenario Attachment 1",
"mime_type": "text/plain",
"data": "QmVmb3JlU2NlbmFyaW9BdHRhY2htZW50"
},
{
"name": "Before Step Attachment 3",
"mime_type": "text/plain",
"data": "QmVmb3JlU3RlcEF0dGFjaG1lbnQ="
},
{
"name": "TheFilename1",
"mime_type": "text/plain",
"data": "VGhlRGF0YTE="
},
{
"name": "TheFilename2",
"mime_type": "text/plain",
"data": "VGhlRGF0YTI="
},
{
"name": "After Step Attachment 4",
"mime_type": "text/plain",
"data": "QWZ0ZXJTdGVwQXR0YWNobWVudA=="
}
]
},
{
"keyword": "And ",
"name": "a step with multiple attachment calls",
"line": 8,
"match": {
"location": "fmt_output_test.go:119"
},
"result": {
"status": "passed",
"duration": 0
},
"embeddings": [
{
"name": "Before Step Attachment 3",
"mime_type": "text/plain",
"data": "QmVmb3JlU3RlcEF0dGFjaG1lbnQ="
},
{
"name": "TheFilename3",
"mime_type": "text/plain",
"data": "VGhlRGF0YTE="
},
{
"name": "TheFilename4",
"mime_type": "text/plain",
"data": "VGhlRGF0YTI="
},
{
"name": "After Step Attachment 4",
"mime_type": "text/plain",
"data": "QWZ0ZXJTdGVwQXR0YWNobWVudA=="
},
{
"name": "After Scenario Attachment 2",
"mime_type": "text/plain",
"data": "QWZ0ZXJTY2VuYXJpb0F0dGFjaG1lbnQ="
}
]
}
]
}
]
}
]

Просмотреть файл

@ -1,6 +1,6 @@
[
{
"uri": "formatter-tests/features/some_scenarions_including_failing.feature",
"uri": "formatter-tests/features/some_scenarios_including_failing.feature",
"id": "some-scenarios",
"keyword": "Feature",
"name": "some scenarios",
@ -66,7 +66,7 @@
"name": "pending step",
"line": 9,
"match": {
"location": "formatter-tests/features/some_scenarions_including_failing.feature:9"
"location": "formatter-tests/features/some_scenarios_including_failing.feature:9"
},
"result": {
"status": "pending"
@ -98,7 +98,7 @@
"name": "undefined",
"line": 13,
"match": {
"location": "formatter-tests/features/some_scenarions_including_failing.feature:13"
"location": "formatter-tests/features/some_scenarios_including_failing.feature:13"
},
"result": {
"status": "undefined"
@ -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_scenarios_including_failing.feature:17"
},
"result": {
"status": "ambiguous",
"error_message": "ambiguous step definition, step text: ambiguous step\n matches:\n ^ambiguous step.*$\n ^ambiguous step$"
}
},
{
"keyword": "Then ",
"name": "passing step",
"line": 18,
"match": {
"location": "fmt_output_test.go:XXX"
},
"result": {
"status": "skipped"
}
}
]
}
]
}

Просмотреть файл

@ -1,57 +1,57 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/scenario_outline.feature:2","source":"@outline @tag\nFeature: outline\n\n @scenario\n Scenario Outline: outline\n Given passing step\n When passing step\n Then odd \u003codd\u003e and even \u003ceven\u003e number\n\n @tagged\n Examples: tagged\n | odd | even |\n | 1 | 2 |\n | 2 | 0 |\n | 3 | 11 |\n\n @tag2\n Examples:\n | odd | even |\n | 1 | 14 |\n | 3 | 9 |\n"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_outline.feature:13","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_outline.feature:13","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_outline.feature:14","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871,"status":"failed","summary":"2 is not odd"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_outline.feature:14","timestamp":-6795364578871,"status":"failed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_outline.feature:15","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871,"status":"failed","summary":"11 is not even"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_outline.feature:15","timestamp":-6795364578871,"status":"failed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_outline.feature:20","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_outline.feature:20","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_outline.feature:21","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:6","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:6","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:7","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_outline.feature:8","definition_id":"fmt_output_test.go:103 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef","arguments":[[4,5],[5,15]]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_outline.feature:8","timestamp":-6795364578871,"status":"failed","summary":"9 is not even"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_outline.feature:21","timestamp":-6795364578871,"status":"failed"}

Просмотреть файл

@ -0,0 +1,21 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/scenario_with_attachment.feature:1","source":"Feature: feature with attachment\n describes\n an attachment\n feature\n\n Scenario: scenario with attachment\n Given a step with a single attachment call for multiple attachments\n And a step with multiple attachment calls\n"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_with_attachment.feature:6","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_attachment.feature:7","definition_id":"fmt_output_test.go:XXX -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.stepWithSingleAttachmentCall","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"Before Scenario Attachment 1","mimeType":"text/plain","body":"BeforeScenarioAttachment"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"Before Step Attachment 3","mimeType":"text/plain","body":"BeforeStepAttachment"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"TheFilename1","mimeType":"text/plain","body":"TheData1"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"TheFilename2","mimeType":"text/plain","body":"TheData2"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"After Step Attachment 4","mimeType":"text/plain","body":"AfterStepAttachment"}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_attachment.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_attachment.feature:8","definition_id":"fmt_output_test.go:XXX -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.stepWithMultipleAttachmentCalls","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"Before Step Attachment 3","mimeType":"text/plain","body":"BeforeStepAttachment"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"TheFilename3","mimeType":"text/plain","body":"TheData1"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"TheFilename4","mimeType":"text/plain","body":"TheData2"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"After Step Attachment 4","mimeType":"text/plain","body":"AfterStepAttachment"}
{"event":"Attachment","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"contentEncoding":"BASE64","fileName":"After Scenario Attachment 2","mimeType":"text/plain","body":"AfterScenarioAttachment"}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_attachment.feature:8","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_with_attachment.feature:6","timestamp":-6795364578871,"status":"passed"}
{"event":"TestRunFinished","status":"passed","timestamp":-6795364578871,"snippets":"","memory":""}

Просмотреть файл

@ -1,16 +1,16 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/scenario_with_background.feature:1","source":"Feature: single scenario with background\n\n Background: named\n Given passing step\n And passing step\n\n Scenario: scenario\n When passing step\n Then passing step\n"}
{"event":"TestCaseStarted","location":"formatter-tests/features/scenario_with_background.feature:7","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:4","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:4","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_background.feature:4","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_background.feature:4","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:5","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:5","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_background.feature:5","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_background.feature:5","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:8","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:8","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_background.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_background.feature:8","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:9","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/scenario_with_background.feature:9","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/scenario_with_background.feature:9","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/scenario_with_background.feature:9","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseFinished","location":"formatter-tests/features/scenario_with_background.feature:7","timestamp":-6795364578871,"status":"passed"}

Просмотреть файл

@ -1,7 +1,7 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/single_scenario_with_passing_step.feature:1","source":"Feature: single passing scenario\n describes\n a single scenario\n feature\n\n Scenario: one step passing\n Given a passing step\n"}
{"event":"TestCaseStarted","location":"formatter-tests/features/single_scenario_with_passing_step.feature:6","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/single_scenario_with_passing_step.feature:7","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/single_scenario_with_passing_step.feature:7","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/single_scenario_with_passing_step.feature:7","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/single_scenario_with_passing_step.feature:7","timestamp":-6795364578871,"status":"passed"}
{"event":"TestCaseFinished","location":"formatter-tests/features/single_scenario_with_passing_step.feature:6","timestamp":-6795364578871,"status":"passed"}

Просмотреть файл

@ -1,29 +0,0 @@
{"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":"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}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:4","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:5","definition_id":"fmt_output_test.go:117 -\u003e github.com/cucumber/godog/internal/formatters_test.failingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:5","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:5","timestamp":-6795364578871,"status":"failed","summary":"step failed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:6","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:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:6","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:3","timestamp":-6795364578871,"status":"failed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:8","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:9","definition_id":"fmt_output_test.go:115 -\u003e github.com/cucumber/godog/internal/formatters_test.pendingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:9","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:9","timestamp":-6795364578871,"status":"pending"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:10","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:10","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:10","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:8","timestamp":-6795364578871,"status":"pending"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:12","timestamp":-6795364578871}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarions_including_failing.feature:13","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarions_including_failing.feature:13","timestamp":-6795364578871,"status":"undefined"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarions_including_failing.feature:14","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: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":"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":""}

Просмотреть файл

@ -0,0 +1,36 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/some_scenarios_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_scenarios_including_failing.feature:3","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:4","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:4","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:4","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:5","definition_id":"fmt_output_test.go:117 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:5","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:5","timestamp":-6795364578871,"status":"failed","summary":"step failed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:6","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:6","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:6","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:3","timestamp":-6795364578871,"status":"failed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:8","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:9","definition_id":"fmt_output_test.go:115 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.pendingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:9","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:9","timestamp":-6795364578871,"status":"pending"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:10","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:10","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:10","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:8","timestamp":-6795364578871,"status":"pending"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:12","timestamp":-6795364578871}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:13","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:13","timestamp":-6795364578871,"status":"undefined"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:14","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:14","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:14","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:12","timestamp":-6795364578871,"status":"undefined"}
{"event":"TestCaseStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:16","timestamp":-6795364578871}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:17","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:17","timestamp":-6795364578871,"status":"ambiguous","summary":"ambiguous step definition, step text: ambiguous step\n matches:\n ^ambiguous step.*$\n ^ambiguous step$"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/some_scenarios_including_failing.feature:18","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/some_scenarios_including_failing.feature:18","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/some_scenarios_including_failing.feature:18","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/some_scenarios_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":""}

Просмотреть файл

@ -1,27 +1,27 @@
{"event":"TestRunStarted","version":"0.1.0","timestamp":-6795364578871,"suite":"events"}
{"event":"TestSource","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:1","source":"Feature: two scenarios with background fail\n\n Background:\n Given passing step\n And failing step\n\n Scenario: one\n When passing step\n Then passing step\n\n Scenario: two\n Then passing step\n"}
{"event":"TestCaseStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:7","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","definition_id":"fmt_output_test.go:117 -\u003e github.com/cucumber/godog/internal/formatters_test.failingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","definition_id":"fmt_output_test.go:117 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","timestamp":-6795364578871,"status":"failed","summary":"step failed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:8","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:8","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:8","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:8","timestamp":-6795364578871,"status":"skipped"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:9","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:9","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:9","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:9","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:7","timestamp":-6795364578871,"status":"failed"}
{"event":"TestCaseStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:11","timestamp":-6795364578871}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:4","timestamp":-6795364578871,"status":"passed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","definition_id":"fmt_output_test.go:117 -\u003e github.com/cucumber/godog/internal/formatters_test.failingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","definition_id":"fmt_output_test.go:117 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:5","timestamp":-6795364578871,"status":"failed","summary":"step failed"}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:12","definition_id":"fmt_output_test.go:101 -\u003e github.com/cucumber/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"StepDefinitionFound","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:12","definition_id":"fmt_output_test.go:101 -\u003e git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef","arguments":[]}
{"event":"TestStepStarted","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:12","timestamp":-6795364578871}
{"event":"TestStepFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:12","timestamp":-6795364578871,"status":"skipped"}
{"event":"TestCaseFinished","location":"formatter-tests/features/two_scenarios_with_background_fail.feature:11","timestamp":-6795364578871,"status":"failed"}

Просмотреть файл

@ -0,0 +1,8 @@
Feature: feature with attachment
describes
an attachment
feature
Scenario: scenario with attachment
Given a step with a single attachment call for multiple attachments
And a step with multiple attachment calls

Просмотреть файл

@ -12,3 +12,7 @@ Feature: some scenarios
Scenario: undefined
When undefined
Then passing step
Scenario: ambiguous
When ambiguous step
Then passing step

Просмотреть файл

@ -1,9 +1,9 @@
<bold-white>Feature:</bold-white> outline
<bold-white>Scenario Outline:</bold-white> outline <bold-black># formatter-tests/features/scenario_outline.feature:5</bold-black>
<cyan>Given</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>odd </cyan><bold-cyan><odd></bold-cyan><cyan> and even </cyan><bold-cyan><even></bold-cyan><cyan> number</cyan> <bold-black># fmt_output_test.go:103 -> github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef</bold-black>
<cyan>Given</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>odd </cyan><bold-cyan><odd></bold-cyan><cyan> and even </cyan><bold-cyan><even></bold-cyan><cyan> number</cyan> <bold-black># fmt_output_test.go:103 -> git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef</bold-black>
<bold-white>Examples:</bold-white> tagged
| <cyan>odd</cyan> | <cyan>even</cyan> |

Просмотреть файл

@ -1,12 +1,12 @@
<bold-white>Feature:</bold-white> single scenario with background
<bold-white>Background:</bold-white> named
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> scenario <bold-black># formatter-tests/features/scenario_with_background.feature:7</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
<testsuite name="single scenario with background" tests="1" skipped="0" failures="0" errors="0" time="0">

Просмотреть файл

@ -4,7 +4,7 @@
feature
<bold-white>Scenario:</bold-white> one step passing <bold-black># formatter-tests/features/single_scenario_with_passing_step.feature:6</bold-black>
<green>Given</green> <green>a passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Given</green> <green>a passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="junit,pretty" tests="1" skipped="0" failures="0" errors="0" time="0">
<testsuite name="single passing scenario" tests="1" skipped="0" failures="0" errors="0" time="0">

Просмотреть файл

@ -1,54 +0,0 @@
<bold-white>Feature:</bold-white> some scenarios
<bold-white>Scenario:</bold-white> failing <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:3</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<red>When</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> github.com/cucumber/godog/internal/formatters_test.failingStepDef</bold-black>
<bold-red>step failed</bold-red>
<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> pending <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:8</bold-black>
<yellow>When</yellow> <yellow>pending step</yellow> <bold-black># fmt_output_test.go:115 -> github.com/cucumber/godog/internal/formatters_test.pendingStepDef</bold-black>
<yellow>TODO: write pending definition</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> undefined <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:12</bold-black>
<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>
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="junit,pretty" tests="3" skipped="0" failures="1" errors="2" time="0">
<testsuite name="some scenarios" tests="3" 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>
</testcase>
<testcase name="pending" status="pending" time="0">
<error message="Step pending step: TODO: write pending definition" type="pending"></error>
<error message="Step passing step" type="skipped"></error>
</testcase>
<testcase name="undefined" status="undefined" time="0">
<error message="Step undefined" type="undefined"></error>
<error message="Step passing step" type="skipped"></error>
</testcase>
</testsuite>
</testsuites>
--- <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>)
0s
<yellow>You can implement step definitions for undefined steps with these snippets:</yellow>
<yellow>
func undefined() error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^undefined$`, undefined)
}
</yellow>

Просмотреть файл

@ -0,0 +1,66 @@
<bold-white>Feature:</bold-white> some scenarios
<bold-white>Scenario:</bold-white> failing <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:3</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<red>When</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef</bold-black>
<bold-red>step failed</bold-red>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> pending <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:8</bold-black>
<yellow>When</yellow> <yellow>pending step</yellow> <bold-black># fmt_output_test.go:115 -> git.golang1.ru/softonik/godog/internal/formatters_test.pendingStepDef</bold-black>
<yellow>TODO: write pending definition</yellow>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> undefined <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:12</bold-black>
<yellow>When</yellow> <yellow>undefined</yellow>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> ambiguous <bold-black># formatter-tests/features/some_scenarios_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:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="junit,pretty" 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>
</testcase>
<testcase name="pending" status="pending" time="0">
<error message="Step pending step: TODO: write pending definition" type="pending"></error>
<error message="Step passing step" type="skipped"></error>
</testcase>
<testcase name="undefined" status="undefined" time="0">
<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>
--- <red>Failed steps:</red>
<red>Scenario: failing</red> <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:3</bold-black>
<red>When failing step</red> <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:5</bold-black>
<red>Error: </red><bold-red>step failed</bold-red>
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>
<yellow>
func undefined() error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^undefined$`, undefined)
}
</yellow>

Просмотреть файл

@ -1,16 +1,16 @@
<bold-white>Feature:</bold-white> two scenarios with background fail
<bold-white>Background:</bold-white>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<red>And</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> github.com/cucumber/godog/internal/formatters_test.failingStepDef</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<red>And</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef</bold-black>
<bold-red>step failed</bold-red>
<bold-white>Scenario:</bold-white> one <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:7</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> two <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:11</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="junit,pretty" tests="2" skipped="0" failures="2" errors="0" time="0">
<testsuite name="two scenarios with background fail" tests="2" skipped="0" failures="2" errors="0" time="0">

Просмотреть файл

@ -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>
@ -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>

Просмотреть файл

@ -1,28 +1,28 @@
<bold-white>Feature:</bold-white> rules with examples with backgrounds
<bold-white>Background:</bold-white> for first rule
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Example:</bold-white> rule 1 example 1 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:9</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Example:</bold-white> rule 1 example 2 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:13</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Background:</bold-white> for second rule
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Example:</bold-white> rule 1 example 1 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:24</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Example:</bold-white> rule 2 example 2 <bold-black># formatter-tests/features/rules_with_examples_with_backgrounds.feature:28</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
4 scenarios (<green>4 passed</green>)
16 steps (<green>16 passed</green>)

Просмотреть файл

@ -1,9 +1,9 @@
<bold-white>Feature:</bold-white> outline
<bold-white>Scenario Outline:</bold-white> outline <bold-black># formatter-tests/features/scenario_outline.feature:5</bold-black>
<cyan>Given</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>odd </cyan><bold-cyan><odd></bold-cyan><cyan> and even </cyan><bold-cyan><even></bold-cyan><cyan> number</cyan> <bold-black># fmt_output_test.go:103 -> github.com/cucumber/godog/internal/formatters_test.oddEvenStepDef</bold-black>
<cyan>Given</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>odd </cyan><bold-cyan><odd></bold-cyan><cyan> and even </cyan><bold-cyan><even></bold-cyan><cyan> number</cyan> <bold-black># fmt_output_test.go:103 -> git.golang1.ru/softonik/godog/internal/formatters_test.oddEvenStepDef</bold-black>
<bold-white>Examples:</bold-white> tagged
| <cyan>odd</cyan> | <cyan>even</cyan> |

Просмотреть файл

@ -1,12 +1,12 @@
<bold-white>Feature:</bold-white> single scenario with background
<bold-white>Background:</bold-white> named
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>And</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> scenario <bold-black># formatter-tests/features/scenario_with_background.feature:7</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>When</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Then</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
1 scenarios (<green>1 passed</green>)
4 steps (<green>4 passed</green>)

Просмотреть файл

@ -4,7 +4,7 @@
feature
<bold-white>Scenario:</bold-white> one step passing <bold-black># formatter-tests/features/single_scenario_with_passing_step.feature:6</bold-black>
<green>Given</green> <green>a passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<green>Given</green> <green>a passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
1 scenarios (<green>1 passed</green>)
1 steps (<green>1 passed</green>)

Просмотреть файл

@ -1,38 +0,0 @@
<bold-white>Feature:</bold-white> some scenarios
<bold-white>Scenario:</bold-white> failing <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:3</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<red>When</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> github.com/cucumber/godog/internal/formatters_test.failingStepDef</bold-black>
<bold-red>step failed</bold-red>
<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> pending <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:8</bold-black>
<yellow>When</yellow> <yellow>pending step</yellow> <bold-black># fmt_output_test.go:115 -> github.com/cucumber/godog/internal/formatters_test.pendingStepDef</bold-black>
<yellow>TODO: write pending definition</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> undefined <bold-black># formatter-tests/features/some_scenarions_including_failing.feature:12</bold-black>
<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>
--- <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>)
0s
<yellow>You can implement step definitions for undefined steps with these snippets:</yellow>
<yellow>
func undefined() error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^undefined$`, undefined)
}
</yellow>

Просмотреть файл

@ -0,0 +1,46 @@
<bold-white>Feature:</bold-white> some scenarios
<bold-white>Scenario:</bold-white> failing <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:3</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<red>When</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef</bold-black>
<bold-red>step failed</bold-red>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> pending <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:8</bold-black>
<yellow>When</yellow> <yellow>pending step</yellow> <bold-black># fmt_output_test.go:115 -> git.golang1.ru/softonik/godog/internal/formatters_test.pendingStepDef</bold-black>
<yellow>TODO: write pending definition</yellow>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> undefined <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:12</bold-black>
<yellow>When</yellow> <yellow>undefined</yellow>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> ambiguous <bold-black># formatter-tests/features/some_scenarios_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 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
--- <red>Failed steps:</red>
<red>Scenario: failing</red> <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:3</bold-black>
<red>When failing step</red> <bold-black># formatter-tests/features/some_scenarios_including_failing.feature:5</bold-black>
<red>Error: </red><bold-red>step failed</bold-red>
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>
<yellow>
func undefined() error {
return godog.ErrPending
}
func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^undefined$`, undefined)
}
</yellow>

Просмотреть файл

@ -1,16 +1,16 @@
<bold-white>Feature:</bold-white> two scenarios with background fail
<bold-white>Background:</bold-white>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<red>And</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> github.com/cucumber/godog/internal/formatters_test.failingStepDef</bold-black>
<green>Given</green> <green>passing step</green> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<red>And</red> <red>failing step</red> <bold-black># fmt_output_test.go:117 -> git.golang1.ru/softonik/godog/internal/formatters_test.failingStepDef</bold-black>
<bold-red>step failed</bold-red>
<bold-white>Scenario:</bold-white> one <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:7</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>When</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
<bold-white>Scenario:</bold-white> two <bold-black># formatter-tests/features/two_scenarios_with_background_fail.feature:11</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> github.com/cucumber/godog/internal/formatters_test.passingStepDef</bold-black>
<cyan>Then</cyan> <cyan>passing step</cyan> <bold-black># fmt_output_test.go:101 -> git.golang1.ru/softonik/godog/internal/formatters_test.passingStepDef</bold-black>
--- <red>Failed steps:</red>

Просмотреть файл

@ -1,15 +1,15 @@
<green>.</green><red>F</red><cyan>-</cyan><yellow>P</yellow><cyan>-</cyan><yellow>U</yellow><cyan>-</cyan> 7
<green>.</green><red>F</red><cyan>-</cyan><yellow>P</yellow><cyan>-</cyan><yellow>U</yellow><cyan>-</cyan><yellow>A</yellow><cyan>-</cyan> 9
--- <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>Scenario: failing</red><bold-black> # formatter-tests/features/some_scenarios_including_failing.feature:3</bold-black>
<red>When failing step</red><bold-black> # formatter-tests/features/some_scenarios_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>

Просмотреть файл

@ -13,7 +13,7 @@ import (
// some snippet formatting regexps
var snippetExprCleanup = regexp.MustCompile(`([\/\[\]\(\)\\^\$\.\|\?\*\+\'])`)
var snippetExprQuoted = regexp.MustCompile(`(\W|^)"(?:[^"]*)"(\W|$)`)
var snippetMethodName = regexp.MustCompile(`[^a-zA-Z\_\ ]`)
var snippetMethodName = regexp.MustCompile("[^a-zA-Zа-яА-ЯёЁ\\_\\ ]")
var snippetNumbers = regexp.MustCompile(`(\d+)`)
var snippetHelperFuncs = template.FuncMap{

Просмотреть файл

@ -4,7 +4,7 @@ import (
"testing"
"time"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/internal/utils"
)
// this zeroes the time throughout whole test suite

Просмотреть файл

@ -3,8 +3,8 @@ package models_test
import (
"testing"
"github.com/cucumber/godog/internal/models"
"github.com/cucumber/godog/internal/testutils"
"git.golang1.ru/softonik/godog/internal/models"
"git.golang1.ru/softonik/godog/internal/testutils"
"github.com/stretchr/testify/assert"
)

Просмотреть файл

@ -3,8 +3,8 @@ package models
import (
"time"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/utils"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/utils"
)
// TestRunStarted ...
@ -18,6 +18,13 @@ type PickleResult struct {
StartedAt time.Time
}
// PickleAttachment ...
type PickleAttachment struct {
Name string
MimeType string
Data []byte
}
// PickleStepResult ...
type PickleStepResult struct {
Status StepResultStatus
@ -28,6 +35,8 @@ type PickleStepResult struct {
PickleStepID string
Def *StepDefinition
Attachments []PickleAttachment
}
// NewStepResult ...
@ -35,6 +44,7 @@ func NewStepResult(
status StepResultStatus,
pickleID, pickleStepID string,
match *StepDefinition,
attachments []PickleAttachment,
err error,
) PickleStepResult {
return PickleStepResult{
@ -44,6 +54,7 @@ func NewStepResult(
PickleID: pickleID,
PickleStepID: pickleStepID,
Def: match,
Attachments: attachments,
}
}
@ -61,6 +72,8 @@ const (
Undefined
// Pending ...
Pending
// Ambiguous ...
Ambiguous
)
// Color ...
@ -90,6 +103,8 @@ func (st StepResultStatus) String() string {
return "undefined"
case Pending:
return "pending"
case Ambiguous:
return "ambiguous"
default:
return "unknown"
}

Просмотреть файл

@ -1,12 +1,13 @@
package models_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/cucumber/godog/colors"
"github.com/cucumber/godog/internal/models"
"git.golang1.ru/softonik/godog/colors"
"git.golang1.ru/softonik/godog/internal/models"
)
type stepResultStatusTestCase struct {
@ -21,6 +22,7 @@ var stepResultStatusTestCases = []stepResultStatusTestCase{
{st: models.Skipped, str: "skipped", clr: colors.Cyan},
{st: models.Undefined, str: "undefined", clr: colors.Yellow},
{st: models.Pending, str: "pending", clr: colors.Yellow},
{st: models.Ambiguous, str: "ambiguous", clr: colors.Yellow},
{st: -1, str: "unknown", clr: colors.Yellow},
}
@ -32,3 +34,21 @@ func Test_StepResultStatus(t *testing.T) {
})
}
}
func Test_NewStepResuklt(t *testing.T) {
status := models.StepResultStatus(123)
pickleID := "pickleId"
pickleStepID := "pickleStepID"
match := &models.StepDefinition{}
attachments := make([]models.PickleAttachment, 0)
err := fmt.Errorf("intentional")
results := models.NewStepResult(status, pickleID, pickleStepID, match, attachments, err)
assert.Equal(t, status, results.Status)
assert.Equal(t, pickleID, results.PickleID)
assert.Equal(t, pickleStepID, results.PickleStepID)
assert.Equal(t, match, results.Def)
assert.Equal(t, attachments, results.Attachments)
assert.Equal(t, err, results.Err)
}

Просмотреть файл

@ -9,16 +9,16 @@ import (
messages "github.com/cucumber/messages/go/v21"
"github.com/cucumber/godog/formatters"
"git.golang1.ru/softonik/godog/formatters"
)
var typeOfBytes = reflect.TypeOf([]byte(nil))
// matchable errors
var (
ErrUnmatchedStepArgumentNumber = errors.New("func received more arguments than expected")
ErrUnmatchedStepArgumentNumber = errors.New("func expected more arguments than given")
ErrCannotConvert = errors.New("cannot convert argument")
ErrUnsupportedArgumentType = errors.New("unsupported argument type")
ErrUnsupportedParameterType = errors.New("func has unsupported parameter type")
)
// StepDefinition ...
@ -36,6 +36,9 @@ type StepDefinition struct {
var typeOfContext = reflect.TypeOf((*context.Context)(nil)).Elem()
// Run a step with the matched arguments using reflect
// Returns one of ...
// (context, error)
// (context, godog.Steps)
func (sd *StepDefinition) Run(ctx context.Context) (context.Context, interface{}) {
var values []reflect.Value
@ -51,7 +54,7 @@ func (sd *StepDefinition) Run(ctx context.Context) (context.Context, interface{}
}
if len(sd.Args) < numIn {
return ctx, fmt.Errorf("%w: expected %d arguments, matched %d from step", ErrUnmatchedStepArgumentNumber, typ.NumIn(), len(sd.Args))
return ctx, fmt.Errorf("%w: expected %d arguments, matched %d from step", ErrUnmatchedStepArgumentNumber, numIn, len(sd.Args))
}
for i := 0; i < numIn; i++ {
@ -161,7 +164,8 @@ func (sd *StepDefinition) Run(ctx context.Context) (context.Context, interface{}
return ctx, fmt.Errorf(`%w %d: "%v" of type "%T" to *messages.PickleTable`, ErrCannotConvert, i, arg, arg)
default:
return ctx, fmt.Errorf("%w: the argument %d type %T is not supported %s", ErrUnsupportedArgumentType, i, arg, param.Elem().String())
// the error here is that the declared function has an unsupported param type - really this ought to be trapped at registration ti,e
return ctx, fmt.Errorf("%w: the data type of parameter %d type *%s is not supported", ErrUnsupportedParameterType, i, param.Elem().String())
}
case reflect.Slice:
switch param {
@ -172,10 +176,13 @@ func (sd *StepDefinition) Run(ctx context.Context) (context.Context, interface{}
}
values = append(values, reflect.ValueOf([]byte(s)))
default:
return ctx, fmt.Errorf("%w: the slice argument %d type %s is not supported", ErrUnsupportedArgumentType, i, param.Kind())
// the problem is the function decl is not using a support slice type as the param
return ctx, fmt.Errorf("%w: the slice parameter %d type []%s is not supported", ErrUnsupportedParameterType, i, param.Elem().Kind())
}
case reflect.Struct:
return ctx, fmt.Errorf("%w: the struct parameter %d type %s is not supported", ErrUnsupportedParameterType, i, param.String())
default:
return ctx, fmt.Errorf("%w: the argument %d type %s is not supported", ErrUnsupportedArgumentType, i, param.Kind())
return ctx, fmt.Errorf("%w: the parameter %d type %s is not supported", ErrUnsupportedParameterType, i, param.Kind())
}
}
@ -184,17 +191,43 @@ func (sd *StepDefinition) Run(ctx context.Context) (context.Context, interface{}
return ctx, nil
}
if len(res) == 1 {
r := res[0].Interface()
// Note that the step fn return types were validated at Initialise in test_context.go stepWithKeyword()
if ctx, ok := r.(context.Context); ok {
// single return value may be one of ...
// error
// context.Context
// godog.Steps
result0 := res[0].Interface()
if len(res) == 1 {
// if the single return value is a context then just return it
if ctx, ok := result0.(context.Context); ok {
return ctx, nil
}
return ctx, res[0].Interface()
// return type is presumably one of nil, "error" or "Steps" so place it into second return position
return ctx, result0
}
return res[0].Interface().(context.Context), res[1].Interface()
// multi-value value return must be
// (context, error) and the context value must not be nil
if ctx, ok := result0.(context.Context); ok {
return ctx, res[1].Interface()
}
result1 := res[1].Interface()
errMsg := ""
if result1 != nil {
errMsg = fmt.Sprintf(", step def also returned an error: %v", result1)
}
text := sd.StepDefinition.Expr.String()
if result0 == nil {
panic(fmt.Sprintf("step definition '%v' with return type (context.Context, error) must not return <nil> for the context.Context value%s", text, errMsg))
}
panic(fmt.Errorf("step definition '%v' has return type (context.Context, error), but found %v rather than a context.Context value%s", text, result0, errMsg))
}
func (sd *StepDefinition) shouldBeString(idx int) (string, error) {

Просмотреть файл

@ -5,23 +5,105 @@ import (
"errors"
"fmt"
"reflect"
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/cucumber/godog"
"github.com/cucumber/godog/formatters"
"github.com/cucumber/godog/internal/models"
"git.golang1.ru/softonik/godog"
"git.golang1.ru/softonik/godog/formatters"
"git.golang1.ru/softonik/godog/internal/models"
messages "github.com/cucumber/messages/go/v21"
)
type ctxKey string
func TestShouldSupportContext(t *testing.T) {
func TestShouldSupportVoidHandlerReturn(t *testing.T) {
wasCalled := false
initialCtx := context.WithValue(context.Background(), ctxKey("original"), 123)
fn := func(ctx context.Context) {
wasCalled = true
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{}
ctx, err := def.Run(initialCtx)
assert.True(t, wasCalled)
// ctx is passed thru
assert.Equal(t, initialCtx, ctx)
assert.Nil(t, err)
}
func TestShouldSupportNilContextReturn(t *testing.T) {
initialCtx := context.WithValue(context.Background(), ctxKey("original"), 123)
wasCalled := false
fn := func(ctx context.Context) context.Context {
wasCalled = true
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
// nil context is permitted if is single return value
return nil
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{}
ctx, err := def.Run(initialCtx)
assert.True(t, wasCalled)
// original context is substituted for a nil return value
// << JL : IS THIS A BUG? TWO ARG API DOESN'T ALLOW THIS
assert.Equal(t, initialCtx, ctx)
assert.Nil(t, err)
}
func TestShouldSupportNilErrorReturn(t *testing.T) {
initialCtx := context.WithValue(context.Background(), ctxKey("original"), 123)
wasCalled := false
fn := func(ctx context.Context) error {
wasCalled = true
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
// nil error is permitted
return nil
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{}
ctx, err := def.Run(initialCtx)
assert.True(t, wasCalled)
// original context is passed thru if method doesn't return context.
assert.Equal(t, initialCtx, ctx)
assert.Nil(t, err)
}
func TestShouldSupportContextReturn(t *testing.T) {
ctx := context.WithValue(context.Background(), ctxKey("original"), 123)
fn := func(ctx context.Context, a int64, b int32, c int16, d int8) context.Context {
fn := func(ctx context.Context) context.Context {
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
return context.WithValue(ctx, ctxKey("updated"), 321)
@ -34,18 +116,69 @@ func TestShouldSupportContext(t *testing.T) {
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1", "1", "1", "1"}
def.Args = []interface{}{}
ctx, err := def.Run(ctx)
assert.Nil(t, err)
// converys the context
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
assert.Equal(t, 321, ctx.Value(ctxKey("updated")))
}
func TestShouldSupportContextAndError(t *testing.T) {
func TestShouldSupportErrorReturn(t *testing.T) {
ctx := context.WithValue(context.Background(), ctxKey("original"), 123)
expectedErr := fmt.Errorf("expected error")
fn := func(ctx context.Context) error {
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
return expectedErr
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{}
ctx, err := def.Run(ctx)
// conveys the returned error
assert.Equal(t, expectedErr, err)
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
}
func TestShouldSupportContextAndErrorReturn(t *testing.T) {
ctx := context.WithValue(context.Background(), ctxKey("original"), 123)
expectedErr := fmt.Errorf("expected error")
fn := func(ctx context.Context) (context.Context, error) {
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
return context.WithValue(ctx, ctxKey("updated"), 321), expectedErr
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{}
ctx, err := def.Run(ctx)
// conveys error and context
assert.Equal(t, expectedErr, err)
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
assert.Equal(t, 321, ctx.Value(ctxKey("updated")))
}
func TestShouldSupportContextAndNilErrorReturn(t *testing.T) {
ctx := context.WithValue(context.Background(), ctxKey("original"), 123)
fn := func(ctx context.Context, a int64, b int32, c int16, d int8) (context.Context, error) {
fn := func(ctx context.Context) (context.Context, error) {
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
return context.WithValue(ctx, ctxKey("updated"), 321), nil
@ -58,146 +191,54 @@ func TestShouldSupportContextAndError(t *testing.T) {
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1", "1", "1", "1"}
def.Args = []interface{}{}
ctx, err := def.Run(ctx)
// conveys nil error and context
assert.Nil(t, err)
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
assert.Equal(t, 321, ctx.Value(ctxKey("updated")))
}
func TestShouldSupportEmptyHandlerReturn(t *testing.T) {
fn := func(a int64, b int32, c int16, d int8) {}
func TestShouldRejectNilContextWhenMultiValueReturn(t *testing.T) {
ctx := context.WithValue(context.Background(), ctxKey("original"), 123)
fn := func(ctx context.Context) (context.Context, error) {
assert.Equal(t, 123, ctx.Value(ctxKey("original")))
// nil context is illegal.
return nil, fmt.Errorf("expected error")
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
Expr: regexp.MustCompile("some regex string"),
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1", "1", "1", "1"}
if _, err := def.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
def.Args = []interface{}{}
defer func() {
if e := recover(); e != nil {
pe := e.(string)
assert.Equal(t, "step definition 'some regex string' with return type (context.Context, error) must not return <nil> for the context.Context value, step def also returned an error: expected error", pe)
}
}()
def.Run(ctx)
assert.Fail(t, "should not get here")
}
def.Args = []interface{}{"1", "1", "1", strings.Repeat("1", 9)}
if _, err := def.Run(context.Background()); err == nil {
t.Fatalf("expected convertion fail for int8, but got none")
}
func TestArgumentCountChecks(t *testing.T) {
wasCalled := false
fn := func(a int, b int) {
wasCalled = true
}
func TestShouldSupportIntTypes(t *testing.T) {
fn := func(a int64, b int32, c int16, d int8) error { return nil }
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1", "1", "1", "1"}
if _, err := def.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
def.Args = []interface{}{"1", "1", "1", strings.Repeat("1", 9)}
if _, err := def.Run(context.Background()); err == nil {
t.Fatalf("expected convertion fail for int8, but got none")
}
}
func TestShouldSupportFloatTypes(t *testing.T) {
fn := func(a float64, b float32) error { return nil }
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1.1", "1.09"}
if _, err := def.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
def.Args = []interface{}{"1.08", strings.Repeat("1", 65) + ".67"}
if _, err := def.Run(context.Background()); err == nil {
t.Fatalf("expected convertion fail for float32, but got none")
}
}
func TestShouldNotSupportOtherPointerTypesThanGherkin(t *testing.T) {
fn1 := func(a *int) error { return nil }
fn2 := func(a *messages.PickleDocString) error { return nil }
fn3 := func(a *messages.PickleTable) error { return nil }
def1 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn1,
},
HandlerValue: reflect.ValueOf(fn1),
Args: []interface{}{(*int)(nil)},
}
def2 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn2,
},
HandlerValue: reflect.ValueOf(fn2),
Args: []interface{}{&messages.PickleDocString{}},
}
def3 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn3,
},
HandlerValue: reflect.ValueOf(fn3),
Args: []interface{}{(*messages.PickleTable)(nil)},
}
if _, err := def1.Run(context.Background()); err == nil {
t.Fatalf("expected conversion error, but got none")
}
if _, err := def2.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, err := def3.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
}
func TestShouldSupportOnlyByteSlice(t *testing.T) {
fn1 := func(a []byte) error { return nil }
fn2 := func(a []string) error { return nil }
def1 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn1,
},
HandlerValue: reflect.ValueOf(fn1),
Args: []interface{}{"str"},
}
def2 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn2,
},
HandlerValue: reflect.ValueOf(fn2),
Args: []interface{}{[]string{}},
}
if _, err := def1.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, err := def2.Run(context.Background()); err == nil {
t.Fatalf("expected conversion error, but got none")
}
}
func TestUnexpectedArguments(t *testing.T) {
fn := func(a, b int) error { return nil }
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
@ -206,24 +247,24 @@ func TestUnexpectedArguments(t *testing.T) {
}
def.Args = []interface{}{"1"}
_, err := def.Run(context.Background())
assert.False(t, wasCalled)
assert.Equal(t, `func expected more arguments than given: expected 2 arguments, matched 1 from step`, err.(error).Error())
assert.True(t, errors.Is(err.(error), models.ErrUnmatchedStepArgumentNumber))
_, res := def.Run(context.Background())
if res == nil {
t.Fatalf("expected an error due to wrong number of arguments, but got none")
// FIXME - extra args are ignored - but should be reported at runtime
def.Args = []interface{}{"1", "2", "IGNORED-EXTRA-ARG"}
_, err = def.Run(context.Background())
assert.True(t, wasCalled)
assert.Nil(t, err)
}
err, ok := res.(error)
if !ok {
t.Fatalf("expected an error due to wrong number of arguments, but got %T instead", res)
func TestArgumentCountChecksWithContext(t *testing.T) {
wasCalled := false
fn := func(ctx context.Context, a int, b int) {
wasCalled = true
}
if !errors.Is(err, models.ErrUnmatchedStepArgumentNumber) {
t.Fatalf("expected an error due to wrong number of arguments, but got %v instead", err)
}
}
func TestStepDefinition_Run_StepShouldBeString(t *testing.T) {
test := func(t *testing.T, fn interface{}) {
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
@ -231,6 +272,171 @@ func TestStepDefinition_Run_StepShouldBeString(t *testing.T) {
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1"}
_, err := def.Run(context.Background())
assert.False(t, wasCalled)
assert.Equal(t, `func expected more arguments than given: expected 2 arguments, matched 1 from step`, err.(error).Error())
assert.True(t, errors.Is(err.(error), models.ErrUnmatchedStepArgumentNumber))
}
func TestShouldSupportIntTypes(t *testing.T) {
var aActual int64
var bActual int32
var cActual int16
var dActual int8
fn := func(a int64, b int32, c int16, d int8) {
aActual = a
bActual = b
cActual = c
dActual = d
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1", "2", "3", "4"}
_, err := def.Run(context.Background())
assert.Nil(t, err)
assert.Equal(t, int64(1), aActual)
assert.Equal(t, int32(2), bActual)
assert.Equal(t, int16(3), cActual)
assert.Equal(t, int8(4), dActual)
// 128 doesn't fit in signed 8bit int
def.Args = []interface{}{"1", "2", "3", "128"}
_, err = def.Run(context.Background())
assert.Equal(t, `cannot convert argument 3: "128" to int8: strconv.ParseInt: parsing "128": value out of range`, err.(error).Error())
def.Args = []interface{}{"1", "2", "99999", "4"}
_, err = def.Run(context.Background())
assert.Equal(t, `cannot convert argument 2: "99999" to int16: strconv.ParseInt: parsing "99999": value out of range`, err.(error).Error())
def.Args = []interface{}{"1", strings.Repeat("2", 32), "3", "4"}
_, err = def.Run(context.Background())
assert.Equal(t, `cannot convert argument 1: "22222222222222222222222222222222" to int32: strconv.ParseInt: parsing "22222222222222222222222222222222": value out of range`, err.(error).Error())
def.Args = []interface{}{strings.Repeat("1", 32), "2", "3", "4"}
_, err = def.Run(context.Background())
assert.Equal(t, `cannot convert argument 0: "11111111111111111111111111111111" to int64: strconv.ParseInt: parsing "11111111111111111111111111111111": value out of range`, err.(error).Error())
}
func TestShouldSupportFloatTypes(t *testing.T) {
var aActual float64
var bActual float32
fn := func(a float64, b float32) {
aActual = a
bActual = b
}
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
def.Args = []interface{}{"1.1", "2.2"}
_, err := def.Run(context.Background())
assert.Nil(t, err)
assert.Equal(t, float64(1.1), aActual)
assert.Equal(t, float32(2.2), bActual)
def.Args = []interface{}{"1.1", strings.Repeat("2", 65) + ".22"}
_, err = def.Run(context.Background())
assert.Equal(t, `cannot convert argument 1: "22222222222222222222222222222222222222222222222222222222222222222.22" to float32: strconv.ParseFloat: parsing "22222222222222222222222222222222222222222222222222222222222222222.22": value out of range`, err.(error).Error())
}
func TestShouldSupportGherkinDocstring(t *testing.T) {
var actualDocString *messages.PickleDocString
fnDocstring := func(a *messages.PickleDocString) {
actualDocString = a
}
expectedDocString := &messages.PickleDocString{Content: "hello"}
defDocstring := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fnDocstring,
},
HandlerValue: reflect.ValueOf(fnDocstring),
Args: []interface{}{expectedDocString},
}
_, err := defDocstring.Run(context.Background())
assert.Nil(t, err)
assert.Equal(t, expectedDocString, actualDocString)
}
func TestShouldSupportGherkinTable(t *testing.T) {
var actualTable *messages.PickleTable
fnTable := func(a *messages.PickleTable) {
actualTable = a
}
expectedTable := &messages.PickleTable{}
defTable := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fnTable,
},
HandlerValue: reflect.ValueOf(fnTable),
Args: []interface{}{expectedTable},
}
_, err := defTable.Run(context.Background())
assert.Nil(t, err)
assert.Equal(t, expectedTable, actualTable)
}
func TestShouldSupportOnlyByteSlice(t *testing.T) {
var aActual []byte
fn1 := func(a []byte) {
aActual = a
}
fn2 := func(a []string) {
assert.Fail(t, "fn2 should not be called")
}
def1 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn1,
},
HandlerValue: reflect.ValueOf(fn1),
Args: []interface{}{"str"},
}
def2 := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn2,
},
HandlerValue: reflect.ValueOf(fn2),
Args: []interface{}{[]string{}},
}
_, err := def1.Run(context.Background())
assert.Nil(t, err)
assert.Equal(t, []byte{'s', 't', 'r'}, aActual)
_, err = def2.Run(context.Background())
assert.Equal(t, `func has unsupported parameter type: the slice parameter 0 type []string is not supported`, err.(error).Error())
assert.True(t, errors.Is(err.(error), models.ErrUnsupportedParameterType))
}
// this test is superficial compared to the ones above where the actual error messages the user woudl see are verified
func TestStepDefinition_Run_StepArgsShouldBeString(t *testing.T) {
test := func(t *testing.T, fn interface{}, expectedError string) {
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
},
HandlerValue: reflect.ValueOf(fn),
}
// some value that is not a string
def.Args = []interface{}{12}
_, res := def.Run(context.Background())
@ -246,26 +452,30 @@ func TestStepDefinition_Run_StepShouldBeString(t *testing.T) {
if !errors.Is(err, models.ErrCannotConvert) {
t.Fatalf("expected a string convertion error, but got '%v' instead", err)
}
assert.Equal(t, expectedError, err.Error())
}
// Ensure step type error if step argument is not a string
// for all supported types.
test(t, func(a int) error { return nil })
test(t, func(a int64) error { return nil })
test(t, func(a int32) error { return nil })
test(t, func(a int16) error { return nil })
test(t, func(a int8) error { return nil })
test(t, func(a string) error { return nil })
test(t, func(a float64) error { return nil })
test(t, func(a float32) error { return nil })
test(t, func(a *godog.Table) error { return nil })
test(t, func(a *godog.DocString) error { return nil })
test(t, func(a []byte) error { return nil })
const toStringError = `cannot convert argument 0: "12" of type "int" to string`
shouldNotBeCalled := func() { assert.Fail(t, "shound not be called") }
test(t, func(a int) { shouldNotBeCalled() }, toStringError)
test(t, func(a int64) { shouldNotBeCalled() }, toStringError)
test(t, func(a int32) { shouldNotBeCalled() }, toStringError)
test(t, func(a int16) { shouldNotBeCalled() }, toStringError)
test(t, func(a int8) { shouldNotBeCalled() }, toStringError)
test(t, func(a string) { shouldNotBeCalled() }, toStringError)
test(t, func(a float64) { shouldNotBeCalled() }, toStringError)
test(t, func(a float32) { shouldNotBeCalled() }, toStringError)
test(t, func(a *godog.Table) { shouldNotBeCalled() }, `cannot convert argument 0: "12" of type "int" to *messages.PickleTable`)
test(t, func(a *godog.DocString) { shouldNotBeCalled() }, `cannot convert argument 0: "12" of type "int" to *messages.PickleDocString`)
test(t, func(a []byte) { shouldNotBeCalled() }, toStringError)
}
func TestStepDefinition_Run_InvalidHandlerParamConversion(t *testing.T) {
test := func(t *testing.T, fn interface{}) {
test := func(t *testing.T, fn interface{}, expectedError string) {
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
@ -285,44 +495,49 @@ func TestStepDefinition_Run_InvalidHandlerParamConversion(t *testing.T) {
t.Fatalf("expected an unsupported argument type error, but got %T instead", res)
}
if !errors.Is(err, models.ErrUnsupportedArgumentType) {
if !errors.Is(err, models.ErrUnsupportedParameterType) {
// FIXME JL - check logic as the error message was wrong
t.Fatalf("expected an unsupported argument type error, but got '%v' instead", err)
}
assert.Equal(t, expectedError, err.Error())
}
shouldNotBeCalled := func() { assert.Fail(t, "shound not be called") }
// Lists some unsupported argument types for step handler.
// Pointers should work only for godog.Table/godog.DocString
test(t, func(a *int) error { return nil })
test(t, func(a *int64) error { return nil })
test(t, func(a *int32) error { return nil })
test(t, func(a *int16) error { return nil })
test(t, func(a *int8) error { return nil })
test(t, func(a *string) error { return nil })
test(t, func(a *float64) error { return nil })
test(t, func(a *float32) error { return nil })
test(t, func(a *int) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *int is not supported")
test(t, func(a *int64) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *int64 is not supported")
test(t, func(a *int32) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *int32 is not supported")
test(t, func(a *int16) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *int16 is not supported")
test(t, func(a *int8) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *int8 is not supported")
test(t, func(a *string) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *string is not supported")
test(t, func(a *float64) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *float64 is not supported")
test(t, func(a *float32) { shouldNotBeCalled() }, "func has unsupported parameter type: the data type of parameter 0 type *float32 is not supported")
// I cannot pass structures
test(t, func(a godog.Table) error { return nil })
test(t, func(a godog.DocString) error { return nil })
test(t, func(a testStruct) error { return nil })
test(t, func(a godog.Table) { shouldNotBeCalled() }, "func has unsupported parameter type: the struct parameter 0 type messages.PickleTable is not supported")
test(t, func(a godog.DocString) { shouldNotBeCalled() }, "func has unsupported parameter type: the struct parameter 0 type messages.PickleDocString is not supported")
test(t, func(a testStruct) { shouldNotBeCalled() }, "func has unsupported parameter type: the struct parameter 0 type models_test.testStruct is not supported")
// I cannot use maps
test(t, func(a map[string]interface{}) error { return nil })
test(t, func(a map[string]int) error { return nil })
// // I cannot use maps
test(t, func(a map[string]interface{ body() }) { shouldNotBeCalled() }, "func has unsupported parameter type: the parameter 0 type map is not supported")
test(t, func(a map[string]int) { shouldNotBeCalled() }, "func has unsupported parameter type: the parameter 0 type map is not supported")
// Slice works only for byte
test(t, func(a []int) error { return nil })
test(t, func(a []string) error { return nil })
test(t, func(a []bool) error { return nil })
// // Slice works only for byte
test(t, func(a []int) { shouldNotBeCalled() }, "func has unsupported parameter type: the slice parameter 0 type []int is not supported")
test(t, func(a []string) { shouldNotBeCalled() }, "func has unsupported parameter type: the slice parameter 0 type []string is not supported")
test(t, func(a []bool) { shouldNotBeCalled() }, "func has unsupported parameter type: the slice parameter 0 type []bool is not supported")
// I cannot use bool
test(t, func(a bool) error { return nil })
// // I cannot use bool
test(t, func(a bool) { shouldNotBeCalled() }, "func has unsupported parameter type: the parameter 0 type bool is not supported")
}
func TestStepDefinition_Run_StringConversionToFunctionType(t *testing.T) {
test := func(t *testing.T, fn interface{}, args []interface{}) {
test := func(t *testing.T, fn interface{}, args []interface{}, expectedError string) {
def := &models.StepDefinition{
StepDefinition: formatters.StepDefinition{
Handler: fn,
@ -344,26 +559,30 @@ func TestStepDefinition_Run_StringConversionToFunctionType(t *testing.T) {
if !errors.Is(err, models.ErrCannotConvert) {
t.Fatalf("expected a cannot convert argument type error, but got '%v' instead", err)
}
assert.Equal(t, expectedError, err.Error())
}
shouldNotBeCalled := func() { assert.Fail(t, "shound not be called") }
// Lists some unsupported argument types for step handler.
// Cannot convert invalid int
test(t, func(a int) error { return nil }, []interface{}{"a"})
test(t, func(a int64) error { return nil }, []interface{}{"a"})
test(t, func(a int32) error { return nil }, []interface{}{"a"})
test(t, func(a int16) error { return nil }, []interface{}{"a"})
test(t, func(a int8) error { return nil }, []interface{}{"a"})
test(t, func(a int) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to int: strconv.ParseInt: parsing "a": invalid syntax`)
test(t, func(a int64) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to int64: strconv.ParseInt: parsing "a": invalid syntax`)
test(t, func(a int32) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to int32: strconv.ParseInt: parsing "a": invalid syntax`)
test(t, func(a int16) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to int16: strconv.ParseInt: parsing "a": invalid syntax`)
test(t, func(a int8) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to int8: strconv.ParseInt: parsing "a": invalid syntax`)
// Cannot convert invalid float
test(t, func(a float32) error { return nil }, []interface{}{"a"})
test(t, func(a float64) error { return nil }, []interface{}{"a"})
test(t, func(a float32) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to float32: strconv.ParseFloat: parsing "a": invalid syntax`)
test(t, func(a float64) { shouldNotBeCalled() }, []interface{}{"a"}, `cannot convert argument 0: "a" to float64: strconv.ParseFloat: parsing "a": invalid syntax`)
// Cannot convert to DataArg
test(t, func(a *godog.Table) error { return nil }, []interface{}{"194"})
test(t, func(a *godog.Table) { shouldNotBeCalled() }, []interface{}{"194"}, `cannot convert argument 0: "194" of type "string" to *messages.PickleTable`)
// Cannot convert to DocString ?
test(t, func(a *godog.DocString) error { return nil }, []interface{}{"194"})
test(t, func(a *godog.DocString) { shouldNotBeCalled() }, []interface{}{"194"}, `cannot convert argument 0: "194" of type "string" to *messages.PickleDocString`)
}
@ -381,11 +600,9 @@ type testStruct struct {
}
func TestShouldSupportDocStringToStringConversion(t *testing.T) {
fn := func(a string) error {
if a != "hello" {
return fmt.Errorf("did not get hello")
}
return nil
var aActual string
fn := func(a string) {
aActual = a
}
def := &models.StepDefinition{
@ -398,7 +615,7 @@ func TestShouldSupportDocStringToStringConversion(t *testing.T) {
}},
}
if _, err := def.Run(context.Background()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
_, err := def.Run(context.Background())
assert.Nil(t, err)
assert.Equal(t, "hello", aActual)
}

Показаны не все изменённые файлы, т.к. их слишком много Показать больше