Added features to the in-mem storage

Этот коммит содержится в:
Fredrik Lönnblad 2020-06-10 22:45:16 +02:00 коммит произвёл Fredrik Lönnblad
родитель 18a045f989
коммит b1a69ae142
13 изменённых файлов: 220 добавлений и 237 удалений

65
fmt.go
Просмотреть файл

@ -174,7 +174,6 @@ type basefmt struct {
storage *storage
startedAt time.Time
features []*feature
firstFeature *bool
lock *sync.Mutex
@ -184,60 +183,6 @@ func (f *basefmt) setStorage(st *storage) {
f.storage = st
}
func (f *basefmt) lastFeature() *feature {
return f.features[len(f.features)-1]
}
func (f *basefmt) findFeature(scenarioAstID string) *feature {
for _, ft := range f.features {
if sc := ft.findScenario(scenarioAstID); sc != nil {
return ft
}
}
panic("Couldn't find scenario for AST ID: " + scenarioAstID)
}
func (f *basefmt) findScenario(scenarioAstID string) *messages.GherkinDocument_Feature_Scenario {
for _, ft := range f.features {
if sc := ft.findScenario(scenarioAstID); sc != nil {
return sc
}
}
panic("Couldn't find scenario for AST ID: " + scenarioAstID)
}
func (f *basefmt) findBackground(scenarioAstID string) *messages.GherkinDocument_Feature_Background {
for _, ft := range f.features {
if bg := ft.findBackground(scenarioAstID); bg != nil {
return bg
}
}
return nil
}
func (f *basefmt) findExample(exampleAstID string) (*messages.GherkinDocument_Feature_Scenario_Examples, *messages.GherkinDocument_Feature_TableRow) {
for _, ft := range f.features {
if es, rs := ft.findExample(exampleAstID); es != nil && rs != nil {
return es, rs
}
}
return nil, nil
}
func (f *basefmt) findStep(stepAstID string) *messages.GherkinDocument_Feature_Step {
for _, ft := range f.features {
if st := ft.findStep(stepAstID); st != nil {
return st
}
}
panic("Couldn't find step for AST ID: " + stepAstID)
}
func (f *basefmt) TestRunStarted() {
f.lock.Lock()
defer f.lock.Unlock()
@ -255,8 +200,6 @@ func (f *basefmt) Feature(ft *messages.GherkinDocument, p string, c []byte) {
defer f.lock.Unlock()
*f.firstFeature = false
f.features = append(f.features, &feature{GherkinDocument: ft, time: timeNowFunc()})
}
func (f *basefmt) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) {
@ -383,13 +326,7 @@ func (f *basefmt) Sync(cf ConcurrentFormatter) {
}
}
func (f *basefmt) Copy(cf ConcurrentFormatter) {
if source, ok := cf.(*basefmt); ok {
for _, v := range source.features {
f.features = append(f.features, v)
}
}
}
func (f *basefmt) Copy(cf ConcurrentFormatter) {}
func (f *basefmt) snippets() string {
undefinedStepResults := f.storage.mustGetPickleStepResultsByStatus(undefined)

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

@ -34,7 +34,9 @@ type cukefmt struct {
}
func (f *cukefmt) Summary() {
res := f.buildCukeFeatures(f.features)
features := f.storage.mustGetFeatures()
res := f.buildCukeFeatures(features)
dat, err := json.MarshalIndent(res, "", " ")
if err != nil {
@ -57,7 +59,7 @@ func (f *cukefmt) Copy(cf ConcurrentFormatter) {
}
func (f *cukefmt) buildCukeFeatures(features []*feature) (res []cukeFeatureJSON) {
sort.Sort(sortByName(features))
sort.Sort(sortFeaturesByName(features))
res = make([]cukeFeatureJSON, len(features))
@ -88,7 +90,7 @@ func (f *cukefmt) buildCukeElements(pickles []*messages.Pickle) (res []cukeEleme
pickleResult := f.storage.mustGetPickleResult(pickle.Id)
pickleStepResults := f.storage.mustGetPickleStepResultsByPickleID(pickle.Id)
cukeElement := f.buildCukeElement(pickle.Name, pickle.AstNodeIds)
cukeElement := f.buildCukeElement(pickle)
stepStartedAt := pickleResult.StartedAt
@ -204,10 +206,11 @@ func buildCukeFeature(feat *feature) cukeFeatureJSON {
return cukeFeature
}
func (f *cukefmt) buildCukeElement(pickleName string, pickleAstNodeIDs []string) (cukeElement cukeElement) {
scenario := f.findScenario(pickleAstNodeIDs[0])
func (f *cukefmt) buildCukeElement(pickle *messages.Pickle) (cukeElement cukeElement) {
feature := f.storage.mustGetFeature(pickle.Uri)
scenario := feature.findScenario(pickle.AstNodeIds[0])
cukeElement.Name = pickleName
cukeElement.Name = pickle.Name
cukeElement.Line = int(scenario.Location.Line)
cukeElement.Description = scenario.Description
cukeElement.Keyword = scenario.Keyword
@ -219,11 +222,11 @@ func (f *cukefmt) buildCukeElement(pickleName string, pickleAstNodeIDs []string)
cukeElement.Tags[idx].Name = element.Name
}
if len(pickleAstNodeIDs) == 1 {
if len(pickle.AstNodeIds) == 1 {
return
}
example, _ := f.findExample(pickleAstNodeIDs[1])
example, _ := feature.findExample(pickle.AstNodeIds[1])
for _, tag := range example.Tags {
tag := cukeTag{Line: int(tag.Location.Line), Name: tag.Name}
@ -232,7 +235,7 @@ func (f *cukefmt) buildCukeElement(pickleName string, pickleAstNodeIDs []string)
examples := scenario.GetExamples()
if len(examples) > 0 {
rowID := pickleAstNodeIDs[1]
rowID := pickle.AstNodeIds[1]
for _, example := range examples {
for idx, row := range example.TableBody {
@ -248,12 +251,13 @@ func (f *cukefmt) buildCukeElement(pickleName string, pickleAstNodeIDs []string)
}
func (f *cukefmt) buildCukeStep(pickle *messages.Pickle, stepResult pickleStepResult) (cukeStep cukeStep) {
feature := f.storage.mustGetFeature(pickle.Uri)
pickleStep := f.storage.mustGetPickleStep(stepResult.PickleStepID)
step := f.findStep(pickleStep.AstNodeIds[0])
step := feature.findStep(pickleStep.AstNodeIds[0])
line := step.Location.Line
if len(pickle.AstNodeIds) == 2 {
_, row := f.findExample(pickle.AstNodeIds[1])
_, row := feature.findExample(pickle.AstNodeIds[1])
line = row.Location.Line
}

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

@ -149,8 +149,9 @@ func (f *events) Copy(cf ConcurrentFormatter) {
}
func (f *events) step(pickle *messages.Pickle, pickleStep *messages.Pickle_PickleStep) {
feature := f.storage.mustGetFeature(pickle.Uri)
pickleStepResult := f.storage.mustGetPickleStepResult(pickleStep.Id)
step := f.findStep(pickleStep.AstNodeIds[0])
step := feature.findStep(pickleStep.AstNodeIds[0])
var errMsg string
if pickleStepResult.err != nil {
@ -207,7 +208,8 @@ func (f *events) Defined(pickle *messages.Pickle, pickleStep *messages.Pickle_Pi
f.lock.Lock()
defer f.lock.Unlock()
step := f.findStep(pickleStep.AstNodeIds[0])
feature := f.storage.mustGetFeature(pickle.Uri)
step := feature.findStep(pickleStep.AstNodeIds[0])
if def != nil {
m := def.Expr.FindStringSubmatchIndex(pickleStep.Text)[2:]
@ -294,10 +296,12 @@ func (f *events) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleSt
}
func (f *events) scenarioLocation(pickle *messages.Pickle) string {
scenario := f.findScenario(pickle.AstNodeIds[0])
feature := f.storage.mustGetFeature(pickle.Uri)
scenario := feature.findScenario(pickle.AstNodeIds[0])
line := scenario.Location.Line
if len(pickle.AstNodeIds) == 2 {
_, row := f.findExample(pickle.AstNodeIds[1])
_, row := feature.findExample(pickle.AstNodeIds[1])
line = row.Location.Line
}

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

@ -54,19 +54,20 @@ func junitTimeDuration(from, to time.Time) string {
}
func (f *junitFormatter) buildJUNITPackageSuite() junitPackageSuite {
features := f.storage.mustGetFeatures()
sort.Sort(sortFeaturesByName(features))
suite := junitPackageSuite{
Name: f.suiteName,
TestSuites: make([]*junitTestSuite, len(f.features)),
TestSuites: make([]*junitTestSuite, len(features)),
Time: junitTimeDuration(f.startedAt, timeNowFunc()),
}
sort.Sort(sortByName(f.features))
for idx, feat := range f.features {
pickles := f.storage.mustGetPickles(feat.Uri)
for idx, feature := range features {
pickles := f.storage.mustGetPickles(feature.Uri)
sort.Sort(sortPicklesByID(pickles))
var finishedAt = feat.startedAt()
var finishedAt = feature.startedAt()
if len(pickles) > 0 {
lastPickle := pickles[len(pickles)-1]
@ -79,8 +80,8 @@ func (f *junitFormatter) buildJUNITPackageSuite() junitPackageSuite {
}
ts := junitTestSuite{
Name: feat.GherkinDocument.Feature.Name,
Time: junitTimeDuration(feat.startedAt(), finishedAt),
Name: feature.Feature.Name,
Time: junitTimeDuration(feature.startedAt(), finishedAt),
TestCases: make([]*junitTestCase, len(pickles)),
}

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

@ -130,9 +130,10 @@ func keywordAndName(keyword, name string) string {
return title
}
func (f *pretty) scenarioLengths(scenarioAstID string) (scenarioHeaderLength int, maxLength int) {
astScenario := f.findScenario(scenarioAstID)
astBackground := f.findBackground(scenarioAstID)
func (f *pretty) scenarioLengths(pickle *messages.Pickle) (scenarioHeaderLength int, maxLength int) {
feature := f.storage.mustGetFeature(pickle.Uri)
astScenario := feature.findScenario(pickle.AstNodeIds[0])
astBackground := feature.findBackground(pickle.AstNodeIds[0])
scenarioHeaderLength = f.lengthPickle(astScenario.Keyword, astScenario.Name)
maxLength = f.longestStep(astScenario.Steps, scenarioHeaderLength)
@ -144,17 +145,19 @@ func (f *pretty) scenarioLengths(scenarioAstID string) (scenarioHeaderLength int
return scenarioHeaderLength, maxLength
}
func (f *pretty) printScenarioHeader(astScenario *messages.GherkinDocument_Feature_Scenario, spaceFilling int) {
func (f *pretty) printScenarioHeader(pickle *messages.Pickle, astScenario *messages.GherkinDocument_Feature_Scenario, spaceFilling int) {
feature := f.storage.mustGetFeature(pickle.Uri)
text := s(f.indent) + keywordAndName(astScenario.Keyword, astScenario.Name)
text += s(spaceFilling) + f.line(f.lastFeature().Uri, astScenario.Location)
text += s(spaceFilling) + line(feature.Uri, astScenario.Location)
fmt.Fprintln(f.out, "\n"+text)
}
func (f *pretty) printUndefinedPickle(pickle *messages.Pickle) {
astScenario := f.findScenario(pickle.AstNodeIds[0])
astBackground := f.findBackground(pickle.AstNodeIds[0])
feature := f.storage.mustGetFeature(pickle.Uri)
astScenario := feature.findScenario(pickle.AstNodeIds[0])
astBackground := feature.findBackground(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle)
if astBackground != nil {
fmt.Fprintln(f.out, "\n"+s(f.indent)+keywordAndName(astBackground.Keyword, astBackground.Name))
@ -166,7 +169,7 @@ func (f *pretty) printUndefinedPickle(pickle *messages.Pickle) {
// do not print scenario headers and examples multiple times
if len(astScenario.Examples) > 0 {
exampleTable, exampleRow := f.findExample(pickle.AstNodeIds[1])
exampleTable, exampleRow := feature.findExample(pickle.AstNodeIds[1])
firstExampleRow := exampleTable.TableBody[0].Id == exampleRow.Id
firstExamplesTable := astScenario.Examples[0].Location.Line == exampleTable.Location.Line
@ -175,7 +178,7 @@ func (f *pretty) printUndefinedPickle(pickle *messages.Pickle) {
}
}
f.printScenarioHeader(astScenario, maxLength-scenarioHeaderLength)
f.printScenarioHeader(pickle, astScenario, maxLength-scenarioHeaderLength)
for _, examples := range astScenario.Examples {
max := longestExampleRow(examples, cyan, cyan)
@ -202,17 +205,16 @@ func (f *pretty) Summary() {
for _, fail := range failedStepResults {
pickle := f.storage.mustGetPickle(fail.PickleID)
pickleStep := f.storage.mustGetPickleStep(fail.PickleStepID)
feature := f.storage.mustGetFeature(pickle.Uri)
feature := f.findFeature(pickle.AstNodeIds[0])
astScenario := f.findScenario(pickle.AstNodeIds[0])
astScenario := feature.findScenario(pickle.AstNodeIds[0])
scenarioDesc := fmt.Sprintf("%s: %s", astScenario.Keyword, pickle.Name)
astStep := f.findStep(pickleStep.AstNodeIds[0])
astStep := feature.findStep(pickleStep.AstNodeIds[0])
stepDesc := strings.TrimSpace(astStep.Keyword) + " " + pickleStep.Text
fmt.Fprintln(f.out, s(f.indent)+red(scenarioDesc)+f.line(feature.Uri, astScenario.Location))
fmt.Fprintln(f.out, s(f.indent*2)+red(stepDesc)+f.line(feature.Uri, astStep.Location))
fmt.Fprintln(f.out, s(f.indent)+red(scenarioDesc)+line(feature.Uri, astScenario.Location))
fmt.Fprintln(f.out, s(f.indent*2)+red(stepDesc)+line(feature.Uri, astStep.Location))
fmt.Fprintln(f.out, s(f.indent*3)+red("Error: ")+redb(fmt.Sprintf("%+v", fail.err))+"\n")
}
}
@ -224,10 +226,11 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in
var errorMsg string
var clr = green
astScenario := f.findScenario(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle.AstNodeIds[0])
feature := f.storage.mustGetFeature(pickle.Uri)
astScenario := feature.findScenario(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle)
exampleTable, exampleRow := f.findExample(pickle.AstNodeIds[1])
exampleTable, exampleRow := feature.findExample(pickle.AstNodeIds[1])
printExampleHeader := exampleTable.TableBody[0].Id == exampleRow.Id
firstExamplesTable := astScenario.Examples[0].Location.Line == exampleTable.Location.Line
@ -235,7 +238,7 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in
firstExecutedScenarioStep := len(pickleStepResults) == backgroundSteps+1
if firstExamplesTable && printExampleHeader && firstExecutedScenarioStep {
f.printScenarioHeader(astScenario, maxLength-scenarioHeaderLength)
f.printScenarioHeader(pickle, astScenario, maxLength-scenarioHeaderLength)
}
if len(exampleTable.TableBody) == 0 {
@ -265,7 +268,7 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in
// in first example, we need to print steps
pickleStep := f.storage.mustGetPickleStep(result.PickleStepID)
astStep := f.findStep(pickleStep.AstNodeIds[0])
astStep := feature.findStep(pickleStep.AstNodeIds[0])
var text = ""
if result.def != nil {
@ -282,7 +285,7 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in
text = cyan(astStep.Text)
}
_, maxLength := f.scenarioLengths(pickle.AstNodeIds[0])
_, maxLength := f.scenarioLengths(pickle)
stepLength := f.lengthPickleStep(astStep.Keyword, astStep.Text)
text += s(maxLength - stepLength)
@ -336,9 +339,10 @@ func (f *pretty) printTableHeader(row *messages.GherkinDocument_Feature_TableRow
}
func (f *pretty) printStep(pickle *messages.Pickle, pickleStep *messages.Pickle_PickleStep) {
astBackground := f.findBackground(pickle.AstNodeIds[0])
astScenario := f.findScenario(pickle.AstNodeIds[0])
astStep := f.findStep(pickleStep.AstNodeIds[0])
feature := f.storage.mustGetFeature(pickle.Uri)
astBackground := feature.findBackground(pickle.AstNodeIds[0])
astScenario := feature.findScenario(pickle.AstNodeIds[0])
astStep := feature.findStep(pickleStep.AstNodeIds[0])
var backgroundSteps int
if astBackground != nil {
@ -374,12 +378,12 @@ func (f *pretty) printStep(pickle *messages.Pickle, pickleStep *messages.Pickle_
return
}
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle.AstNodeIds[0])
scenarioHeaderLength, maxLength := f.scenarioLengths(pickle)
stepLength := f.lengthPickleStep(astStep.Keyword, pickleStep.Text)
firstExecutedScenarioStep := len(pickleStepResults) == backgroundSteps+1
if !astBackgroundStep && firstExecutedScenarioStep {
f.printScenarioHeader(astScenario, maxLength-scenarioHeaderLength)
f.printScenarioHeader(pickle, astScenario, maxLength-scenarioHeaderLength)
}
pickleStepResult := f.storage.mustGetPickleStepResult(pickleStep.Id)
@ -519,7 +523,7 @@ func (f *pretty) longestStep(steps []*messages.GherkinDocument_Feature_Step, pic
}
// a line number representation in feature file
func (f *pretty) line(path string, loc *messages.Location) string {
func line(path string, loc *messages.Location) string {
return " " + blackb(fmt.Sprintf("# %s:%d", path, loc.Line))
}

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

@ -48,12 +48,13 @@ func (f *progress) Summary() {
if sr.Status == failed {
pickle := f.storage.mustGetPickle(sr.PickleID)
pickleStep := f.storage.mustGetPickleStep(sr.PickleStepID)
feature := f.storage.mustGetFeature(pickle.Uri)
sc := f.findScenario(pickle.AstNodeIds[0])
sc := feature.findScenario(pickle.AstNodeIds[0])
scenarioDesc := fmt.Sprintf("%s: %s", sc.Keyword, pickle.Name)
scenarioLine := fmt.Sprintf("%s:%d", pickle.Uri, sc.Location.Line)
step := f.findStep(pickleStep.AstNodeIds[0])
step := feature.findStep(pickleStep.AstNodeIds[0])
stepDesc := strings.TrimSpace(step.Keyword) + " " + pickleStep.Text
stepLine := fmt.Sprintf("%s:%d", pickle.Uri, step.Location.Line)

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

@ -27,13 +27,15 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) {
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(basicGherkinFeature), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
var buf bytes.Buffer
w := colors.Uncolored(&buf)
r := runner{
fmt: progressFunc("progress", w),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^one$`, func() error { return nil })
s.Step(`^two$`, func() error { panic("omg") })
@ -41,7 +43,8 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) {
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}
@ -49,7 +52,7 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) {
require.True(t, failed)
actual := buf.String()
assert.Contains(t, actual, "godog/fmt_progress_test.go:39")
assert.Contains(t, actual, "godog/fmt_progress_test.go:41")
}
func TestProgressFormatterWithPanicInMultistep(t *testing.T) {
@ -58,13 +61,15 @@ func TestProgressFormatterWithPanicInMultistep(t *testing.T) {
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(basicGherkinFeature), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
var buf bytes.Buffer
w := colors.Uncolored(&buf)
r := runner{
fmt: progressFunc("progress", w),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^sub1$`, func() error { return nil })
s.Step(`^sub-sub$`, func() error { return nil })
@ -75,7 +80,8 @@ func TestProgressFormatterWithPanicInMultistep(t *testing.T) {
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}
@ -89,13 +95,15 @@ func TestProgressFormatterMultistepTemplates(t *testing.T) {
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(basicGherkinFeature), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
var buf bytes.Buffer
w := colors.Uncolored(&buf)
r := runner{
fmt: progressFunc("progress", w),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^sub-sub$`, func() error { return nil })
s.Step(`^substep$`, func() Steps { return Steps{"sub-sub", `unavailable "John" cost 5`, "one", "three"} })
@ -105,7 +113,8 @@ func TestProgressFormatterMultistepTemplates(t *testing.T) {
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}
@ -162,13 +171,15 @@ Feature: basic
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(featureSource), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
var buf bytes.Buffer
w := colors.Uncolored(&buf)
r := runner{
fmt: progressFunc("progress", w),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^one$`, func() error { return nil })
s.Step(`^two:$`, func(doc *messages.PickleStepArgument_PickleDocString) Steps { return Steps{"one"} })
@ -176,7 +187,8 @@ Feature: basic
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}
@ -197,7 +209,9 @@ Feature: basic
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(featureSource), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
var subStep = `three:
"""
@ -208,7 +222,7 @@ Feature: basic
w := colors.Uncolored(&buf)
r := runner{
fmt: progressFunc("progress", w),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^one$`, func() error { return nil })
s.Step(`^two$`, func() Steps { return Steps{subStep} })
@ -217,7 +231,8 @@ Feature: basic
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}

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

@ -237,6 +237,8 @@ func runWithOptions(suite string, runner runner, opt Options) int {
runner.storage = newStorage()
for _, feat := range runner.features {
runner.storage.mustInsertFeature(feat)
for _, pickle := range feat.pickles {
runner.storage.mustInsertPickle(pickle)
}

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

@ -64,11 +64,13 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(basicGherkinFeature), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
r := runner{
fmt: progressFunc("progress", ioutil.Discard),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^one$`, func() error { return nil })
s.Step(`^two$`, func() error { return ErrPending })
@ -76,7 +78,8 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) {
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}
@ -94,11 +97,13 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(basicGherkinFeature), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
r := runner{
fmt: progressFunc("progress", ioutil.Discard),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^one$`, func() error { return nil })
// two - is undefined
@ -106,7 +111,8 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) {
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}
@ -124,11 +130,13 @@ func TestShouldFailOnError(t *testing.T) {
gd, err := gherkin.ParseGherkinDocument(strings.NewReader(basicGherkinFeature), (&messages.Incrementing{}).NewId)
require.NoError(t, err)
pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
gd.Uri = path
ft := feature{GherkinDocument: gd}
ft.pickles = gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId)
r := runner{
fmt: progressFunc("progress", ioutil.Discard),
features: []*feature{{GherkinDocument: gd, pickles: pickles}},
features: []*feature{&ft},
initializer: func(s *Suite) {
s.Step(`^one$`, func() error { return nil })
s.Step(`^two$`, func() error { return fmt.Errorf("error") })
@ -136,7 +144,8 @@ func TestShouldFailOnError(t *testing.T) {
}
r.storage = newStorage()
for _, pickle := range pickles {
r.storage.mustInsertFeature(&ft)
for _, pickle := range ft.pickles {
r.storage.mustInsertPickle(pickle)
}

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

@ -11,6 +11,9 @@ const (
writeMode bool = true
readMode bool = false
tableFeature string = "feature"
tableFeatureIndexURI string = "id"
tablePickle string = "pickle"
tablePickleIndexID string = "id"
tablePickleIndexURI string = "uri"
@ -35,6 +38,16 @@ func newStorage() *storage {
// Create the DB schema
schema := memdb.DBSchema{
Tables: map[string]*memdb.TableSchema{
tableFeature: {
Name: tableFeature,
Indexes: map[string]*memdb.IndexSchema{
tableFeatureIndexURI: {
Name: tableFeatureIndexURI,
Unique: true,
Indexer: &memdb.StringFieldIndex{Field: "Uri"},
},
},
},
tablePickle: {
Name: tablePickle,
Indexes: map[string]*memdb.IndexSchema{
@ -119,29 +132,12 @@ func (s *storage) mustInsertPickle(p *messages.Pickle) {
}
func (s *storage) mustGetPickle(id string) *messages.Pickle {
txn := s.db.Txn(readMode)
defer txn.Abort()
var v interface{}
v, err := txn.First(tablePickle, tablePickleIndexID, id)
if err != nil {
panic(err)
} else if v == nil {
panic("Couldn't find pickle with ID: " + id)
}
v := s.mustFirst(tablePickle, tablePickleIndexID, id)
return v.(*messages.Pickle)
}
func (s *storage) mustGetPickles(uri string) (ps []*messages.Pickle) {
txn := s.db.Txn(readMode)
defer txn.Abort()
it, err := txn.Get(tablePickle, tablePickleIndexURI, uri)
if err != nil {
panic(err)
}
it := s.mustGet(tablePickle, tablePickleIndexURI, uri)
for v := it.Next(); v != nil; v = it.Next() {
ps = append(ps, v.(*messages.Pickle))
}
@ -150,73 +146,34 @@ func (s *storage) mustGetPickles(uri string) (ps []*messages.Pickle) {
}
func (s *storage) mustGetPickleStep(id string) *messages.Pickle_PickleStep {
txn := s.db.Txn(readMode)
defer txn.Abort()
var v interface{}
v, err := txn.First(tablePickleStep, tablePickleStepIndexID, id)
if err != nil {
panic(err)
} else if v == nil {
panic("Couldn't find pickle step with ID: " + id)
}
v := s.mustFirst(tablePickleStep, tablePickleStepIndexID, id)
return v.(*messages.Pickle_PickleStep)
}
func (s *storage) mustInsertPickleResult(pr pickleResult) {
txn := s.db.Txn(writeMode)
if err := txn.Insert(tablePickleResult, pr); err != nil {
panic(err)
}
txn.Commit()
s.mustInsert(tablePickleResult, pr)
}
func (s *storage) mustInsertPickleStepResult(psr pickleStepResult) {
txn := s.db.Txn(writeMode)
if err := txn.Insert(tablePickleStepResult, psr); err != nil {
panic(err)
}
txn.Commit()
s.mustInsert(tablePickleStepResult, psr)
}
func (s *storage) mustGetPickleResult(id string) pickleResult {
pr, err := s.getPickleResult(id)
if err != nil {
panic(err)
}
return pr
v := s.mustFirst(tablePickleResult, tablePickleResultIndexPickleID, id)
return v.(pickleResult)
}
func (s *storage) getPickleResult(id string) (_ pickleResult, err error) {
txn := s.db.Txn(readMode)
defer txn.Abort()
v, err := txn.First(tablePickleResult, tablePickleResultIndexPickleID, id)
v, err := s.first(tablePickleResult, tablePickleResultIndexPickleID, id)
if err != nil {
return
} else if v == nil {
err = fmt.Errorf("Couldn't find pickle result with ID: %s", id)
return
}
return v.(pickleResult), nil
}
func (s *storage) mustGetPickleResults() (prs []pickleResult) {
txn := s.db.Txn(readMode)
defer txn.Abort()
it, err := txn.Get(tablePickleResult, tablePickleResultIndexPickleID)
if err != nil {
panic(err)
}
it := s.mustGet(tablePickleResult, tablePickleResultIndexPickleID)
for v := it.Next(); v != nil; v = it.Next() {
prs = append(prs, v.(pickleResult))
}
@ -225,28 +182,12 @@ func (s *storage) mustGetPickleResults() (prs []pickleResult) {
}
func (s *storage) mustGetPickleStepResult(id string) pickleStepResult {
txn := s.db.Txn(readMode)
defer txn.Abort()
v, err := txn.First(tablePickleStepResult, tablePickleStepResultIndexPickleStepID, id)
if err != nil {
panic(err)
} else if v == nil {
panic("Couldn't find pickle step result with ID: " + id)
}
v := s.mustFirst(tablePickleStepResult, tablePickleStepResultIndexPickleStepID, id)
return v.(pickleStepResult)
}
func (s *storage) mustGetPickleStepResultsByPickleID(pickleID string) (psrs []pickleStepResult) {
txn := s.db.Txn(readMode)
defer txn.Abort()
it, err := txn.Get(tablePickleStepResult, tablePickleStepResultIndexPickleID, pickleID)
if err != nil {
panic(err)
}
it := s.mustGet(tablePickleStepResult, tablePickleStepResultIndexPickleID, pickleID)
for v := it.Next(); v != nil; v = it.Next() {
psrs = append(psrs, v.(pickleStepResult))
}
@ -255,17 +196,74 @@ func (s *storage) mustGetPickleStepResultsByPickleID(pickleID string) (psrs []pi
}
func (s *storage) mustGetPickleStepResultsByStatus(status stepResultStatus) (psrs []pickleStepResult) {
txn := s.db.Txn(readMode)
defer txn.Abort()
it, err := txn.Get(tablePickleStepResult, tablePickleStepResultIndexStatus, status)
if err != nil {
panic(err)
}
it := s.mustGet(tablePickleStepResult, tablePickleStepResultIndexStatus, status)
for v := it.Next(); v != nil; v = it.Next() {
psrs = append(psrs, v.(pickleStepResult))
}
return psrs
}
func (s *storage) mustInsertFeature(f *feature) {
s.mustInsert(tableFeature, f)
}
func (s *storage) mustGetFeature(uri string) *feature {
v := s.mustFirst(tableFeature, tableFeatureIndexURI, uri)
return v.(*feature)
}
func (s *storage) mustGetFeatures() (fs []*feature) {
it := s.mustGet(tableFeature, tableFeatureIndexURI)
for v := it.Next(); v != nil; v = it.Next() {
fs = append(fs, v.(*feature))
}
return
}
func (s *storage) mustInsert(table string, obj interface{}) {
txn := s.db.Txn(writeMode)
if err := txn.Insert(table, obj); err != nil {
panic(err)
}
txn.Commit()
}
func (s *storage) first(table, index string, args ...interface{}) (v interface{}, err error) {
txn := s.db.Txn(readMode)
defer txn.Abort()
v, err = txn.First(table, index, args...)
if err != nil {
return
} else if v == nil {
err = fmt.Errorf("Couldn't find index: %q in table: %q with args: %+v", index, table, args)
return
}
return
}
func (s *storage) mustFirst(table, index string, args ...interface{}) interface{} {
v, err := s.first(table, index, args...)
if err != nil {
panic(err)
}
return v
}
func (s *storage) mustGet(table, index string, args ...interface{}) memdb.ResultIterator {
txn := s.db.Txn(readMode)
defer txn.Abort()
it, err := txn.Get(table, index, args...)
if err != nil {
panic(err)
}
return it
}

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

@ -98,11 +98,11 @@ func (f feature) startedAt() time.Time {
return f.time
}
type sortByName []*feature
type sortFeaturesByName []*feature
func (s sortByName) Len() int { return len(s) }
func (s sortByName) Less(i, j int) bool { return s[i].Feature.Name < s[j].Feature.Name }
func (s sortByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
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 sortPicklesByID []*messages.Pickle

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

@ -184,6 +184,8 @@ func (s *suiteContext) iRunFeatureSuiteWithTags(tags string) error {
s.testedSuite.storage = newStorage()
for _, feat := range s.testedSuite.features {
s.testedSuite.storage.mustInsertFeature(feat)
for _, pickle := range feat.pickles {
s.testedSuite.storage.mustInsertPickle(pickle)
}
@ -212,6 +214,8 @@ func (s *suiteContext) iRunFeatureSuiteWithFormatter(name string) error {
s.testedSuite.storage = newStorage()
for _, feat := range s.testedSuite.features {
s.testedSuite.storage.mustInsertFeature(feat)
for _, pickle := range feat.pickles {
s.testedSuite.storage.mustInsertPickle(pickle)
}

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

@ -146,6 +146,8 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithTags(tags string) error {
tc.testedSuite.storage = newStorage()
for _, feat := range tc.testedSuite.features {
tc.testedSuite.storage.mustInsertFeature(feat)
for _, pickle := range feat.pickles {
tc.testedSuite.storage.mustInsertPickle(pickle)
}
@ -174,6 +176,8 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithFormatter(name string) erro
tc.testedSuite.storage = newStorage()
for _, feat := range tc.testedSuite.features {
tc.testedSuite.storage.mustInsertFeature(feat)
for _, pickle := range feat.pickles {
tc.testedSuite.storage.mustInsertPickle(pickle)
}