update step print matches
Этот коммит содержится в:
родитель
b69fa26b8b
коммит
156613f767
5 изменённых файлов: 71 добавлений и 77 удалений
51
formatter.go
51
formatter.go
|
@ -2,6 +2,7 @@ package godog
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/DATA-DOG/godog/gherkin"
|
||||
|
@ -14,8 +15,8 @@ func init() {
|
|||
// Formatter is an interface for feature runner output
|
||||
type Formatter interface {
|
||||
Node(interface{})
|
||||
Failed(*gherkin.Step, error)
|
||||
Passed(*gherkin.Step)
|
||||
Failed(*gherkin.Step, *stepMatchHandler, error)
|
||||
Passed(*gherkin.Step, *stepMatchHandler)
|
||||
Skipped(*gherkin.Step)
|
||||
Pending(*gherkin.Step)
|
||||
}
|
||||
|
@ -65,14 +66,48 @@ func (f *pretty) Node(node interface{}) {
|
|||
f.background = t
|
||||
fmt.Println("\n" + bcl("Background:", white))
|
||||
case *gherkin.Scenario:
|
||||
f.scenario = t
|
||||
fmt.Println("\n"+strings.Repeat(" ", t.Token.Indent)+bcl("Scenario: ", white)+t.Title, f.line(t.Token))
|
||||
}
|
||||
}
|
||||
|
||||
func (f *pretty) Passed(step *gherkin.Step) {
|
||||
if f.canPrintStep(step) {
|
||||
fmt.Println(cl(step.Token.Text, green))
|
||||
func (f *pretty) printMatchedStep(step *gherkin.Step, match *stepMatchHandler, c color) {
|
||||
if !f.canPrintStep(step) {
|
||||
return
|
||||
}
|
||||
var text string
|
||||
if m := (match.expr.FindStringSubmatchIndex(step.Text))[2:]; len(m) > 0 {
|
||||
var pos, i int
|
||||
for pos, i = 0, 0; i < len(m); i++ {
|
||||
if math.Mod(float64(i), 2) == 0 {
|
||||
text += cl(step.Text[pos:m[i]], c)
|
||||
} else {
|
||||
text += bcl(step.Text[pos:m[i]], c)
|
||||
}
|
||||
pos = m[i]
|
||||
}
|
||||
text += cl(step.Text[pos:len(step.Text)], c)
|
||||
} else {
|
||||
text = cl(step.Text, c)
|
||||
}
|
||||
|
||||
switch step.Token.Type {
|
||||
case gherkin.GIVEN:
|
||||
text = cl("Given", c) + " " + text
|
||||
case gherkin.WHEN:
|
||||
text = cl("When", c) + " " + text
|
||||
case gherkin.THEN:
|
||||
text = cl("Then", c) + " " + text
|
||||
case gherkin.AND:
|
||||
text = cl("And", c) + " " + text
|
||||
case gherkin.BUT:
|
||||
text = cl("But", c) + " " + text
|
||||
}
|
||||
fmt.Println(strings.Repeat(" ", step.Token.Indent) + text)
|
||||
}
|
||||
|
||||
func (f *pretty) Passed(step *gherkin.Step, match *stepMatchHandler) {
|
||||
f.printMatchedStep(step, match, green)
|
||||
}
|
||||
|
||||
func (f *pretty) Skipped(step *gherkin.Step) {
|
||||
|
@ -87,8 +122,6 @@ func (f *pretty) Pending(step *gherkin.Step) {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *pretty) Failed(step *gherkin.Step, err error) {
|
||||
if f.canPrintStep(step) {
|
||||
fmt.Println(cl(step.Token.Text, red))
|
||||
}
|
||||
func (f *pretty) Failed(step *gherkin.Step, match *stepMatchHandler, err error) {
|
||||
f.printMatchedStep(step, match, red)
|
||||
}
|
||||
|
|
|
@ -111,20 +111,11 @@ type Background struct {
|
|||
Steps []*Step
|
||||
}
|
||||
|
||||
// StepType is a general type of step
|
||||
type StepType string
|
||||
|
||||
const (
|
||||
Given StepType = "Given"
|
||||
When StepType = "When"
|
||||
Then StepType = "Then"
|
||||
)
|
||||
|
||||
// Step describes a Scenario or Background step
|
||||
type Step struct {
|
||||
*Token
|
||||
Text string
|
||||
Type StepType
|
||||
Type string
|
||||
PyString *PyString
|
||||
Table *Table
|
||||
}
|
||||
|
@ -309,20 +300,6 @@ func (p *parser) parseScenario() (s *Scenario, err error) {
|
|||
func (p *parser) parseSteps() (steps []*Step, err error) {
|
||||
for tok := p.peek(); tok.OfType(allSteps...); tok = p.peek() {
|
||||
step := &Step{Text: tok.Value, Token: tok}
|
||||
switch tok.Type {
|
||||
case GIVEN:
|
||||
step.Type = Given
|
||||
case WHEN:
|
||||
step.Type = When
|
||||
case THEN:
|
||||
step.Type = Then
|
||||
case AND, BUT:
|
||||
if len(steps) > 0 {
|
||||
step.Type = steps[len(steps)-1].Type
|
||||
} else {
|
||||
step.Type = Given
|
||||
}
|
||||
}
|
||||
|
||||
p.next() // have read a peeked step
|
||||
if step.Text[len(step.Text)-1] == ':' {
|
||||
|
|
|
@ -44,12 +44,6 @@ var testStepSamples = map[string]string{
|
|||
Then I expect the result`,
|
||||
}
|
||||
|
||||
func (s *Step) assertType(typ StepType, t *testing.T) {
|
||||
if s.Type != typ {
|
||||
t.Fatalf("expected step '%s' type to be '%s', but got '%s'", s.Text, typ, s.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Step) assertText(text string, t *testing.T) {
|
||||
if s.Text != text {
|
||||
t.Fatalf("expected step text to be '%s', but got '%s'", text, s.Text)
|
||||
|
@ -102,7 +96,6 @@ func Test_parse_basic_given_step(t *testing.T) {
|
|||
t.Fatalf("expected one step to be parsed")
|
||||
}
|
||||
|
||||
steps[0].assertType(Given, t)
|
||||
steps[0].assertText("I'm a step", t)
|
||||
|
||||
p.next() // step over to eof
|
||||
|
@ -126,7 +119,6 @@ func Test_parse_step_with_comment(t *testing.T) {
|
|||
t.Fatalf("expected one step to be parsed")
|
||||
}
|
||||
|
||||
steps[0].assertType(Given, t)
|
||||
steps[0].assertText("I'm an admin", t)
|
||||
steps[0].assertComment("sets admin permissions", t)
|
||||
|
||||
|
@ -151,7 +143,6 @@ func Test_parse_hash_table_given_step(t *testing.T) {
|
|||
t.Fatalf("expected one step to be parsed")
|
||||
}
|
||||
|
||||
steps[0].assertType(Given, t)
|
||||
steps[0].assertText("there are users:", t)
|
||||
steps[0].assertTableRow(t, 0, "name", "John Doe")
|
||||
|
||||
|
@ -177,7 +168,6 @@ func Test_parse_table_given_step(t *testing.T) {
|
|||
t.Fatalf("expected one step to be parsed")
|
||||
}
|
||||
|
||||
steps[0].assertType(Given, t)
|
||||
steps[0].assertText("there are users:", t)
|
||||
steps[0].assertTableRow(t, 0, "name", "lastname")
|
||||
steps[0].assertTableRow(t, 1, "John", "Doe")
|
||||
|
@ -207,7 +197,6 @@ func Test_parse_pystring_step(t *testing.T) {
|
|||
t.Fatalf("expected one step to be parsed")
|
||||
}
|
||||
|
||||
steps[0].assertType(Then, t)
|
||||
steps[0].assertText("there should be text:", t)
|
||||
steps[0].assertPyString(strings.Join([]string{
|
||||
indent(4, "Some text"),
|
||||
|
@ -239,7 +228,6 @@ func Test_parse_empty_pystring_step(t *testing.T) {
|
|||
t.Fatalf("expected one step to be parsed")
|
||||
}
|
||||
|
||||
steps[0].assertType(When, t)
|
||||
steps[0].assertText("I do request with body:", t)
|
||||
steps[0].assertPyString("", t)
|
||||
|
||||
|
@ -285,13 +273,9 @@ func Test_parse_step_group(t *testing.T) {
|
|||
t.Fatalf("expected four steps to be parsed, but got: %d", len(steps))
|
||||
}
|
||||
|
||||
steps[0].assertType(Given, t)
|
||||
steps[0].assertText("there are conditions", t)
|
||||
steps[1].assertType(Given, t)
|
||||
steps[1].assertText("there are more conditions", t)
|
||||
steps[2].assertType(When, t)
|
||||
steps[2].assertText("I do something", t)
|
||||
steps[3].assertType(Then, t)
|
||||
steps[3].assertText("something should happen", t)
|
||||
|
||||
p.next() // step over to eof
|
||||
|
@ -318,13 +302,9 @@ func Test_parse_another_step_group(t *testing.T) {
|
|||
t.Fatalf("expected four steps to be parsed, but got: %d", len(steps))
|
||||
}
|
||||
|
||||
steps[0].assertType(Given, t)
|
||||
steps[0].assertText(`an admin user "John Doe"`, t)
|
||||
steps[1].assertType(Given, t)
|
||||
steps[1].assertText(`user "John Doe" belongs to user group "editors"`, t)
|
||||
steps[2].assertType(When, t)
|
||||
steps[2].assertText("I do something", t)
|
||||
steps[3].assertType(Then, t)
|
||||
steps[3].assertText("I expect the result", t)
|
||||
|
||||
p.next() // step over to eof
|
||||
|
|
48
suite.go
48
suite.go
|
@ -66,6 +66,11 @@ func (f StepHandlerFunc) HandleStep(args ...Arg) error {
|
|||
|
||||
var errPending = fmt.Errorf("pending step")
|
||||
|
||||
type stepMatchHandler struct {
|
||||
handler StepHandler
|
||||
expr *regexp.Regexp
|
||||
}
|
||||
|
||||
// Suite is an interface which allows various contexts
|
||||
// to register step definitions and event handlers
|
||||
type Suite interface {
|
||||
|
@ -73,7 +78,7 @@ type Suite interface {
|
|||
}
|
||||
|
||||
type suite struct {
|
||||
steps map[*regexp.Regexp]StepHandler
|
||||
steps []*stepMatchHandler
|
||||
features []*gherkin.Feature
|
||||
fmt Formatter
|
||||
}
|
||||
|
@ -82,9 +87,7 @@ type suite struct {
|
|||
// interface. The instance is passed around to all
|
||||
// context initialization functions from *_test.go files
|
||||
func New() *suite {
|
||||
return &suite{
|
||||
steps: make(map[*regexp.Regexp]StepHandler),
|
||||
}
|
||||
return &suite{}
|
||||
}
|
||||
|
||||
// Step allows to register a StepHandler in Godog
|
||||
|
@ -97,8 +100,11 @@ func New() *suite {
|
|||
//
|
||||
// If none of the StepHandlers are matched, then a pending
|
||||
// step error will be raised.
|
||||
func (s *suite) Step(exp *regexp.Regexp, h StepHandler) {
|
||||
s.steps[exp] = h
|
||||
func (s *suite) Step(expr *regexp.Regexp, h StepHandler) {
|
||||
s.steps = append(s.steps, &stepMatchHandler{
|
||||
handler: h,
|
||||
expr: expr,
|
||||
})
|
||||
}
|
||||
|
||||
// Run - runs a godog feature suite
|
||||
|
@ -122,33 +128,33 @@ func (s *suite) Run() {
|
|||
}
|
||||
|
||||
func (s *suite) runStep(step *gherkin.Step) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = e.(error)
|
||||
s.fmt.Failed(step, err)
|
||||
}
|
||||
}()
|
||||
|
||||
var handler StepHandler
|
||||
var match *stepMatchHandler
|
||||
var args []Arg
|
||||
for r, h := range s.steps {
|
||||
if m := r.FindStringSubmatch(step.Text); len(m) > 0 {
|
||||
handler = h
|
||||
for _, h := range s.steps {
|
||||
if m := h.expr.FindStringSubmatch(step.Text); len(m) > 0 {
|
||||
match = h
|
||||
for _, a := range m[1:] {
|
||||
args = append(args, Arg(a))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if handler == nil {
|
||||
if match == nil {
|
||||
s.fmt.Pending(step)
|
||||
return errPending
|
||||
}
|
||||
|
||||
if err = handler.HandleStep(args...); err != nil {
|
||||
s.fmt.Failed(step, err)
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = e.(error)
|
||||
s.fmt.Failed(step, match, err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err = match.handler.HandleStep(args...); err != nil {
|
||||
s.fmt.Failed(step, match, err)
|
||||
} else {
|
||||
s.fmt.Passed(step)
|
||||
s.fmt.Passed(step, match)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ func (s *suiteFeature) numParsed(args ...Arg) (err error) {
|
|||
|
||||
func SuiteContext(g Suite) {
|
||||
s := &suiteFeature{
|
||||
suite: suite{
|
||||
steps: make(map[*regexp.Regexp]StepHandler),
|
||||
},
|
||||
suite: suite{},
|
||||
}
|
||||
|
||||
g.Step(
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче