Added an in-mem storage for pickles
Этот коммит содержится в:
		
							родитель
							
								
									055f87f731
								
							
						
					
					
						коммит
						4356addf9f
					
				
					 15 изменённых файлов: 350 добавлений и 94 удалений
				
			
		
							
								
								
									
										37
									
								
								fmt.go
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								fmt.go
									
										
									
									
									
								
							|  | @ -91,6 +91,10 @@ type ConcurrentFormatter interface { | |||
| 	Sync(ConcurrentFormatter) | ||||
| } | ||||
| 
 | ||||
| type storageFormatter interface { | ||||
| 	setStorage(*storage) | ||||
| } | ||||
| 
 | ||||
| // FormatterFunc builds a formatter with given | ||||
| // suite name and io.Writer to record output | ||||
| type FormatterFunc func(string, io.Writer) Formatter | ||||
|  | @ -140,13 +144,14 @@ type stepResult struct { | |||
| 	time   time.Time | ||||
| 	err    error | ||||
| 
 | ||||
| 	owner *messages.Pickle | ||||
| 	step  *messages.Pickle_PickleStep | ||||
| 	pickleID     string | ||||
| 	pickleStepID string | ||||
| 
 | ||||
| 	def *StepDefinition | ||||
| } | ||||
| 
 | ||||
