github.com/maps90/godog@v0.7.5-0.20170923143419-0093943021d4/run_test.go (about) 1 package godog 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "strings" 10 "testing" 11 12 "github.com/DATA-DOG/godog/colors" 13 "github.com/DATA-DOG/godog/gherkin" 14 ) 15 16 func okStep() error { 17 return nil 18 } 19 20 func TestPrintsStepDefinitions(t *testing.T) { 21 var buf bytes.Buffer 22 w := colors.Uncolored(&buf) 23 s := &Suite{} 24 25 steps := []string{ 26 "^passing step$", 27 `^with name "([^"])"`, 28 } 29 30 for _, step := range steps { 31 s.Step(step, okStep) 32 } 33 s.printStepDefinitions(w) 34 35 out := buf.String() 36 ref := `okStep` 37 for i, def := range strings.Split(strings.TrimSpace(out), "\n") { 38 if idx := strings.Index(def, steps[i]); idx == -1 { 39 t.Fatalf(`step "%s" was not found in output`, steps[i]) 40 } 41 if idx := strings.Index(def, ref); idx == -1 { 42 t.Fatalf(`step definition reference "%s" was not found in output: "%s"`, ref, def) 43 } 44 } 45 } 46 47 func TestPrintsNoStepDefinitionsIfNoneFound(t *testing.T) { 48 var buf bytes.Buffer 49 w := colors.Uncolored(&buf) 50 s := &Suite{} 51 s.printStepDefinitions(w) 52 53 out := strings.TrimSpace(buf.String()) 54 if out != "there were no contexts registered, could not find any step definition.." { 55 t.Fatalf("expected output does not match to: %s", out) 56 } 57 } 58 59 func TestFailsOrPassesBasedOnStrictModeWhenHasPendingSteps(t *testing.T) { 60 feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature)) 61 if err != nil { 62 t.Fatalf("unexpected error: %v", err) 63 } 64 65 r := runner{ 66 fmt: progressFunc("progress", ioutil.Discard), 67 features: []*feature{&feature{Feature: feat}}, 68 initializer: func(s *Suite) { 69 s.Step(`^one$`, func() error { return nil }) 70 s.Step(`^two$`, func() error { return ErrPending }) 71 }, 72 } 73 74 if r.run() { 75 t.Fatal("the suite should have passed") 76 } 77 78 r.strict = true 79 if !r.run() { 80 t.Fatal("the suite should have failed") 81 } 82 } 83 84 func TestFailsOrPassesBasedOnStrictModeWhenHasUndefinedSteps(t *testing.T) { 85 feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature)) 86 if err != nil { 87 t.Fatalf("unexpected error: %v", err) 88 } 89 90 r := runner{ 91 fmt: progressFunc("progress", ioutil.Discard), 92 features: []*feature{&feature{Feature: feat}}, 93 initializer: func(s *Suite) { 94 s.Step(`^one$`, func() error { return nil }) 95 // two - is undefined 96 }, 97 } 98 99 if r.run() { 100 t.Fatal("the suite should have passed") 101 } 102 103 r.strict = true 104 if !r.run() { 105 t.Fatal("the suite should have failed") 106 } 107 } 108 109 func TestShouldFailOnError(t *testing.T) { 110 feat, err := gherkin.ParseFeature(strings.NewReader(basicGherkinFeature)) 111 if err != nil { 112 t.Fatalf("unexpected error: %v", err) 113 } 114 115 r := runner{ 116 fmt: progressFunc("progress", ioutil.Discard), 117 features: []*feature{&feature{Feature: feat}}, 118 initializer: func(s *Suite) { 119 s.Step(`^one$`, func() error { return nil }) 120 s.Step(`^two$`, func() error { return fmt.Errorf("error") }) 121 }, 122 } 123 124 if !r.run() { 125 t.Fatal("the suite should have failed") 126 } 127 } 128 129 func TestFailsWithConcurrencyOptionError(t *testing.T) { 130 stderr, closer := bufErrorPipe(t) 131 defer closer() 132 defer stderr.Close() 133 134 opt := Options{ 135 Format: "pretty", 136 Paths: []string{"features/load:6"}, 137 Concurrency: 2, 138 Output: ioutil.Discard, 139 } 140 141 status := RunWithOptions("fails", func(_ *Suite) {}, opt) 142 if status != exitOptionError { 143 t.Fatalf("expected exit status to be 2, but was: %d", status) 144 } 145 closer() 146 147 b, err := ioutil.ReadAll(stderr) 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 out := strings.TrimSpace(string(b)) 153 if out != `format "pretty" does not support concurrent execution` { 154 t.Fatalf("unexpected error output: \"%s\"", out) 155 } 156 } 157 158 func TestFailsWithUnknownFormatterOptionError(t *testing.T) { 159 stderr, closer := bufErrorPipe(t) 160 defer closer() 161 defer stderr.Close() 162 163 opt := Options{ 164 Format: "unknown", 165 Paths: []string{"features/load:6"}, 166 Output: ioutil.Discard, 167 } 168 169 status := RunWithOptions("fails", func(_ *Suite) {}, opt) 170 if status != exitOptionError { 171 t.Fatalf("expected exit status to be 2, but was: %d", status) 172 } 173 closer() 174 175 b, err := ioutil.ReadAll(stderr) 176 if err != nil { 177 t.Fatal(err) 178 } 179 180 out := strings.TrimSpace(string(b)) 181 if strings.Index(out, `unregistered formatter name: "unknown", use one of`) == -1 { 182 t.Fatalf("unexpected error output: \"%s\"", out) 183 } 184 } 185 186 func TestFailsWithOptionErrorWhenLookingForFeaturesInUnavailablePath(t *testing.T) { 187 stderr, closer := bufErrorPipe(t) 188 defer closer() 189 defer stderr.Close() 190 191 opt := Options{ 192 Format: "progress", 193 Paths: []string{"unavailable"}, 194 Output: ioutil.Discard, 195 } 196 197 status := RunWithOptions("fails", func(_ *Suite) {}, opt) 198 if status != exitOptionError { 199 t.Fatalf("expected exit status to be 2, but was: %d", status) 200 } 201 closer() 202 203 b, err := ioutil.ReadAll(stderr) 204 if err != nil { 205 t.Fatal(err) 206 } 207 208 out := strings.TrimSpace(string(b)) 209 if out != `feature path "unavailable" is not available` { 210 t.Fatalf("unexpected error output: \"%s\"", out) 211 } 212 } 213 214 func TestByDefaultRunsFeaturesPath(t *testing.T) { 215 opt := Options{ 216 Format: "progress", 217 Output: ioutil.Discard, 218 Strict: true, 219 } 220 221 status := RunWithOptions("fails", func(_ *Suite) {}, opt) 222 // should fail in strict mode due to undefined steps 223 if status != exitFailure { 224 t.Fatalf("expected exit status to be 1, but was: %d", status) 225 } 226 227 opt.Strict = false 228 status = RunWithOptions("succeeds", func(_ *Suite) {}, opt) 229 // should succeed in non strict mode due to undefined steps 230 if status != exitSuccess { 231 t.Fatalf("expected exit status to be 0, but was: %d", status) 232 } 233 } 234 235 func bufErrorPipe(t *testing.T) (io.ReadCloser, func()) { 236 stderr := os.Stderr 237 r, w, err := os.Pipe() 238 if err != nil { 239 t.Fatal(err) 240 } 241 242 os.Stderr = w 243 return r, func() { 244 w.Close() 245 os.Stderr = stderr 246 } 247 }