Merge pull request #326 from cucumber/internal-parser-pkg

Added an internal package for tags filtering
Этот коммит содержится в:
Fredrik Lönnblad 2020-07-01 07:13:37 +02:00 коммит произвёл GitHub
родитель 183de20e80 e38c6ed719
коммит 4da375f4c0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

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

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

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