sort feature files by path when executing, separate the concurrent runner

Этот коммит содержится в:
gedi 2016-06-16 12:01:58 +03:00
родитель a6a318322b
коммит abc6b65c1c
4 изменённых файлов: 41 добавлений и 15 удалений

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

@ -42,6 +42,6 @@ Feature: load features
When I parse features
Then I should have 2 feature files:
"""
features/load.feature
features/events.feature
features/load.feature
"""

44
run.go
Просмотреть файл

@ -3,29 +3,24 @@ package godog
import (
"fmt"
"os"
"sync"
)
type initializer func(*Suite)
type runner struct {
sync.WaitGroup
semaphore chan int
stopOnFailure bool
features []*feature
fmt Formatter // needs to support concurrency
initializer initializer
}
func (r *runner) run() (failed bool) {
r.Add(len(r.features))
for _, ft := range r.features {
func (r *runner) concurrent(rate int) (failed bool) {
queue := make(chan int, rate)
for i, ft := range r.features {
queue <- i // reserve space in queue
go func(fail *bool, feat *feature) {
r.semaphore <- 1
defer func() {
r.Done()
<-r.semaphore
<-queue // free a space in queue
}()
if r.stopOnFailure && *fail {
return
@ -42,12 +37,30 @@ func (r *runner) run() (failed bool) {
}
}(&failed, ft)
}
r.Wait()
// wait until last are processed
for i := 0; i < rate; i++ {
queue <- i
}
close(queue)
// print summary
r.fmt.Summary()
return
}
func (r *runner) run() (failed bool) {
suite := &Suite{
fmt: r.fmt,
stopOnFailure: r.stopOnFailure,
features: r.features,
}
r.initializer(suite)
suite.run()
r.fmt.Summary()
return suite.failed
}
// Run creates and runs the feature suite.
// uses contextInitializer to register contexts
//
@ -94,12 +107,17 @@ func Run(contextInitializer func(suite *Suite)) int {
r := runner{
fmt: formatter,
initializer: contextInitializer,
semaphore: make(chan int, concurrency),
features: features,
stopOnFailure: sof,
}
if failed := r.run(); failed {
var failed bool
if concurrency > 1 {
failed = r.concurrent(concurrency)
} else {
failed = r.run()
}
if failed {
return 1
}
return 0

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

@ -6,6 +6,7 @@ import (
"path/filepath"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"unicode/utf8"
@ -445,9 +446,16 @@ func parseFeatures(filter string, paths []string) (features []*feature, err erro
return features, err
}
}
sort.Sort(featuresSortedByPath(features))
return
}
type featuresSortedByPath []*feature
func (s featuresSortedByPath) Len() int { return len(s) }
func (s featuresSortedByPath) Less(i, j int) bool { return s[i].Path < s[j].Path }
func (s featuresSortedByPath) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func applyTagFilter(tags string, ft *gherkin.Feature) {
if len(tags) == 0 {
return

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

@ -44,7 +44,7 @@ func s(n int) string {
// checks the error and exits with error status code
func fatal(err error) {
if err != nil {
fmt.Println(err)
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}