| func newStepResult(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) *stepResult { | ||||
| 	return &stepResult{time: timeNowFunc(), owner: pickle, step: step, def: match} | ||||
| func newStepResult(pickleID, pickleStepID string, match *StepDefinition) *stepResult { | ||||
| 	return &stepResult{time: timeNowFunc(), pickleID: pickleID, pickleStepID: pickleStepID, def: match} | ||||
| } | ||||
| 
 | ||||
| func newBaseFmt(suite string, out io.Writer) *basefmt { | ||||
|  | @ -166,6 +171,8 @@ type basefmt struct { | |||
| 	owner  interface{} | ||||
| 	indent int | ||||
| 
 | ||||
| 	storage *storage | ||||
| 
 | ||||
| 	started  time.Time | ||||
| 	features []*feature | ||||
| 
 | ||||
|  | @ -173,6 +180,10 @@ type basefmt struct { | |||
| 	lock         *sync.Mutex | ||||
| } | ||||
| 
 | ||||
| func (f *basefmt) setStorage(st *storage) { | ||||
| 	f.storage = st | ||||
| } | ||||
| 
 | ||||
| func (f *basefmt) lastFeature() *feature { | ||||
| 	return f.features[len(f.features)-1] | ||||
| } | ||||
|  | @ -245,7 +256,7 @@ func (f *basefmt) Pickle(p *messages.Pickle) { | |||
| 
 | ||||
| 	feature := f.features[len(f.features)-1] | ||||
| 
 | ||||
| 	pr := pickleResult{name: p.Name, astNodeIDs: p.AstNodeIds, time: timeNowFunc()} | ||||
| 	pr := pickleResult{pickleID: p.Id, time: timeNowFunc()} | ||||
| 	feature.pickleResults = append(feature.pickleResults, &pr) | ||||
| } | ||||
| 
 | ||||
|  | @ -264,7 +275,7 @@ func (f *basefmt) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleSt | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	s := newStepResult(pickle, step, match) | ||||
| 	s := newStepResult(pickle.Id, step.Id, match) | ||||
| 	s.status = passed | ||||
| 	f.lastFeature().appendStepResult(s) | ||||
| } | ||||
|  | @ -273,7 +284,7 @@ func (f *basefmt) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleS | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	s := newStepResult(pickle, step, match) | ||||
| 	s := newStepResult(pickle.Id, step.Id, match) | ||||
| 	s.status = skipped | ||||
| 	f.lastFeature().appendStepResult(s) | ||||
| } | ||||
|  | @ -282,7 +293,7 @@ func (f *basefmt) Undefined(pickle *messages.Pickle, step *messages.Pickle_Pickl | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	s := newStepResult(pickle, step, match) | ||||
| 	s := newStepResult(pickle.Id, step.Id, match) | ||||
| 	s.status = undefined | ||||
| 	f.lastFeature().appendStepResult(s) | ||||
| } | ||||
|  | @ -291,7 +302,7 @@ func (f *basefmt) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleSt | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	s := newStepResult(pickle, step, match) | ||||
| 	s := newStepResult(pickle.Id, step.Id, match) | ||||
| 	s.status = failed | ||||
| 	s.err = err | ||||
| 	f.lastFeature().appendStepResult(s) | ||||
|  | @ -301,7 +312,7 @@ func (f *basefmt) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleS | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	s := newStepResult(pickle, step, match) | ||||
| 	s := newStepResult(pickle.Id, step.Id, match) | ||||
| 	s.status = pending | ||||
| 	f.lastFeature().appendStepResult(s) | ||||
| } | ||||
|  | @ -450,8 +461,10 @@ func (f *basefmt) snippets() string { | |||
| 	var snips []undefinedSnippet | ||||
| 	// build snippets | ||||
| 	for _, u := range undefinedStepResults { | ||||
| 		steps := []string{u.step.Text} | ||||
| 		arg := u.step.Argument | ||||
| 		pickleStep := f.storage.mustGetPickleStep(u.pickleStepID) | ||||
| 
 | ||||
| 		steps := []string{pickleStep.Text} | ||||
| 		arg := pickleStep.Argument | ||||
| 		if u.def != nil { | ||||
| 			steps = u.def.undefined | ||||
| 			arg = nil | ||||
|  |  | |||
|  | @ -79,7 +79,9 @@ func (f *cukefmt) buildCukeElements(pickleResults []*pickleResult) (res []cukeEl | |||
| 	res = make([]cukeElement, len(pickleResults)) | ||||
| 
 | ||||
| 	for idx, pickleResult := range pickleResults { | ||||
| 		cukeElement := f.buildCukeElement(pickleResult.name, pickleResult.astNodeIDs) | ||||
| 		pickle := f.storage.mustGetPickle(pickleResult.pickleID) | ||||
| 
 | ||||
| 		cukeElement := f.buildCukeElement(pickle.Name, pickle.AstNodeIds) | ||||
| 
 | ||||
| 		stepStartedAt := pickleResult.startedAt() | ||||
| 
 | ||||
|  | @ -237,19 +239,21 @@ func (f *cukefmt) buildCukeElement(pickleName string, pickleAstNodeIDs []string) | |||
| } | ||||
| 
 | ||||
| func (f *cukefmt) buildCukeStep(stepResult *stepResult) (cukeStep cukeStep) { | ||||
| 	step := f.findStep(stepResult.step.AstNodeIds[0]) | ||||
| 	pickle := f.storage.mustGetPickle(stepResult.pickleID) | ||||
| 	pickleStep := f.storage.mustGetPickleStep(stepResult.pickleStepID) | ||||
| 	step := f.findStep(pickleStep.AstNodeIds[0]) | ||||
| 
 | ||||
| 	line := step.Location.Line | ||||
| 	if len(stepResult.owner.AstNodeIds) == 2 { | ||||
| 		_, row := f.findExample(stepResult.owner.AstNodeIds[1]) | ||||
| 	if len(pickle.AstNodeIds) == 2 { | ||||
| 		_, row := f.findExample(pickle.AstNodeIds[1]) | ||||
| 		line = row.Location.Line | ||||
| 	} | ||||
| 
 | ||||
| 	cukeStep.Name = stepResult.step.Text | ||||
| 	cukeStep.Name = pickleStep.Text | ||||
| 	cukeStep.Line = int(line) | ||||
| 	cukeStep.Keyword = step.Keyword | ||||
| 
 | ||||
| 	arg := stepResult.step.Argument | ||||
| 	arg := pickleStep.Argument | ||||
| 
 | ||||
| 	if arg.GetDocString() != nil && step.GetDocString() != nil { | ||||
| 		cukeStep.Docstring = &cukeDocstring{} | ||||
|  | @ -279,7 +283,7 @@ func (f *cukefmt) buildCukeStep(stepResult *stepResult) (cukeStep cukeStep) { | |||
| 	} | ||||
| 
 | ||||
| 	if stepResult.status == undefined || stepResult.status == pending { | ||||
| 		cukeStep.Match.Location = fmt.Sprintf("%s:%d", stepResult.owner.Uri, step.Location.Line) | ||||
| 		cukeStep.Match.Location = fmt.Sprintf("%s:%d", pickle.Uri, step.Location.Line) | ||||
| 	} | ||||
| 
 | ||||
| 	return cukeStep | ||||
|  |  | |||
|  | @ -145,8 +145,9 @@ func (f *events) Copy(cf ConcurrentFormatter) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (f *events) step(res *stepResult) { | ||||
| 	step := f.findStep(res.step.AstNodeIds[0]) | ||||
| func (f *events) step(pickle *messages.Pickle, res *stepResult) { | ||||
| 	pickleStep := f.storage.mustGetPickleStep(res.pickleStepID) | ||||
| 	step := f.findStep(pickleStep.AstNodeIds[0]) | ||||
| 
 | ||||
| 	var errMsg string | ||||
| 	if res.err != nil { | ||||
|  | @ -160,13 +161,13 @@ func (f *events) step(res *stepResult) { | |||
| 		Summary   string `json:"summary,omitempty"` | ||||
| 	}{ | ||||
| 		"TestStepFinished", | ||||
| 		fmt.Sprintf("%s:%d", res.owner.Uri, step.Location.Line), | ||||
| 		fmt.Sprintf("%s:%d", pickle.Uri, step.Location.Line), | ||||
| 		timeNowFunc().UnixNano() / nanoSec, | ||||
| 		res.status.String(), | ||||
| 		errMsg, | ||||
| 	}) | ||||
| 
 | ||||
| 	if isLastStep(res.owner, res.step) { | ||||
| 	if isLastStep(pickle, pickleStep) { | ||||
| 		var status string | ||||
| 
 | ||||
| 		for _, stepResult := range f.lastFeature().lastPickleResult().stepResults { | ||||
|  | @ -189,7 +190,7 @@ func (f *events) step(res *stepResult) { | |||
| 			Status    string `json:"status"` | ||||
| 		}{ | ||||
| 			"TestCaseFinished", | ||||
| 			f.scenarioLocation(res.owner), | ||||
| 			f.scenarioLocation(pickle), | ||||
| 			timeNowFunc().UnixNano() / nanoSec, | ||||
| 			status, | ||||
| 		}) | ||||
|  | @ -249,7 +250,7 @@ func (f *events) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleSte | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.step(f.lastStepResult()) | ||||
| 	f.step(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *events) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) { | ||||
|  | @ -258,7 +259,7 @@ func (f *events) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleSt | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.step(f.lastStepResult()) | ||||
| 	f.step(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *events) Undefined(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) { | ||||
|  | @ -267,7 +268,7 @@ func (f *events) Undefined(pickle *messages.Pickle, step *messages.Pickle_Pickle | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.step(f.lastStepResult()) | ||||
| 	f.step(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *events) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition, err error) { | ||||
|  | @ -276,7 +277,7 @@ func (f *events) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleSte | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.step(f.lastStepResult()) | ||||
| 	f.step(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *events) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) { | ||||
|  | @ -285,7 +286,7 @@ func (f *events) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleSt | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.step(f.lastStepResult()) | ||||
| 	f.step(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *events) scenarioLocation(pickle *messages.Pickle) string { | ||||
|  |  | |||
							
								
								
									
										31
									
								
								fmt_junit.go
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								fmt_junit.go
									
										
									
									
									
								
							|  | @ -23,7 +23,7 @@ type junitFormatter struct { | |||
| } | ||||
| 
 | ||||
| func (f *junitFormatter) Summary() { | ||||
| 	suite := buildJUNITPackageSuite(f.suiteName, f.started, f.features) | ||||
| 	suite := f.buildJUNITPackageSuite() | ||||
| 
 | ||||
| 	_, err := io.WriteString(f.out, xml.Header) | ||||
| 	if err != nil { | ||||
|  | @ -53,16 +53,16 @@ func junitTimeDuration(from, to time.Time) string { | |||
| 	return strconv.FormatFloat(to.Sub(from).Seconds(), 'f', -1, 64) | ||||
| } | ||||
| 
 | ||||
| func buildJUNITPackageSuite(suiteName string, startedAt time.Time, features []*feature) junitPackageSuite { | ||||
| func (f *junitFormatter) buildJUNITPackageSuite() junitPackageSuite { | ||||
| 	suite := junitPackageSuite{ | ||||
| 		Name:       suiteName, | ||||
| 		TestSuites: make([]*junitTestSuite, len(features)), | ||||
| 		Time:       junitTimeDuration(startedAt, timeNowFunc()), | ||||
| 		Name:       f.suiteName, | ||||
| 		TestSuites: make([]*junitTestSuite, len(f.features)), | ||||
| 		Time:       junitTimeDuration(f.started, timeNowFunc()), | ||||
| 	} | ||||
| 
 | ||||
| 	sort.Sort(sortByName(features)) | ||||
| 	sort.Sort(sortByName(f.features)) | ||||
| 
 | ||||
| 	for idx, feat := range features { | ||||
| 	for idx, feat := range f.features { | ||||
| 		ts := junitTestSuite{ | ||||
| 			Name:      feat.GherkinDocument.Feature.Name, | ||||
| 			Time:      junitTimeDuration(feat.startedAt(), feat.finishedAt()), | ||||
|  | @ -71,7 +71,8 @@ func buildJUNITPackageSuite(suiteName string, startedAt time.Time, features []*f | |||
| 
 | ||||
| 		var testcaseNames = make(map[string]int) | ||||
| 		for _, pickleResult := range feat.pickleResults { | ||||
| 			testcaseNames[pickleResult.name] = testcaseNames[pickleResult.name] + 1 | ||||
| 			pickle := f.storage.mustGetPickle(pickleResult.pickleID) | ||||
| 			testcaseNames[pickle.Name] = testcaseNames[pickle.Name] + 1 | ||||
| 		} | ||||
| 
 | ||||
| 		var outlineNo = make(map[string]int) | ||||
|  | @ -79,7 +80,9 @@ func buildJUNITPackageSuite(suiteName string, startedAt time.Time, features []*f | |||
| 			tc := junitTestCase{} | ||||
| 			tc.Time = junitTimeDuration(pickleResult.startedAt(), pickleResult.finishedAt()) | ||||
| 
 | ||||
| 			tc.Name = pickleResult.name | ||||
| 			pickle := f.storage.mustGetPickle(pickleResult.pickleID) | ||||
| 
 | ||||
| 			tc.Name = pickle.Name | ||||
| 			if testcaseNames[tc.Name] > 1 { | ||||
| 				outlineNo[tc.Name] = outlineNo[tc.Name] + 1 | ||||
| 				tc.Name += fmt.Sprintf(" #%d", outlineNo[tc.Name]) | ||||
|  | @ -89,30 +92,32 @@ func buildJUNITPackageSuite(suiteName string, startedAt time.Time, features []*f | |||
| 			suite.Tests++ | ||||
| 
 | ||||
| 			for _, stepResult := range pickleResult.stepResults { | ||||
| 				pickleStep := f.storage.mustGetPickleStep(stepResult.pickleStepID) | ||||
| 
 | ||||
| 				switch stepResult.status { | ||||
| 				case passed: | ||||
| 					tc.Status = passed.String() | ||||
| 				case failed: | ||||
| 					tc.Status = failed.String() | ||||
| 					tc.Failure = &junitFailure{ | ||||
| 						Message: fmt.Sprintf("Step %s: %s", stepResult.step.Text, stepResult.err), | ||||
| 						Message: fmt.Sprintf("Step %s: %s", pickleStep.Text, stepResult.err), | ||||
| 					} | ||||
| 				case skipped: | ||||
| 					tc.Error = append(tc.Error, &junitError{ | ||||
| 						Type:    "skipped", | ||||
| 						Message: fmt.Sprintf("Step %s", stepResult.step.Text), | ||||
| 						Message: fmt.Sprintf("Step %s", pickleStep.Text), | ||||
| 					}) | ||||
| 				case undefined: | ||||
| 					tc.Status = undefined.String() | ||||
| 					tc.Error = append(tc.Error, &junitError{ | ||||
| 						Type:    "undefined", | ||||
| 						Message: fmt.Sprintf("Step %s", stepResult.step.Text), | ||||
| 						Message: fmt.Sprintf("Step %s", pickleStep.Text), | ||||
| 					}) | ||||
| 				case pending: | ||||
| 					tc.Status = pending.String() | ||||
| 					tc.Error = append(tc.Error, &junitError{ | ||||
| 						Type:    "pending", | ||||
| 						Message: fmt.Sprintf("Step %s: TODO: write pending definition", stepResult.step.Text), | ||||
| 						Message: fmt.Sprintf("Step %s: TODO: write pending definition", pickleStep.Text), | ||||
| 					}) | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ func (f *pretty) Passed(pickle *messages.Pickle, step *messages.Pickle_PickleSte | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.printStep(f.lastStepResult()) | ||||
| 	f.printStep(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) { | ||||
|  | @ -70,7 +70,7 @@ func (f *pretty) Skipped(pickle *messages.Pickle, step *messages.Pickle_PickleSt | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.printStep(f.lastStepResult()) | ||||
| 	f.printStep(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) Undefined(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) { | ||||
|  | @ -79,7 +79,7 @@ func (f *pretty) Undefined(pickle *messages.Pickle, step *messages.Pickle_Pickle | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.printStep(f.lastStepResult()) | ||||
| 	f.printStep(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition, err error) { | ||||
|  | @ -88,7 +88,7 @@ func (f *pretty) Failed(pickle *messages.Pickle, step *messages.Pickle_PickleSte | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.printStep(f.lastStepResult()) | ||||
| 	f.printStep(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleStep, match *StepDefinition) { | ||||
|  | @ -97,7 +97,7 @@ func (f *pretty) Pending(pickle *messages.Pickle, step *messages.Pickle_PickleSt | |||
| 	f.lock.Lock() | ||||
| 	defer f.lock.Unlock() | ||||
| 
 | ||||
| 	f.printStep(f.lastStepResult()) | ||||
| 	f.printStep(pickle, f.lastStepResult()) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) Sync(cf ConcurrentFormatter) { | ||||
|  | @ -196,13 +196,16 @@ func (f *pretty) Summary() { | |||
| 	if len(failedStepResults) > 0 { | ||||
| 		fmt.Fprintln(f.out, "\n--- "+red("Failed steps:")+"\n") | ||||
| 		for _, fail := range failedStepResults { | ||||
| 			feature := f.findFeature(fail.owner.AstNodeIds[0]) | ||||
| 			pickle := f.storage.mustGetPickle(fail.pickleID) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(fail.pickleStepID) | ||||
| 
 | ||||
| 			astScenario := f.findScenario(fail.owner.AstNodeIds[0]) | ||||
| 			scenarioDesc := fmt.Sprintf("%s: %s", astScenario.Keyword, fail.owner.Name) | ||||
| 			feature := f.findFeature(pickle.AstNodeIds[0]) | ||||
| 
 | ||||
| 			astStep := f.findStep(fail.step.AstNodeIds[0]) | ||||
| 			stepDesc := strings.TrimSpace(astStep.Keyword) + " " + fail.step.Text | ||||
| 			astScenario := f.findScenario(pickle.AstNodeIds[0]) | ||||
| 			scenarioDesc := fmt.Sprintf("%s: %s", astScenario.Keyword, pickle.Name) | ||||
| 
 | ||||
| 			astStep := f.findStep(pickleStep.AstNodeIds[0]) | ||||
| 			stepDesc := strings.TrimSpace(astStep.Keyword) + " " + pickleStep.Text | ||||
| 
 | ||||
| 			fmt.Fprintln(f.out, s(f.indent)+red(scenarioDesc)+f.line(feature.path, astScenario.Location)) | ||||
| 			fmt.Fprintln(f.out, s(f.indent*2)+red(stepDesc)+f.line(feature.path, astStep.Location)) | ||||
|  | @ -240,7 +243,8 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for _, result := range f.lastFeature().lastPickleResult().stepResults { | ||||
| 	lastPickleResult := f.lastFeature().lastPickleResult() | ||||
| 	for _, result := range lastPickleResult.stepResults { | ||||
| 		// determine example row status | ||||
| 		switch { | ||||
| 		case result.status == failed: | ||||
|  | @ -256,7 +260,8 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in | |||
| 			// in first example, we need to print steps | ||||
| 			var text string | ||||
| 
 | ||||
| 			astStep := f.findStep(result.step.AstNodeIds[0]) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(result.pickleStepID) | ||||
| 			astStep := f.findStep(pickleStep.AstNodeIds[0]) | ||||
| 
 | ||||
| 			if result.def != nil { | ||||
| 				if m := outlinePlaceholderRegexp.FindAllStringIndex(astStep.Text, -1); len(m) > 0 { | ||||
|  | @ -272,7 +277,9 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in | |||
| 					text = cyan(astStep.Text) | ||||
| 				} | ||||
| 
 | ||||
| 				_, maxLength := f.scenarioLengths(result.owner.AstNodeIds[0]) | ||||
| 				pickle := f.storage.mustGetPickle(lastPickleResult.pickleID) | ||||
| 
 | ||||
| 				_, maxLength := f.scenarioLengths(pickle.AstNodeIds[0]) | ||||
| 				stepLength := f.lengthPickleStep(astStep.Keyword, astStep.Text) | ||||
| 
 | ||||
| 				text += s(maxLength - stepLength) | ||||
|  | @ -283,7 +290,7 @@ func (f *pretty) printOutlineExample(pickle *messages.Pickle, backgroundSteps in | |||
| 			// print the step outline | ||||
| 			fmt.Fprintln(f.out, s(f.indent*2)+cyan(strings.TrimSpace(astStep.Keyword))+" "+text) | ||||
| 
 | ||||
| 			if table := result.step.Argument.GetDataTable(); table != nil { | ||||
| 			if table := pickleStep.Argument.GetDataTable(); table != nil { | ||||
| 				f.printTable(table, cyan) | ||||
| 			} | ||||
| 
 | ||||
|  | @ -326,10 +333,12 @@ func (f *pretty) printTableHeader(row *messages.GherkinDocument_Feature_TableRow | |||
| 	f.printTableRow(row, max, cyan) | ||||
| } | ||||
| 
 | ||||
| func (f *pretty) printStep(result *stepResult) { | ||||
| 	astBackground := f.findBackground(result.owner.AstNodeIds[0]) | ||||
| 	astScenario := f.findScenario(result.owner.AstNodeIds[0]) | ||||
| 	astStep := f.findStep(result.step.AstNodeIds[0]) | ||||
| func (f *pretty) printStep(pickle *messages.Pickle, result *stepResult) { | ||||
| 	pickleStep := f.storage.mustGetPickleStep(result.pickleStepID) | ||||
| 
 | ||||
| 	astBackground := f.findBackground(pickle.AstNodeIds[0]) | ||||
| 	astScenario := f.findScenario(pickle.AstNodeIds[0]) | ||||
| 	astStep := f.findStep(pickleStep.AstNodeIds[0]) | ||||
| 
 | ||||
| 	var backgroundSteps int | ||||
| 	if astBackground != nil { | ||||
|  | @ -350,26 +359,26 @@ func (f *pretty) printStep(result *stepResult) { | |||
| 	} | ||||
| 
 | ||||
| 	if !astBackgroundStep && len(astScenario.Examples) > 0 { | ||||
| 		f.printOutlineExample(result.owner, backgroundSteps) | ||||
| 		f.printOutlineExample(pickle, backgroundSteps) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	scenarioHeaderLength, maxLength := f.scenarioLengths(result.owner.AstNodeIds[0]) | ||||
| 	stepLength := f.lengthPickleStep(astStep.Keyword, result.step.Text) | ||||
| 	scenarioHeaderLength, maxLength := f.scenarioLengths(pickle.AstNodeIds[0]) | ||||
| 	stepLength := f.lengthPickleStep(astStep.Keyword, pickleStep.Text) | ||||
| 
 | ||||
| 	firstExecutedScenarioStep := len(f.lastFeature().lastPickleResult().stepResults) == backgroundSteps+1 | ||||
| 	if !astBackgroundStep && firstExecutedScenarioStep { | ||||
| 		f.printScenarioHeader(astScenario, maxLength-scenarioHeaderLength) | ||||
| 	} | ||||
| 
 | ||||
| 	text := s(f.indent*2) + result.status.clr()(strings.TrimSpace(astStep.Keyword)) + " " + result.status.clr()(result.step.Text) | ||||
| 	text := s(f.indent*2) + result.status.clr()(strings.TrimSpace(astStep.Keyword)) + " " + result.status.clr()(pickleStep.Text) | ||||
| 	if result.def != nil { | ||||
| 		text += s(maxLength - stepLength + 1) | ||||
| 		text += blackb("# " + result.def.definitionID()) | ||||
| 	} | ||||
| 	fmt.Fprintln(f.out, text) | ||||
| 
 | ||||
| 	if table := result.step.Argument.GetDataTable(); table != nil { | ||||
| 	if table := pickleStep.Argument.GetDataTable(); table != nil { | ||||
| 		f.printTable(table, cyan) | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,13 +41,16 @@ func (f *progress) Summary() { | |||
| 	var failedStepsOutput []string | ||||
| 	for _, sr := range f.findStepResults(failed) { | ||||
| 		if sr.status == failed { | ||||
| 			sc := f.findScenario(sr.owner.AstNodeIds[0]) | ||||
| 			scenarioDesc := fmt.Sprintf("%s: %s", sc.Keyword, sr.owner.Name) | ||||
| 			scenarioLine := fmt.Sprintf("%s:%d", sr.owner.Uri, sc.Location.Line) | ||||
| 			pickle := f.storage.mustGetPickle(sr.pickleID) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(sr.pickleStepID) | ||||
| 
 | ||||
| 			step := f.findStep(sr.step.AstNodeIds[0]) | ||||
| 			stepDesc := strings.TrimSpace(step.Keyword) + " " + sr.step.Text | ||||
| 			stepLine := fmt.Sprintf("%s:%d", sr.owner.Uri, step.Location.Line) | ||||
| 			sc := f.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]) | ||||
| 			stepDesc := strings.TrimSpace(step.Keyword) + " " + pickleStep.Text | ||||
| 			stepLine := fmt.Sprintf("%s:%d", pickle.Uri, step.Location.Line) | ||||
| 
 | ||||
| 			failedStepsOutput = append( | ||||
| 				failedStepsOutput, | ||||
|  |  | |||
|  | @ -40,6 +40,11 @@ func TestProgressFormatterWhenStepPanics(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", w) }) | ||||
| 	require.True(t, failed) | ||||
| 
 | ||||
|  | @ -54,6 +59,7 @@ func TestProgressFormatterWithPanicInMultistep(t *testing.T) { | |||
| 	require.NoError(t, err) | ||||
| 
 | ||||
| 	pickles := gherkin.Pickles(*gd, path, (&messages.Incrementing{}).NewId) | ||||
| 
 | ||||
| 	var buf bytes.Buffer | ||||
| 	w := colors.Uncolored(&buf) | ||||
| 	r := runner{ | ||||
|  | @ -68,6 +74,11 @@ func TestProgressFormatterWithPanicInMultistep(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", w) }) | ||||
| 	require.True(t, failed) | ||||
| } | ||||
|  | @ -93,6 +104,11 @@ func TestProgressFormatterMultistepTemplates(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", w) }) | ||||
| 	require.False(t, failed) | ||||
| 
 | ||||
|  | @ -159,6 +175,11 @@ Feature: basic | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", w) }) | ||||
| 	require.False(t, failed) | ||||
| } | ||||
|  | @ -195,6 +216,11 @@ Feature: basic | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", w) }) | ||||
| 	require.True(t, failed) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
										
									
									
									
								
							|  | @ -5,5 +5,6 @@ go 1.13 | |||
| require ( | ||||
| 	github.com/cucumber/gherkin-go/v11 v11.0.0 | ||||
| 	github.com/cucumber/messages-go/v10 v10.0.3 | ||||
| 	github.com/hashicorp/go-memdb v1.2.1 | ||||
| 	github.com/stretchr/testify v1.6.1 | ||||
| ) | ||||
|  |  | |||
							
								
								
									
										9
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								go.sum
									
										
									
									
									
								
							|  | @ -12,7 +12,16 @@ github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4 | |||
| github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | ||||
| github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= | ||||
| github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= | ||||
| github.com/hashicorp/go-immutable-radix v1.2.0 h1:l6UW37iCXwZkZoAbEYnptSHVE/cQ5bOTPYG5W3vf9+8= | ||||
| github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= | ||||
| github.com/hashicorp/go-memdb v1.2.1 h1:wI9btDjYUOJJHTCnRlAG/TkRyD/ij7meJMrLK9X31Cc= | ||||
| github.com/hashicorp/go-memdb v1.2.1/go.mod h1:OSvLJ662Jim8hMM+gWGyhktyWk2xPCnWMc7DWIqtkGA= | ||||
| github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= | ||||
| github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||
| github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= | ||||
| github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||
| github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= | ||||
| github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= | ||||
| github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= | ||||
| github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||||
| github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= | ||||
|  |  | |||
							
								
								
									
										22
									
								
								run.go
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								run.go
									
										
									
									
									
								
							|  | @ -31,6 +31,8 @@ type runner struct { | |||
| 	initializer           initializer | ||||
| 	testSuiteInitializer  testSuiteInitializer | ||||
| 	scenarioInitializer   scenarioInitializer | ||||
| 
 | ||||
| 	storage *storage | ||||
| } | ||||
| 
 | ||||
| func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool) { | ||||
|  | @ -42,10 +44,15 @@ func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool | |||
| 		useFmtCopy = true | ||||
| 	} | ||||
| 
 | ||||
| 	if fmt, ok := r.fmt.(storageFormatter); ok { | ||||
| 		fmt.setStorage(r.storage) | ||||
| 	} | ||||
| 
 | ||||
| 	testSuiteContext := TestSuiteContext{} | ||||
| 	if r.testSuiteInitializer != nil { | ||||
| 		r.testSuiteInitializer(&testSuiteContext) | ||||
| 	} | ||||
| 
 | ||||
| 	r.fmt.TestRunStarted() | ||||
| 
 | ||||
| 	// run before suite handlers | ||||
|  | @ -73,6 +80,8 @@ func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool | |||
| 				strict:        r.strict, | ||||
| 				features:      []*feature{feat}, | ||||
| 			} | ||||
| 
 | ||||
| 			suite.fmt = r.fmt | ||||
| 			if useFmtCopy { | ||||
| 				fmtCopy = formatterFn() | ||||
| 				suite.fmt = fmtCopy | ||||
|  | @ -83,8 +92,10 @@ func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool | |||
| 				if dOk && sOk { | ||||
| 					concurrentDestFmt.Sync(concurrentSourceFmt) | ||||
| 				} | ||||
| 			} else { | ||||
| 				suite.fmt = r.fmt | ||||
| 			} | ||||
| 
 | ||||
| 			if fmt, ok := suite.fmt.(storageFormatter); ok { | ||||
| 				fmt.setStorage(r.storage) | ||||
| 			} | ||||
| 
 | ||||
| 			if r.initializer != nil { | ||||
|  | @ -217,6 +228,13 @@ func runWithOptions(suite string, runner runner, opt Options) int { | |||
| 		return exitOptionError | ||||
| 	} | ||||
| 
 | ||||
| 	runner.storage = newStorage() | ||||
| 	for _, feat := range runner.features { | ||||
| 		for _, pickle := range feat.pickles { | ||||
| 			runner.storage.mustInsertPickle(pickle) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// user may have specified -1 option to create random seed | ||||
| 	runner.randomSeed = opt.Randomize | ||||
| 	if runner.randomSeed == -1 { | ||||
|  |  | |||
							
								
								
									
										15
									
								
								run_test.go
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								run_test.go
									
										
									
									
									
								
							|  | @ -75,6 +75,11 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", ioutil.Discard) }) | ||||
| 	require.False(t, failed) | ||||
| 
 | ||||
|  | @ -100,6 +105,11 @@ func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", ioutil.Discard) }) | ||||
| 	require.False(t, failed) | ||||
| 
 | ||||
|  | @ -125,6 +135,11 @@ func TestShouldFailOnError(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	r.storage = newStorage() | ||||
| 	for _, pickle := range pickles { | ||||
| 		r.storage.mustInsertPickle(pickle) | ||||
| 	} | ||||
| 
 | ||||
| 	failed := r.concurrent(1, func() Formatter { return progressFunc("progress", ioutil.Discard) }) | ||||
| 	require.True(t, failed) | ||||
| } | ||||
|  |  | |||
							
								
								
									
										104
									
								
								storage.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										104
									
								
								storage.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,104 @@ | |||
| package godog | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/cucumber/messages-go/v10" | ||||
| 	"github.com/hashicorp/go-memdb" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	writeMode bool = true | ||||
| 	readMode  bool = false | ||||
| 
 | ||||
| 	tablePickle        string = "pickle" | ||||
| 	tablePickleIndexID string = "id" | ||||
| 
 | ||||
| 	tablePickleStep        string = "pickle_step" | ||||
| 	tablePickleStepIndexID string = "id" | ||||
| ) | ||||
| 
 | ||||
| type storage struct { | ||||
| 	db *memdb.MemDB | ||||
| } | ||||
| 
 | ||||
| func newStorage() *storage { | ||||
| 	// Create the DB schema | ||||
| 	schema := memdb.DBSchema{ | ||||
| 		Tables: map[string]*memdb.TableSchema{ | ||||
| 			tablePickle: { | ||||
| 				Name: tablePickle, | ||||
| 				Indexes: map[string]*memdb.IndexSchema{ | ||||
| 					tablePickleIndexID: { | ||||
| 						Name:    tablePickleIndexID, | ||||
| 						Unique:  true, | ||||
| 						Indexer: &memdb.StringFieldIndex{Field: "Id"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			tablePickleStep: { | ||||
| 				Name: tablePickleStep, | ||||
| 				Indexes: map[string]*memdb.IndexSchema{ | ||||
| 					tablePickleStepIndexID: { | ||||
| 						Name:    tablePickleStepIndexID, | ||||
| 						Unique:  true, | ||||
| 						Indexer: &memdb.StringFieldIndex{Field: "Id"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	// Create a new data base | ||||
| 	db, err := memdb.NewMemDB(&schema) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	return &storage{db} | ||||
| } | ||||
| 
 | ||||
| func (s *storage) mustInsertPickle(p *messages.Pickle) (err error) { | ||||
| 	txn := s.db.Txn(writeMode) | ||||
| 
 | ||||
| 	if err = txn.Insert(tablePickle, p); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	for _, step := range p.Steps { | ||||
| 		if err = txn.Insert(tablePickleStep, step); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	txn.Commit() | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	} | ||||
| 
 | ||||
| 	return v.(*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) | ||||
| 	} | ||||
| 
 | ||||
| 	return v.(*messages.Pickle_PickleStep) | ||||
| } | ||||
							
								
								
									
										4
									
								
								suite.go
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								suite.go
									
										
									
									
									
								
							|  | @ -129,8 +129,8 @@ func (s sortByName) Less(i, j int) bool { return s[i].Feature.Name < s[j].Featur | |||
| func (s sortByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] } | ||||
| 
 | ||||
| type pickleResult struct { | ||||
| 	name        string | ||||
| 	astNodeIDs  []string | ||||
| 	pickleID string | ||||
| 
 | ||||
| 	time        time.Time | ||||
| 	stepResults []*stepResult | ||||
| } | ||||
|  |  | |||
|  | @ -183,7 +183,16 @@ func (s *suiteContext) iRunFeatureSuiteWithTags(tags string) error { | |||
| 		applyTagFilter(tags, feat) | ||||
| 	} | ||||
| 
 | ||||
| 	s.testedSuite.fmt = newBaseFmt("godog", &s.out) | ||||
| 	st := newStorage() | ||||
| 	for _, feat := range s.testedSuite.features { | ||||
| 		for _, pickle := range feat.pickles { | ||||
| 			st.mustInsertPickle(pickle) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	fmt := newBaseFmt("godog", &s.out) | ||||
| 	fmt.setStorage(st) | ||||
| 	s.testedSuite.fmt = fmt | ||||
| 
 | ||||
| 	s.testedSuite.fmt.TestRunStarted() | ||||
| 	s.testedSuite.run() | ||||
|  | @ -193,15 +202,25 @@ func (s *suiteContext) iRunFeatureSuiteWithTags(tags string) error { | |||
| } | ||||
| 
 | ||||
| func (s *suiteContext) iRunFeatureSuiteWithFormatter(name string) error { | ||||
| 	if err := s.parseFeatures(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	f := FindFmt(name) | ||||
| 	if f == nil { | ||||
| 		return fmt.Errorf(`formatter "%s" is not available`, name) | ||||
| 	} | ||||
| 
 | ||||
| 	s.testedSuite.fmt = f("godog", colors.Uncolored(&s.out)) | ||||
| 	st := newStorage() | ||||
| 	for _, feat := range s.testedSuite.features { | ||||
| 		for _, pickle := range feat.pickles { | ||||
| 			st.mustInsertPickle(pickle) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err := s.parseFeatures(); err != nil { | ||||
| 		return err | ||||
| 	s.testedSuite.fmt = f("godog", colors.Uncolored(&s.out)) | ||||
| 	if fmt, ok := s.testedSuite.fmt.(storageFormatter); ok { | ||||
| 		fmt.setStorage(st) | ||||
| 	} | ||||
| 
 | ||||
| 	s.testedSuite.fmt.TestRunStarted() | ||||
|  | @ -276,23 +295,28 @@ func (s *suiteContext) followingStepsShouldHave(status string, steps *DocString) | |||
| 	switch status { | ||||
| 	case "passed": | ||||
| 		for _, st := range f.findStepResults(passed) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "failed": | ||||
| 		for _, st := range f.findStepResults(failed) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "skipped": | ||||
| 		for _, st := range f.findStepResults(skipped) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "undefined": | ||||
| 		for _, st := range f.findStepResults(undefined) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "pending": | ||||
| 		for _, st := range f.findStepResults(pending) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	default: | ||||
| 		return fmt.Errorf("unexpected step status wanted: %s", status) | ||||
|  |  | |||
|  | @ -145,7 +145,16 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithTags(tags string) error { | |||
| 		applyTagFilter(tags, feat) | ||||
| 	} | ||||
| 
 | ||||
| 	tc.testedSuite.fmt = newBaseFmt("godog", &tc.out) | ||||
| 	st := newStorage() | ||||
| 	for _, feat := range tc.testedSuite.features { | ||||
| 		for _, pickle := range feat.pickles { | ||||
| 			st.mustInsertPickle(pickle) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	fmt := newBaseFmt("godog", &tc.out) | ||||
| 	fmt.setStorage(st) | ||||
| 	tc.testedSuite.fmt = fmt | ||||
| 
 | ||||
| 	tc.testedSuite.fmt.TestRunStarted() | ||||
| 	tc.testedSuite.run() | ||||
|  | @ -155,15 +164,25 @@ func (tc *godogFeaturesScenario) iRunFeatureSuiteWithTags(tags string) error { | |||
| } | ||||
| 
 | ||||
| func (tc *godogFeaturesScenario) iRunFeatureSuiteWithFormatter(name string) error { | ||||
| 	if err := tc.parseFeatures(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	f := FindFmt(name) | ||||
| 	if f == nil { | ||||
| 		return fmt.Errorf(`formatter "%s" is not available`, name) | ||||
| 	} | ||||
| 
 | ||||
| 	tc.testedSuite.fmt = f("godog", colors.Uncolored(&tc.out)) | ||||
| 	st := newStorage() | ||||
| 	for _, feat := range tc.testedSuite.features { | ||||
| 		for _, pickle := range feat.pickles { | ||||
| 			st.mustInsertPickle(pickle) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err := tc.parseFeatures(); err != nil { | ||||
| 		return err | ||||
| 	tc.testedSuite.fmt = f("godog", colors.Uncolored(&tc.out)) | ||||
| 	if fmt, ok := tc.testedSuite.fmt.(storageFormatter); ok { | ||||
| 		fmt.setStorage(st) | ||||
| 	} | ||||
| 
 | ||||
| 	tc.testedSuite.fmt.TestRunStarted() | ||||
|  | @ -238,23 +257,28 @@ func (tc *godogFeaturesScenario) followingStepsShouldHave(status string, steps * | |||
| 	switch status { | ||||
| 	case "passed": | ||||
| 		for _, st := range f.findStepResults(passed) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "failed": | ||||
| 		for _, st := range f.findStepResults(failed) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "skipped": | ||||
| 		for _, st := range f.findStepResults(skipped) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "undefined": | ||||
| 		for _, st := range f.findStepResults(undefined) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	case "pending": | ||||
| 		for _, st := range f.findStepResults(pending) { | ||||
| 			actual = append(actual, st.step.Text) | ||||
| 			pickleStep := f.storage.mustGetPickleStep(st.pickleStepID) | ||||
| 			actual = append(actual, pickleStep.Text) | ||||
| 		} | ||||
| 	default: | ||||
| 		return fmt.Errorf("unexpected step status wanted: %s", status) | ||||
|  |  | |||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Fredrik Lönnblad
						Fredrik Lönnblad