properly filters features by line and tags given

Этот коммит содержится в:
gedi 2017-10-24 16:02:18 +03:00
родитель 0093943021
коммит df188464c6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 56604CDCCC201556

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

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