properly filters features by line and tags given
Этот коммит содержится в:
родитель
0093943021
коммит
df188464c6
1 изменённых файлов: 72 добавлений и 26 удалений
98
suite.go
98
suite.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -21,8 +22,10 @@ var typeOfBytes = reflect.TypeOf([]byte(nil))
|
||||||
|
|
||||||
type feature struct {
|
type feature struct {
|
||||||
*gherkin.Feature
|
*gherkin.Feature
|
||||||
Content []byte `json:"-"`
|
Content []byte `json:"-"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
scenarios map[int]bool
|
||||||
|
order int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrUndefined is returned in case if step definition was not found
|
// ErrUndefined is returned in case if step definition was not found
|
||||||
|
@ -607,16 +610,19 @@ func (s *Suite) printStepDefinitions(w io.Writer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFeatures(filter string, paths []string) (features []*feature, err error) {
|
func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
||||||
|
byPath := make(map[string]*feature)
|
||||||
|
var order int
|
||||||
for _, pat := range paths {
|
for _, pat := range paths {
|
||||||
// check if line number is specified
|
// check if line number is specified
|
||||||
parts := strings.Split(pat, ":")
|
parts := strings.Split(pat, ":")
|
||||||
path := parts[0]
|
path := parts[0]
|
||||||
line := -1
|
line := -1
|
||||||
|
var err error
|
||||||
if len(parts) > 1 {
|
if len(parts) > 1 {
|
||||||
line, err = strconv.Atoi(parts[1])
|
line, err = strconv.Atoi(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return features, fmt.Errorf("line number should follow after colon path delimiter")
|
return nil, fmt.Errorf("line number should follow after colon path delimiter")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// parse features
|
// parse features
|
||||||
|
@ -632,40 +638,80 @@ func parseFeatures(filter string, paths []string) (features []*feature, err erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s - %v", p, err)
|
return fmt.Errorf("%s - %v", p, err)
|
||||||
}
|
}
|
||||||
features = append(features, &feature{Path: p, Feature: ft, Content: buf.Bytes()})
|
|
||||||
// filter scenario by line number
|
feat := byPath[p]
|
||||||
if line != -1 {
|
if feat == nil {
|
||||||
var scenarios []interface{}
|
feat = &feature{
|
||||||
for _, def := range ft.ScenarioDefinitions {
|
Path: p,
|
||||||
var ln int
|
Feature: ft,
|
||||||
switch t := def.(type) {
|
Content: buf.Bytes(),
|
||||||
case *gherkin.Scenario:
|
scenarios: make(map[int]bool),
|
||||||
ln = t.Location.Line
|
order: order,
|
||||||
case *gherkin.ScenarioOutline:
|
}
|
||||||
ln = t.Location.Line
|
order++
|
||||||
}
|
byPath[p] = feat
|
||||||
if ln == line {
|
}
|
||||||
scenarios = append(scenarios, def)
|
// filter scenario by line number
|
||||||
break
|
for _, def := range ft.ScenarioDefinitions {
|
||||||
}
|
var ln int
|
||||||
|
switch t := def.(type) {
|
||||||
|
case *gherkin.Scenario:
|
||||||
|
ln = t.Location.Line
|
||||||
|
case *gherkin.ScenarioOutline:
|
||||||
|
ln = t.Location.Line
|
||||||
|
}
|
||||||
|
if line == -1 || ln == line {
|
||||||
|
feat.scenarios[ln] = true
|
||||||
}
|
}
|
||||||
ft.ScenarioDefinitions = scenarios
|
|
||||||
}
|
}
|
||||||
applyTagFilter(filter, ft)
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
// check error
|
// check error
|
||||||
switch {
|
switch {
|
||||||
case os.IsNotExist(err):
|
case os.IsNotExist(err):
|
||||||
return features, fmt.Errorf(`feature path "%s" is not available`, path)
|
return nil, fmt.Errorf(`feature path "%s" is not available`, path)
|
||||||
case os.IsPermission(err):
|
case os.IsPermission(err):
|
||||||
return features, fmt.Errorf(`feature path "%s" is not accessible`, path)
|
return nil, fmt.Errorf(`feature path "%s" is not accessible`, path)
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return features, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return filterFeatures(filter, byPath), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortByOrderGiven []*feature
|
||||||
|
|
||||||
|
func (s sortByOrderGiven) Len() int { return len(s) }
|
||||||
|
func (s sortByOrderGiven) Less(i, j int) bool { return s[i].order < s[j].order }
|
||||||
|
func (s sortByOrderGiven) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
|
||||||
|
func filterFeatures(tags string, collected map[string]*feature) (features []*feature) {
|
||||||
|
for _, ft := range collected {
|
||||||
|
var scenarios []interface{}
|
||||||
|
for _, def := range ft.ScenarioDefinitions {
|
||||||
|
var ln int
|
||||||
|
switch t := def.(type) {
|
||||||
|
case *gherkin.Scenario:
|
||||||
|
ln = t.Location.Line
|
||||||
|
case *gherkin.ScenarioOutline:
|
||||||
|
ln = t.Location.Line
|
||||||
|
}
|
||||||
|
if ft.scenarios[ln] {
|
||||||
|
scenarios = append(scenarios, def)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ft.ScenarioDefinitions = scenarios
|
||||||
|
applyTagFilter(tags, ft.Feature)
|
||||||
|
|
||||||
|
if len(ft.ScenarioDefinitions) > 0 {
|
||||||
|
features = append(features, ft)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(sortByOrderGiven(features))
|
||||||
|
|
||||||
|
return features
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyTagFilter(tags string, ft *gherkin.Feature) {
|
func applyTagFilter(tags string, ft *gherkin.Feature) {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче