github.com/data-DOG/godog@v0.7.9/fmt_progress_test.go (about)

     1  package godog
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/DATA-DOG/godog/colors"
    11  	"github.com/DATA-DOG/godog/gherkin"
    12  )
    13  
    14  func TestProgressFormatterOutput(t *testing.T) {
    15  	feat, err := gherkin.ParseFeature(strings.NewReader(sampleGherkinFeature))
    16  	if err != nil {
    17  		t.Fatalf("unexpected error: %v", err)
    18  	}
    19  
    20  	var buf bytes.Buffer
    21  	w := colors.Uncolored(&buf)
    22  	r := runner{
    23  		fmt: progressFunc("progress", w),
    24  		features: []*feature{&feature{
    25  			Path:    "any.feature",
    26  			Feature: feat,
    27  			Content: []byte(sampleGherkinFeature),
    28  		}},
    29  		initializer: func(s *Suite) {
    30  			s.Step(`^passing$`, func() error { return nil })
    31  			s.Step(`^failing$`, func() error { return fmt.Errorf("errored") })
    32  			s.Step(`^pending$`, func() error { return ErrPending })
    33  		},
    34  	}
    35  
    36  	expected := `
    37  ...F-.P-.UU.....F..P..U 23
    38  
    39  
    40  --- Failed steps:
    41  
    42    Scenario: failing scenario # any.feature:10
    43      When failing # any.feature:11
    44  	  Error: errored
    45  
    46    Scenario Outline: outline # any.feature:22
    47  	When failing # any.feature:24
    48  	  Error: errored
    49  
    50  
    51  8 scenarios (2 passed, 2 failed, 2 pending, 2 undefined)
    52  23 steps (14 passed, 2 failed, 2 pending, 3 undefined, 2 skipped)
    53  0s
    54  
    55  You can implement step definitions for undefined steps with these snippets:
    56  
    57  func undefined() error {
    58  	return godog.ErrPending
    59  }
    60  
    61  func nextUndefined() error {
    62  	return godog.ErrPending
    63  }
    64  
    65  func FeatureContext(s *godog.Suite) {
    66  	s.Step(` + "`^undefined$`" + `, undefined)
    67  	s.Step(` + "`^next undefined$`" + `, nextUndefined)
    68  }`
    69  
    70  	expected = trimAllLines(expected)
    71  
    72  	r.run()
    73  
    74  	actual := trimAllLines(buf.String())
    75  
    76  	shouldMatchOutput(expected, actual, t)
    77  }
    78  
    79  func trimAllLines(s string) string {
    80  	var lines []string
    81  	for _, ln := range strings.Split(strings.TrimSpace(s), "\n") {
    82  		lines = append(lines, strings.TrimSpace(ln))
    83  	}
    84  	return strings.Join(lines, "\n")
    85  }
    86  
    87  var basicGherkinFeature = `
    88  Feature: basic
    89  
    90    Scenario: passing scenario
    91  	When one
    92  	Then two
    93  `
    94  
    95  func TestProgressFormatterWhenStepPanics(t *testing.T) {
    96  	feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
    97  	if err != nil {
    98  		t.Fatalf("unexpected error: %v", err)
    99  	}
   100  
   101  	var buf bytes.Buffer
   102  	w := colors.Uncolored(&buf)
   103  	r := runner{
   104  		fmt:      progressFunc("progress", w),
   105  		features: []*feature{&feature{Feature: feat}},
   106  		initializer: func(s *Suite) {
   107  			s.Step(`^one$`, func() error { return nil })
   108  			s.Step(`^two$`, func() error { panic("omg") })
   109  		},
   110  	}
   111  
   112  	if !r.run() {
   113  		t.Fatal("the suite should have failed")
   114  	}
   115  
   116  	out := buf.String()
   117  	if idx := strings.Index(out, "github.com/DATA-DOG/godog/fmt_progress_test.go:108"); idx == -1 {
   118  		t.Fatalf("expected to find panic stacktrace, actual:\n%s", out)
   119  	}
   120  }
   121  
   122  func TestProgressFormatterWithPassingMultisteps(t *testing.T) {
   123  	feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
   124  	if err != nil {
   125  		t.Fatalf("unexpected error: %v", err)
   126  	}
   127  
   128  	var buf bytes.Buffer
   129  	w := colors.Uncolored(&buf)
   130  	r := runner{
   131  		fmt:      progressFunc("progress", w),
   132  		features: []*feature{&feature{Feature: feat}},
   133  		initializer: func(s *Suite) {
   134  			s.Step(`^sub1$`, func() error { return nil })
   135  			s.Step(`^sub-sub$`, func() error { return nil })
   136  			s.Step(`^sub2$`, func() Steps { return Steps{"sub-sub", "sub1", "one"} })
   137  			s.Step(`^one$`, func() error { return nil })
   138  			s.Step(`^two$`, func() Steps { return Steps{"sub1", "sub2"} })
   139  		},
   140  	}
   141  
   142  	if r.run() {
   143  		t.Fatal("the suite should have passed")
   144  	}
   145  }
   146  
   147  func TestProgressFormatterWithFailingMultisteps(t *testing.T) {
   148  	feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
   149  	if err != nil {
   150  		t.Fatalf("unexpected error: %v", err)
   151  	}
   152  
   153  	var buf bytes.Buffer
   154  	w := colors.Uncolored(&buf)
   155  	r := runner{
   156  		fmt:      progressFunc("progress", w),
   157  		features: []*feature{&feature{Feature: feat, Path: "some.feature"}},
   158  		initializer: func(s *Suite) {
   159  			s.Step(`^sub1$`, func() error { return nil })
   160  			s.Step(`^sub-sub$`, func() error { return fmt.Errorf("errored") })
   161  			s.Step(`^sub2$`, func() Steps { return Steps{"sub-sub", "sub1", "one"} })
   162  			s.Step(`^one$`, func() error { return nil })
   163  			s.Step(`^two$`, func() Steps { return Steps{"sub1", "sub2"} })
   164  		},
   165  	}
   166  
   167  	if !r.run() {
   168  		t.Fatal("the suite should have failed")
   169  	}
   170  
   171  	expected := `
   172  .F 2
   173  
   174  
   175  --- Failed steps:
   176  
   177  Scenario: passing scenario # some.feature:4
   178  Then two # some.feature:6
   179  Error: sub2: sub-sub: errored
   180  
   181  
   182  1 scenarios (1 failed)
   183  2 steps (1 passed, 1 failed)
   184  0s
   185  `
   186  
   187  	expected = trimAllLines(expected)
   188  	actual := trimAllLines(buf.String())
   189  
   190  	shouldMatchOutput(expected, actual, t)
   191  }
   192  
   193  func shouldMatchOutput(expected, actual string, t *testing.T) {
   194  	act := []byte(actual)
   195  	exp := []byte(expected)
   196  
   197  	if len(act) != len(exp) {
   198  		t.Fatalf("content lengths do not match, expected: %d, actual %d, actual output:\n%s", len(exp), len(act), actual)
   199  	}
   200  
   201  	for i := 0; i < len(exp); i++ {
   202  		if act[i] == exp[i] {
   203  			continue
   204  		}
   205  
   206  		cpe := make([]byte, len(exp))
   207  		copy(cpe, exp)
   208  		e := append(exp[:i], '^')
   209  		e = append(e, cpe[i:]...)
   210  
   211  		cpa := make([]byte, len(act))
   212  		copy(cpa, act)
   213  		a := append(act[:i], '^')
   214  		a = append(a, cpa[i:]...)
   215  
   216  		t.Fatalf("expected output does not match:\n%s\n\n%s", string(a), string(e))
   217  	}
   218  }
   219  
   220  func TestProgressFormatterWithPanicInMultistep(t *testing.T) {
   221  	feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
   222  	if err != nil {
   223  		t.Fatalf("unexpected error: %v", err)
   224  	}
   225  
   226  	var buf bytes.Buffer
   227  	w := colors.Uncolored(&buf)
   228  	r := runner{
   229  		fmt:      progressFunc("progress", w),
   230  		features: []*feature{&feature{Feature: feat}},
   231  		initializer: func(s *Suite) {
   232  			s.Step(`^sub1$`, func() error { return nil })
   233  			s.Step(`^sub-sub$`, func() error { return nil })
   234  			s.Step(`^sub2$`, func() []string { return []string{"sub-sub", "sub1", "one"} })
   235  			s.Step(`^one$`, func() error { return nil })
   236  			s.Step(`^two$`, func() []string { return []string{"sub1", "sub2"} })
   237  		},
   238  	}
   239  
   240  	if !r.run() {
   241  		t.Fatal("the suite should have failed")
   242  	}
   243  }
   244  
   245  func TestProgressFormatterMultistepTemplates(t *testing.T) {
   246  	feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature))
   247  	if err != nil {
   248  		t.Fatalf("unexpected error: %v", err)
   249  	}
   250  
   251  	var buf bytes.Buffer
   252  	w := colors.Uncolored(&buf)
   253  	r := runner{
   254  		fmt:      progressFunc("progress", w),
   255  		features: []*feature{&feature{Feature: feat}},
   256  		initializer: func(s *Suite) {
   257  			s.Step(`^sub-sub$`, func() error { return nil })
   258  			s.Step(`^substep$`, func() Steps { return Steps{"sub-sub", `unavailable "John" cost 5`, "one", "three"} })
   259  			s.Step(`^one$`, func() error { return nil })
   260  			s.Step(`^(t)wo$`, func(s string) Steps { return Steps{"undef", "substep"} })
   261  		},
   262  	}
   263  
   264  	if r.run() {
   265  		t.Fatal("the suite should have passed")
   266  	}
   267  
   268  	expected := `
   269  .U 2
   270  
   271  
   272  1 scenarios (1 undefined)
   273  2 steps (1 passed, 1 undefined)
   274  0s
   275  
   276  You can implement step definitions for undefined steps with these snippets:
   277  
   278  func undef() error {
   279  	return godog.ErrPending
   280  }
   281  
   282  func unavailableCost(arg1 string, arg2 int) error {
   283  	return godog.ErrPending
   284  }
   285  
   286  func three() error {
   287  	return godog.ErrPending
   288  }
   289  
   290  func FeatureContext(s *godog.Suite) {
   291  	s.Step(` + "`^undef$`" + `, undef)
   292  	s.Step(` + "`^unavailable \"([^\"]*)\" cost (\\d+)$`" + `, unavailableCost)
   293  	s.Step(` + "`^three$`" + `, three)
   294  }
   295  `
   296  
   297  	expected = trimAllLines(expected)
   298  
   299  	actual := trimAllLines(buf.String())
   300  	if actual != expected {
   301  		t.Fatalf("expected output does not match: %s", actual)
   302  	}
   303  }
   304  
   305  func TestProgressFormatterWhenMultiStepHasArgument(t *testing.T) {
   306  
   307  	var featureSource = `
   308  Feature: basic
   309  
   310    Scenario: passing scenario
   311  	When one
   312  	Then two:
   313  	"""
   314  	text
   315  	"""
   316  `
   317  	feat, err := gherkin.ParseFeature(strings.NewReader(featureSource))
   318  	if err != nil {
   319  		t.Fatalf("unexpected error: %v", err)
   320  	}
   321  
   322  	r := runner{
   323  		fmt:      progressFunc("progress", ioutil.Discard),
   324  		features: []*feature{&feature{Feature: feat}},
   325  		initializer: func(s *Suite) {
   326  			s.Step(`^one$`, func() error { return nil })
   327  			s.Step(`^two:$`, func(doc *gherkin.DocString) Steps { return Steps{"one"} })
   328  		},
   329  	}
   330  
   331  	if r.run() {
   332  		t.Fatal("the suite should have passed")
   333  	}
   334  }
   335  
   336  func TestProgressFormatterWhenMultiStepHasStepWithArgument(t *testing.T) {
   337  
   338  	var featureSource = `
   339  Feature: basic
   340  
   341    Scenario: passing scenario
   342  	When one
   343  	Then two`
   344  
   345  	feat, err := gherkin.ParseFeature(strings.NewReader(featureSource))
   346  	if err != nil {
   347  		t.Fatalf("unexpected error: %v", err)
   348  	}
   349  
   350  	var subStep = `three:
   351  	"""
   352  	content
   353  	"""`
   354  
   355  	var buf bytes.Buffer
   356  	w := colors.Uncolored(&buf)
   357  	r := runner{
   358  		fmt:      progressFunc("progress", w),
   359  		features: []*feature{&feature{Feature: feat}},
   360  		initializer: func(s *Suite) {
   361  			s.Step(`^one$`, func() error { return nil })
   362  			s.Step(`^two$`, func() Steps { return Steps{subStep} })
   363  			s.Step(`^three:$`, func(doc *gherkin.DocString) error { return nil })
   364  		},
   365  	}
   366  
   367  	if !r.run() {
   368  		t.Fatal("the suite should have failed")
   369  	}
   370  
   371  	expected := `
   372  .F 2
   373  
   374  
   375  --- Failed steps:
   376  
   377    Scenario: passing scenario # :4
   378      Then two # :6
   379        Error: nested steps cannot be multiline and have table or content body argument
   380  
   381  
   382  1 scenarios (1 failed)
   383  2 steps (1 passed, 1 failed)
   384  0s
   385  `
   386  
   387  	expected = trimAllLines(expected)
   388  	actual := trimAllLines(buf.String())
   389  	if actual != expected {
   390  		t.Fatalf("expected output does not match: %s", actual)
   391  	}
   392  }