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:
|
||||
description: "Run go vet"
|
||||
steps:
|
||||
- run: go vet github.com/cucumber/godog
|
||||
- run: go vet github.com/cucumber/godog/colors
|
||||
- run: go vet ./...
|
||||
go_test:
|
||||
description: "Run go test"
|
||||
steps:
|
||||
- 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:
|
||||
description: "Run godog"
|
||||
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/messages-go/v10"
|
||||
|
||||
"github.com/cucumber/godog/internal/tags"
|
||||
)
|
||||
|
||||
var pathLineRe = regexp.MustCompile(`:([\d]+)$`)
|
||||
|
@ -149,9 +151,9 @@ func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
|||
return features, nil
|
||||
}
|
||||
|
||||
func filterFeatures(tags string, features []*feature) (result []*feature) {
|
||||
func filterFeatures(filter string, features []*feature) (result []*feature) {
|
||||
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 {
|
||||
result = append(result, ft)
|
||||
|
@ -160,17 +162,3 @@ func filterFeatures(tags string, features []*feature) (result []*feature) {
|
|||
|
||||
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"
|
||||
|
||||
"github.com/cucumber/gherkin-go/v11"
|
||||
"github.com/cucumber/godog/colors"
|
||||
"github.com/cucumber/messages-go/v10"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/cucumber/godog/colors"
|
||||
"github.com/cucumber/godog/internal/tags"
|
||||
)
|
||||
|
||||
// InitializeScenario provides steps for godog suite execution and
|
||||
|
@ -180,13 +182,13 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithFormatter(name string) erro
|
|||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, feat := range tc.features {
|
||||
feat.pickles = applyTagFilter(tags, feat.pickles)
|
||||
feat.pickles = tags.ApplyTagFilter(filter, feat.pickles)
|
||||
}
|
||||
|
||||
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
|
Загрузка…
Создание таблицы
Сослаться в новой задаче