Этот коммит содержится в:
gedi 2015-06-15 14:42:40 +03:00
родитель b69fa26b8b
коммит 156613f767
5 изменённых файлов: 71 добавлений и 77 удалений

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

@ -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

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

@ -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(