Merge pull request #326 from cucumber/internal-parser-pkg
Added an internal package for tags filtering
Этот коммит содержится в:
коммит
4da375f4c0
7 изменённых файлов: 124 добавлений и 97 удалений
|
@ -32,13 +32,12 @@ commands:
|
||||||
vet:
|
vet:
|
||||||
description: "Run go vet"
|
description: "Run go vet"
|
||||||
steps:
|
steps:
|
||||||
- run: go vet github.com/cucumber/godog
|
- run: go vet ./...
|
||||||
- run: go vet github.com/cucumber/godog/colors
|
|
||||||
go_test:
|
go_test:
|
||||||
description: "Run go test"
|
description: "Run go test"
|
||||||
steps:
|
steps:
|
||||||
- run: sed -i 's#github.com/cucumber/godog_test#_test#g' formatter-tests/*/*
|
- run: sed -i 's#github.com/cucumber/godog_test#_test#g' formatter-tests/*/*
|
||||||
- run: go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
- run: go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
|
||||||
godog:
|
godog:
|
||||||
description: "Run godog"
|
description: "Run godog"
|
||||||
steps:
|
steps:
|
||||||
|
|
62
internal/tags/tag_filter.go
Обычный файл
62
internal/tags/tag_filter.go
Обычный файл
|
@ -0,0 +1,62 @@
|
||||||
|
package tags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cucumber/messages-go/v10"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApplyTagFilter will apply a filter string on the
|
||||||
|
// array of pickles and returned the filtered list.
|
||||||
|
func ApplyTagFilter(filter string, pickles []*messages.Pickle) []*messages.Pickle {
|
||||||
|
if filter == "" {
|
||||||
|
return pickles
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []*messages.Pickle{}
|
||||||
|
|
||||||
|
for _, pickle := range pickles {
|
||||||
|
if match(filter, pickle.Tags) {
|
||||||
|
result = append(result, pickle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on http://behat.readthedocs.org/en/v2.5/guides/6.cli.html#gherkin-filters
|
||||||
|
func match(filter string, tags []*messages.Pickle_PickleTag) (ok bool) {
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
for _, andTags := range strings.Split(filter, "&&") {
|
||||||
|
var okComma bool
|
||||||
|
|
||||||
|
for _, tag := range strings.Split(andTags, ",") {
|
||||||
|
tag = strings.TrimSpace(tag)
|
||||||
|
tag = strings.Replace(tag, "@", "", -1)
|
||||||
|
|
||||||
|
okComma = contains(tags, tag) || okComma
|
||||||
|
|
||||||
|
if tag[0] == '~' {
|
||||||
|
tag = tag[1:]
|
||||||
|
okComma = !contains(tags, tag) || okComma
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = ok && okComma
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(tags []*messages.Pickle_PickleTag, tag string) bool {
|
||||||
|
for _, t := range tags {
|
||||||
|
tagName := strings.Replace(t.Name, "@", "", -1)
|
||||||
|
|
||||||
|
if tagName == tag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
51
internal/tags/tag_filter_test.go
Обычный файл
51
internal/tags/tag_filter_test.go
Обычный файл
|
@ -0,0 +1,51 @@
|
||||||
|
package tags_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cucumber/messages-go/v10"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/cucumber/godog/internal/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tag = messages.Pickle_PickleTag
|
||||||
|
type pickle = messages.Pickle
|
||||||
|
|
||||||
|
type testcase struct {
|
||||||
|
filter string
|
||||||
|
expected []*pickle
|
||||||
|
}
|
||||||
|
|
||||||
|
var testdata = []*pickle{p1, p2, p3}
|
||||||
|
var p1 = &pickle{Id: "one", Tags: []*tag{{Name: "@one"}, {Name: "@wip"}}}
|
||||||
|
var p2 = &pickle{Id: "two", Tags: []*tag{{Name: "@two"}, {Name: "@wip"}}}
|
||||||
|
var p3 = &pickle{Id: "three", Tags: []*tag{{Name: "@hree"}, {Name: "@wip"}}}
|
||||||
|
|
||||||
|
var testcases = []testcase{
|
||||||
|
{filter: "", expected: testdata},
|
||||||
|
|
||||||
|
{filter: "@one", expected: []*pickle{p1}},
|
||||||
|
{filter: "~@one", expected: []*pickle{p2, p3}},
|
||||||
|
{filter: "one", expected: []*pickle{p1}},
|
||||||
|
{filter: " one ", expected: []*pickle{p1}},
|
||||||
|
|
||||||
|
{filter: "@one,@two", expected: []*pickle{p1, p2}},
|
||||||
|
{filter: "@one,~@two", expected: []*pickle{p1, p3}},
|
||||||
|
{filter: " @one , @two ", expected: []*pickle{p1, p2}},
|
||||||
|
|
||||||
|
{filter: "@one&&@two", expected: []*pickle{}},
|
||||||
|
{filter: "@one&&~@two", expected: []*pickle{p1}},
|
||||||
|
{filter: "@one&&@wip", expected: []*pickle{p1}},
|
||||||
|
|
||||||
|
{filter: "@one&&@two,@wip", expected: []*pickle{p1}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_ApplyTagFilter(t *testing.T) {
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run("", func(t *testing.T) {
|
||||||
|
actual := tags.ApplyTagFilter(tc.filter, testdata)
|
||||||
|
assert.Equal(t, tc.expected, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
20
parser.go
20
parser.go
|
@ -12,6 +12,8 @@ import (
|
||||||
|
|
||||||
"github.com/cucumber/gherkin-go/v11"
|
"github.com/cucumber/gherkin-go/v11"
|
||||||
"github.com/cucumber/messages-go/v10"
|
"github.com/cucumber/messages-go/v10"
|
||||||
|
|
||||||
|
"github.com/cucumber/godog/internal/tags"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pathLineRe = regexp.MustCompile(`:([\d]+)$`)
|
var pathLineRe = regexp.MustCompile(`:([\d]+)$`)
|
||||||
|
@ -149,9 +151,9 @@ func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
||||||
return features, nil
|
return features, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterFeatures(tags string, features []*feature) (result []*feature) {
|
func filterFeatures(filter string, features []*feature) (result []*feature) {
|
||||||
for _, ft := range features {
|
for _, ft := range features {
|
||||||
ft.pickles = applyTagFilter(tags, ft.pickles)
|
ft.pickles = tags.ApplyTagFilter(filter, ft.pickles)
|
||||||
|
|
||||||
if ft.Feature != nil && len(ft.pickles) > 0 {
|
if ft.Feature != nil && len(ft.pickles) > 0 {
|
||||||
result = append(result, ft)
|
result = append(result, ft)
|
||||||
|
@ -160,17 +162,3 @@ func filterFeatures(tags string, features []*feature) (result []*feature) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyTagFilter(tags string, pickles []*messages.Pickle) (result []*messages.Pickle) {
|
|
||||||
if len(tags) == 0 {
|
|
||||||
return pickles
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pickle := range pickles {
|
|
||||||
if matchesTags(tags, pickle.Tags) {
|
|
||||||
result = append(result, pickle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,9 +11,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cucumber/gherkin-go/v11"
|
"github.com/cucumber/gherkin-go/v11"
|
||||||
"github.com/cucumber/godog/colors"
|
|
||||||
"github.com/cucumber/messages-go/v10"
|
"github.com/cucumber/messages-go/v10"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/cucumber/godog/colors"
|
||||||
|
"github.com/cucumber/godog/internal/tags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitializeScenario provides steps for godog suite execution and
|
// InitializeScenario provides steps for godog suite execution and
|
||||||
|
@ -180,13 +182,13 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithFormatter(name string) erro
|
||||||
return tc.iRunFeatureSuiteWithTagsAndFormatter("", f)
|
return tc.iRunFeatureSuiteWithTagsAndFormatter("", f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *godogFeaturesScenario) iRunFeatureSuiteWithTagsAndFormatter(tags string, fmtFunc FormatterFunc) error {
|
func (tc *godogFeaturesScenario) iRunFeatureSuiteWithTagsAndFormatter(filter string, fmtFunc FormatterFunc) error {
|
||||||
if err := tc.parseFeatures(); err != nil {
|
if err := tc.parseFeatures(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, feat := range tc.features {
|
for _, feat := range tc.features {
|
||||||
feat.pickles = applyTagFilter(tags, feat.pickles)
|
feat.pickles = tags.ApplyTagFilter(filter, feat.pickles)
|
||||||
}
|
}
|
||||||
|
|
||||||
tc.testedSuite.storage = newStorage()
|
tc.testedSuite.storage = newStorage()
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package godog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/cucumber/messages-go/v10"
|
|
||||||
)
|
|
||||||
|
|
||||||
// based on http://behat.readthedocs.org/en/v2.5/guides/6.cli.html#gherkin-filters
|
|
||||||
func matchesTags(filter string, tags []*messages.Pickle_PickleTag) (ok bool) {
|
|
||||||
ok = true
|
|
||||||
|
|
||||||
for _, andTags := range strings.Split(filter, "&&") {
|
|
||||||
var okComma bool
|
|
||||||
|
|
||||||
for _, tag := range strings.Split(andTags, ",") {
|
|
||||||
tag = strings.Replace(strings.TrimSpace(tag), "@", "", -1)
|
|
||||||
|
|
||||||
okComma = hasTag(tags, tag) || okComma
|
|
||||||
if tag[0] == '~' {
|
|
||||||
tag = tag[1:]
|
|
||||||
okComma = !hasTag(tags, tag) || okComma
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = ok && okComma
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasTag(tags []*messages.Pickle_PickleTag, tag string) bool {
|
|
||||||
for _, t := range tags {
|
|
||||||
tName := strings.Replace(t.Name, "@", "", -1)
|
|
||||||
|
|
||||||
if tName == tag {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package godog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/cucumber/messages-go/v10"
|
|
||||||
)
|
|
||||||
|
|
||||||
func assertNotMatchesTagFilter(tags []*tag, filter string, t *testing.T) {
|
|
||||||
if matchesTags(filter, tags) {
|
|
||||||
t.Errorf(`expected tags: %v not to match tag filter "%s", but it did`, tags, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertMatchesTagFilter(tags []*tag, filter string, t *testing.T) {
|
|
||||||
if !matchesTags(filter, tags) {
|
|
||||||
t.Errorf(`expected tags: %v to match tag filter "%s", but it did not`, tags, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTagFilter(t *testing.T) {
|
|
||||||
assertMatchesTagFilter([]*tag{{Name: "wip"}}, "@wip", t)
|
|
||||||
assertMatchesTagFilter([]*tag{}, "~@wip", t)
|
|
||||||
assertMatchesTagFilter([]*tag{{Name: "one"}, {Name: "two"}}, "@two,@three", t)
|
|
||||||
assertMatchesTagFilter([]*tag{{Name: "one"}, {Name: "two"}}, "@one&&@two", t)
|
|
||||||
assertMatchesTagFilter([]*tag{{Name: "one"}, {Name: "two"}}, "one && two", t)
|
|
||||||
|
|
||||||
assertNotMatchesTagFilter([]*tag{}, "@wip", t)
|
|
||||||
assertNotMatchesTagFilter([]*tag{{Name: "one"}, {Name: "two"}}, "@one&&~@two", t)
|
|
||||||
assertNotMatchesTagFilter([]*tag{{Name: "one"}, {Name: "two"}}, "@one && ~@two", t)
|
|
||||||
}
|
|
||||||
|
|
||||||
type tag = messages.Pickle_PickleTag
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче