Refactored some states in the formatters and feature struct
Этот коммит содержится в:
родитель
a03a1b8d2c
коммит
b717039e16
13 изменённых файлов: 84 добавлений и 122 удалений
|
@ -7,9 +7,7 @@ import (
|
|||
type feature struct {
|
||||
*messages.GherkinDocument
|
||||
pickles []*messages.Pickle
|
||||
|
||||
content []byte
|
||||
order int
|
||||
}
|
||||
|
||||
type sortFeaturesByName []*feature
|
||||
|
@ -18,12 +16,6 @@ func (s sortFeaturesByName) Len() int { return len(s) }
|
|||
func (s sortFeaturesByName) Less(i, j int) bool { return s[i].Feature.Name < s[j].Feature.Name }
|
||||
func (s sortFeaturesByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
type sortFeaturesByOrder []*feature
|
||||
|
||||
func (s sortFeaturesByOrder) Len() int { return len(s) }
|
||||
func (s sortFeaturesByOrder) Less(i, j int) bool { return s[i].order < s[j].order }
|
||||
func (s sortFeaturesByOrder) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
func (f feature) findScenario(astScenarioID string) *messages.GherkinDocument_Feature_Scenario {
|
||||
for _, child := range f.GherkinDocument.Feature.Children {
|
||||
if sc := child.GetScenario(); sc != nil && sc.Id == astScenarioID {
|
||||
|
|
43
fmt_base.go
43
fmt_base.go
|
@ -9,7 +9,6 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/cucumber/messages-go/v10"
|
||||
|
@ -20,7 +19,6 @@ import (
|
|||
func newBaseFmt(suite string, out io.Writer) *basefmt {
|
||||
return &basefmt{
|
||||
suiteName: suite,
|
||||
startedAt: timeNowFunc(),
|
||||
indent: 2,
|
||||
out: out,
|
||||
lock: new(sync.Mutex),
|
||||
|
@ -29,42 +27,24 @@ func newBaseFmt(suite string, out io.Writer) *basefmt {
|
|||
|
||||
type basefmt struct {
|
||||
suiteName string
|
||||
|
||||
out io.Writer
|
||||
owner interface{}
|
||||
indent int
|
||||
|
||||
storage *storage
|
||||
|
||||
startedAt time.Time
|
||||
|
||||
firstFeature *bool
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
func (f *basefmt) setStorage(st *storage) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
f.storage = st
|
||||
}
|
||||
|
||||
func (f *basefmt) TestRunStarted() {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
firstFeature := true
|
||||
f.firstFeature = &firstFeature
|
||||
}
|
||||
|
||||
func (f *basefmt) TestRunStarted() {}
|
||||
func (f *basefmt) Feature(ft *messages.GherkinDocument, p string, c []byte) {}
|
||||
func (f *basefmt) Pickle(p *messages.Pickle) {}
|
||||
|
||||
func (f *basefmt) Defined(*messages.Pickle, *messages.Pickle_PickleStep, *StepDefinition) {}
|
||||
|
||||
func (f *basefmt) Feature(ft *messages.GherkinDocument, p string, c []byte) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
*f.firstFeature = false
|
||||
}
|
||||
|
||||
func (f *basefmt) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) {
|
||||
}
|
||||
func (f *basefmt) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) {
|
||||
|
@ -145,7 +125,9 @@ func (f *basefmt) Summary() {
|
|||
scenarios = append(scenarios, green(fmt.Sprintf("%d passed", passedSc)))
|
||||
}
|
||||
scenarios = append(scenarios, parts...)
|
||||
elapsed := timeNowFunc().Sub(f.startedAt)
|
||||
|
||||
testRunStartedAt := f.storage.mustGetTestRunStarted().StartedAt
|
||||
elapsed := timeNowFunc().Sub(testRunStartedAt)
|
||||
|
||||
fmt.Fprintln(f.out, "")
|
||||
|
||||
|
@ -182,15 +164,6 @@ func (f *basefmt) Summary() {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *basefmt) Sync(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*basefmt); ok {
|
||||
f.lock = source.lock
|
||||
f.firstFeature = source.firstFeature
|
||||
}
|
||||
}
|
||||
|
||||
func (f *basefmt) Copy(cf ConcurrentFormatter) {}
|
||||
|
||||
func (f *basefmt) snippets() string {
|
||||
undefinedStepResults := f.storage.mustGetPickleStepResultsByStatus(undefined)
|
||||
if len(undefinedStepResults) == 0 {
|
||||
|
|
|
@ -46,18 +46,6 @@ func (f *cukefmt) Summary() {
|
|||
fmt.Fprintf(f.out, "%s\n", string(dat))
|
||||
}
|
||||
|
||||
func (f *cukefmt) Sync(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*cukefmt); ok {
|
||||
f.basefmt.Sync(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *cukefmt) Copy(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*cukefmt); ok {
|
||||
f.basefmt.Copy(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *cukefmt) buildCukeFeatures(features []*feature) (res []cukeFeatureJSON) {
|
||||
sort.Sort(sortFeaturesByName(features))
|
||||
|
||||
|
|
|
@ -136,18 +136,6 @@ func (f *events) Summary() {
|
|||
})
|
||||
}
|
||||
|
||||
func (f *events) Sync(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*events); ok {
|
||||
f.basefmt.Sync(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *events) Copy(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*events); ok {
|
||||
f.basefmt.Copy(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *events) step(pickle *messages.Pickle, pickleStep *messages.Pickle_PickleStep) {
|
||||
feature := f.storage.mustGetFeature(pickle.Uri)
|
||||
pickleStepResult := f.storage.mustGetPickleStepResult(pickleStep.Id)
|
||||
|
|
20
fmt_junit.go
20
fmt_junit.go
|
@ -37,18 +37,6 @@ func (f *junitFormatter) Summary() {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *junitFormatter) Sync(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*junitFormatter); ok {
|
||||
f.basefmt.Sync(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *junitFormatter) Copy(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*junitFormatter); ok {
|
||||
f.basefmt.Copy(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func junitTimeDuration(from, to time.Time) string {
|
||||
return strconv.FormatFloat(to.Sub(from).Seconds(), 'f', -1, 64)
|
||||
}
|
||||
|
@ -57,10 +45,12 @@ func (f *junitFormatter) buildJUNITPackageSuite() junitPackageSuite {
|
|||
features := f.storage.mustGetFeatures()
|
||||
sort.Sort(sortFeaturesByName(features))
|
||||
|
||||
testRunStartedAt := f.storage.mustGetTestRunStarted().StartedAt
|
||||
|
||||
suite := junitPackageSuite{
|
||||
Name: f.suiteName,
|
||||
TestSuites: make([]*junitTestSuite, len(features)),
|
||||
Time: junitTimeDuration(f.startedAt, timeNowFunc()),
|
||||
Time: junitTimeDuration(testRunStartedAt, timeNowFunc()),
|
||||
}
|
||||
|
||||
for idx, feature := range features {
|
||||
|
@ -77,8 +67,8 @@ func (f *junitFormatter) buildJUNITPackageSuite() junitPackageSuite {
|
|||
testcaseNames[pickle.Name] = testcaseNames[pickle.Name] + 1
|
||||
}
|
||||
|
||||
firstPickleStartedAt := f.startedAt
|
||||
lastPickleFinishedAt := f.startedAt
|
||||
firstPickleStartedAt := testRunStartedAt
|
||||
lastPickleFinishedAt := testRunStartedAt
|
||||
|
||||
var outlineNo = make(map[string]int)
|
||||
for idx, pickle := range pickles {
|
||||
|
|
|
@ -26,6 +26,17 @@ var outlinePlaceholderRegexp = regexp.MustCompile("<[^>]+>")
|
|||
// a built in default pretty formatter
|
||||
type pretty struct {
|
||||
*basefmt
|
||||
firstFeature *bool
|
||||
}
|
||||
|
||||
func (f *pretty) TestRunStarted() {
|
||||
f.basefmt.TestRunStarted()
|
||||
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
firstFeature := true
|
||||
f.firstFeature = &firstFeature
|
||||
}
|
||||
|
||||
func (f *pretty) Feature(gd *messages.GherkinDocument, p string, c []byte) {
|
||||
|
@ -33,6 +44,8 @@ func (f *pretty) Feature(gd *messages.GherkinDocument, p string, c []byte) {
|
|||
if !*f.firstFeature {
|
||||
fmt.Fprintln(f.out, "")
|
||||
}
|
||||
|
||||
*f.firstFeature = false
|
||||
f.lock.Unlock()
|
||||
|
||||
f.basefmt.Feature(gd, p, c)
|
||||
|
@ -101,18 +114,6 @@ func (f *pretty) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleSt
|
|||
f.printStep(pickle, step)
|
||||
}
|
||||
|
||||
func (f *pretty) Sync(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*pretty); ok {
|
||||
f.basefmt.Sync(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *pretty) Copy(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*pretty); ok {
|
||||
f.basefmt.Copy(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *pretty) printFeature(feature *messages.GherkinDocument_Feature) {
|
||||
fmt.Fprintln(f.out, keywordAndName(feature.Keyword, feature.Name))
|
||||
if strings.TrimSpace(feature.Description) != "" {
|
||||
|
|
|
@ -144,16 +144,3 @@ func (f *progress) Pending(pickle *messages.Pickle, step *messages.Pickle_Pickle
|
|||
|
||||
f.step(step.Id)
|
||||
}
|
||||
|
||||
func (f *progress) Sync(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*progress); ok {
|
||||
f.basefmt.Sync(source.basefmt)
|
||||
f.steps = source.steps
|
||||
}
|
||||
}
|
||||
|
||||
func (f *progress) Copy(cf ConcurrentFormatter) {
|
||||
if source, ok := cf.(*progress); ok {
|
||||
f.basefmt.Copy(source.basefmt)
|
||||
}
|
||||
}
|
||||
|
|
27
parser.go
27
parser.go
|
@ -7,7 +7,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -113,6 +112,7 @@ func parsePath(path string) ([]*feature, error) {
|
|||
func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
||||
var order int
|
||||
|
||||
featureIdxs := make(map[string]int)
|
||||
uniqueFeatureURI := make(map[string]*feature)
|
||||
for _, path := range paths {
|
||||
feats, err := parsePath(path)
|
||||
|
@ -131,27 +131,34 @@ func parseFeatures(filter string, paths []string) ([]*feature, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
ft.order = order
|
||||
order++
|
||||
uniqueFeatureURI[ft.Uri] = ft
|
||||
featureIdxs[ft.Uri] = order
|
||||
|
||||
order++
|
||||
}
|
||||
}
|
||||
|
||||
return filterFeatures(filter, uniqueFeatureURI), nil
|
||||
var features = make([]*feature, len(uniqueFeatureURI))
|
||||
for uri, feature := range uniqueFeatureURI {
|
||||
idx := featureIdxs[uri]
|
||||
features[idx] = feature
|
||||
}
|
||||
|
||||
func filterFeatures(tags string, collected map[string]*feature) (features []*feature) {
|
||||
for _, ft := range collected {
|
||||
features = filterFeatures(filter, features)
|
||||
|
||||
return features, nil
|
||||
}
|
||||
|
||||
func filterFeatures(tags string, features []*feature) (result []*feature) {
|
||||
for _, ft := range features {
|
||||
ft.pickles = applyTagFilter(tags, ft.pickles)
|
||||
|
||||
if ft.Feature != nil {
|
||||
features = append(features, ft)
|
||||
result = append(result, ft)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(sortFeaturesByOrder(features))
|
||||
|
||||
return features
|
||||
return
|
||||
}
|
||||
|
||||
func applyTagFilter(tags string, pickles []*messages.Pickle) (result []*messages.Pickle) {
|
||||
|
|
|
@ -6,6 +6,10 @@ import (
|
|||
"github.com/cucumber/godog/colors"
|
||||
)
|
||||
|
||||
type testRunStarted struct {
|
||||
StartedAt time.Time
|
||||
}
|
||||
|
||||
type pickleResult struct {
|
||||
PickleID string
|
||||
StartedAt time.Time
|
||||
|
|
2
run.go
2
run.go
|
@ -55,6 +55,8 @@ func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool
|
|||
r.testSuiteInitializer(&testSuiteContext)
|
||||
}
|
||||
|
||||
testRunStarted := testRunStarted{StartedAt: timeNowFunc()}
|
||||
r.storage.mustInsertTestRunStarted(testRunStarted)
|
||||
r.fmt.TestRunStarted()
|
||||
|
||||
// run before suite handlers
|
||||
|
|
20
storage.go
20
storage.go
|
@ -2,6 +2,7 @@ package godog
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/cucumber/messages-go/v10"
|
||||
"github.com/hashicorp/go-memdb"
|
||||
|
@ -32,6 +33,9 @@ const (
|
|||
|
||||
type storage struct {
|
||||
db *memdb.MemDB
|
||||
|
||||
testRunStarted testRunStarted
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
func newStorage() *storage {
|
||||
|
@ -112,7 +116,7 @@ func newStorage() *storage {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
return &storage{db}
|
||||
return &storage{db: db, lock: new(sync.Mutex)}
|
||||
}
|
||||
|
||||
func (s *storage) mustInsertPickle(p *messages.Pickle) {
|
||||
|
@ -150,6 +154,20 @@ func (s *storage) mustGetPickleStep(id string) *messages.Pickle_PickleStep {
|
|||
return v.(*messages.Pickle_PickleStep)
|
||||
}
|
||||
|
||||
func (s *storage) mustInsertTestRunStarted(trs testRunStarted) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.testRunStarted = trs
|
||||
}
|
||||
|
||||
func (s *storage) mustGetTestRunStarted() testRunStarted {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
return s.testRunStarted
|
||||
}
|
||||
|
||||
func (s *storage) mustInsertPickleResult(pr pickleResult) {
|
||||
s.mustInsert(tablePickleResult, pr)
|
||||
}
|
||||
|
|
|
@ -195,6 +195,9 @@ func (s *suiteContext) iRunFeatureSuiteWithTags(tags string) error {
|
|||
fmt.setStorage(s.testedSuite.storage)
|
||||
s.testedSuite.fmt = fmt
|
||||
|
||||
testRunStarted := testRunStarted{StartedAt: timeNowFunc()}
|
||||
s.testedSuite.storage.mustInsertTestRunStarted(testRunStarted)
|
||||
|
||||
s.testedSuite.fmt.TestRunStarted()
|
||||
s.testedSuite.run()
|
||||
s.testedSuite.fmt.Summary()
|
||||
|
@ -226,6 +229,9 @@ func (s *suiteContext) iRunFeatureSuiteWithFormatter(name string) error {
|
|||
fmt.setStorage(s.testedSuite.storage)
|
||||
}
|
||||
|
||||
testRunStarted := testRunStarted{StartedAt: timeNowFunc()}
|
||||
s.testedSuite.storage.mustInsertTestRunStarted(testRunStarted)
|
||||
|
||||
s.testedSuite.fmt.TestRunStarted()
|
||||
s.testedSuite.run()
|
||||
s.testedSuite.fmt.Summary()
|
||||
|
|
|
@ -157,6 +157,9 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithTags(tags string) error {
|
|||
fmt.setStorage(tc.testedSuite.storage)
|
||||
tc.testedSuite.fmt = fmt
|
||||
|
||||
testRunStarted := testRunStarted{StartedAt: timeNowFunc()}
|
||||
tc.testedSuite.storage.mustInsertTestRunStarted(testRunStarted)
|
||||
|
||||
tc.testedSuite.fmt.TestRunStarted()
|
||||
tc.testedSuite.run()
|
||||
tc.testedSuite.fmt.Summary()
|
||||
|
@ -188,6 +191,9 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithFormatter(name string) erro
|
|||
fmt.setStorage(tc.testedSuite.storage)
|
||||
}
|
||||
|
||||
testRunStarted := testRunStarted{StartedAt: timeNowFunc()}
|
||||
tc.testedSuite.storage.mustInsertTestRunStarted(testRunStarted)
|
||||
|
||||
tc.testedSuite.fmt.TestRunStarted()
|
||||
tc.testedSuite.run()
|
||||
tc.testedSuite.fmt.Summary()
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче