closes #170
Этот коммит содержится в:
родитель
4f373bb9d2
коммит
338a78050c
3 изменённых файлов: 100 добавлений и 66 удалений
|
@ -114,7 +114,7 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) {
|
|||
}
|
||||
|
||||
out := buf.String()
|
||||
if idx := strings.Index(out, "github.com/DATA-DOG/godog/fmt_progress_test.go:108"); idx == -1 {
|
||||
if idx := strings.Index(out, "godog/fmt_progress_test.go:108"); idx == -1 {
|
||||
t.Fatalf("expected to find panic stacktrace, actual:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1 +1,3 @@
|
|||
module github.com/DATA-DOG/godog
|
||||
|
||||
go 1.12
|
||||
|
|
162
suite.go
162
suite.go
|
@ -22,10 +22,9 @@ var typeOfBytes = reflect.TypeOf([]byte(nil))
|
|||
|
||||
type feature struct {
|
||||
*gherkin.Feature
|
||||
Content []byte `json:"-"`
|
||||
Path string `json:"path"`
|
||||
scenarios map[int]bool
|
||||
order int
|
||||
Content []byte `json:"-"`
|
||||
Path string `json:"path"`
|
||||
order int
|
||||
}
|
||||
|
||||
// ErrUndefined is returned in case if step definition was not found
|
||||
|
@ -631,56 +630,93 @@ func extractFeaturePathLine(p string) (string, int) {
|
|||
return retPath, line
|
||||
}
|
||||
|
||||
func parseFeatureFile(path string) (*feature, error) {
|
||||
reader, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
ft, err := gherkin.ParseFeature(io.TeeReader(reader, &buf))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s - %v", path, err)
|
||||
}
|
||||
|
||||
return &feature{
|
||||
Path: path,
|
||||
Feature: ft,
|
||||
Content: buf.Bytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseFeatureDir(dir string) ([]*feature, error) {
|
||||
var features []*feature
|
||||
return features, filepath.Walk(dir, func(p string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(p, ".feature") {
|
||||
return nil
|
||||
}
|
||||
|
||||
feat, err := parseFeatureFile(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
features = append(features, feat)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func parsePath(path string) ([]*feature, error) {
|
||||
var features []*feature
|
||||
// check if line number is specified
|
||||
var line int
|
||||
path, line = extractFeaturePathLine(path)
|
||||
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return features, err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return parseFeatureDir(path)
|
||||
}
|
||||
|
||||
ft, err := parseFeatureFile(path)
|
||||
if err != nil {
|
||||
return features, err
|
||||
}
|
||||
|
||||
// filter scenario by line number
|
||||
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 line == -1 || ln == line {
|
||||
scenarios = append(scenarios, def)
|
||||
}
|
||||
}
|
||||
ft.ScenarioDefinitions = scenarios
|
||||
return append(features, ft), nil
|
||||
}
|
||||
|
||||
func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
||||
byPath := make(map[string]*feature)
|
||||
var order int
|
||||
for _, pat := range paths {
|
||||
// check if line number is specified
|
||||
path, line := extractFeaturePathLine(pat)
|
||||
var err error
|
||||
// parse features
|
||||
err = filepath.Walk(path, func(p string, f os.FileInfo, err error) error {
|
||||
if err == nil && !f.IsDir() && strings.HasSuffix(p, ".feature") {
|
||||
reader, err := os.Open(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
ft, err := gherkin.ParseFeature(io.TeeReader(reader, &buf))
|
||||
reader.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s - %v", p, err)
|
||||
}
|
||||
|
||||
feat := byPath[p]
|
||||
if feat == nil {
|
||||
feat = &feature{
|
||||
Path: p,
|
||||
Feature: ft,
|
||||
Content: buf.Bytes(),
|
||||
scenarios: make(map[int]bool),
|
||||
order: order,
|
||||
}
|
||||
order++
|
||||
byPath[p] = feat
|
||||
}
|
||||
// filter scenario by line number
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
// check error
|
||||
for _, path := range paths {
|
||||
feats, err := parsePath(path)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
return nil, fmt.Errorf(`feature path "%s" is not available`, path)
|
||||
|
@ -689,6 +725,16 @@ func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
|||
case err != nil:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, ft := range feats {
|
||||
if _, duplicate := byPath[ft.Path]; duplicate {
|
||||
continue
|
||||
}
|
||||
|
||||
ft.order = order
|
||||
order++
|
||||
byPath[ft.Path] = ft
|
||||
}
|
||||
}
|
||||
return filterFeatures(filter, byPath), nil
|
||||
}
|
||||
|
@ -701,20 +747,6 @@ 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)
|
||||
features = append(features, ft)
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче