github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/internal_integration/table_test.go (about) 1 package internal_integration_test 2 3 import ( 4 "fmt" 5 "strings" 6 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/gomega" 9 10 . "github.com/onsi/ginkgo/internal/test_helpers" 11 "github.com/onsi/ginkgo/types" 12 ) 13 14 var _ = Describe("Table driven tests", func() { 15 var bodyFunc = func(a, b int) { 16 rt.Run(CurrentSpecReport().LeafNodeText) 17 if a != b { 18 F("fail") 19 } 20 } 21 22 Describe("constructing tables", func() { 23 BeforeEach(func() { 24 entrySlice := []TableEntry{ 25 Entry("C", 1, 2), Entry("D", 1, 1), 26 } 27 success, _ := RunFixture("table happy-path", func() { 28 DescribeTable("hello", bodyFunc, Entry("A", 1, 1), Entry("B", 1, 1), entrySlice) 29 }) 30 Ω(success).Should(BeFalse()) 31 }) 32 33 It("runs all the entries", func() { 34 Ω(rt).Should(HaveTracked("A", "B", "C", "D")) 35 }) 36 37 It("reports on the tests correctly", func() { 38 Ω(reporter.Did.Names()).Should(Equal([]string{"A", "B", "C", "D"})) 39 Ω(reporter.Did.Find("C")).Should(HaveFailed("fail", types.NodeTypeIt)) 40 Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(4), NPassed(3), NFailed(1))) 41 }) 42 }) 43 44 Describe("Entry Descriptions", func() { 45 Describe("tables with no table-level entry description functions or strings", func() { 46 BeforeEach(func() { 47 success, _ := RunFixture("table with no table-level entry description function", func() { 48 DescribeTable("hello", func(a int, b string, c ...float64) {}, 49 Entry(nil, 1, "b"), 50 Entry(nil, 1, "b", 2.71, 3.141), 51 Entry("C", 3, "b", 3.141), 52 ) 53 }) 54 Ω(success).Should(BeTrue()) 55 }) 56 57 It("renders the parameters for nil-described Entries as It strings", func() { 58 Ω(reporter.Did.Names()).Should(Equal([]string{ 59 "Entry: 1, b", 60 "Entry: 1, b, 2.71, 3.141", 61 "C", 62 })) 63 }) 64 }) 65 66 Describe("tables with a table-level entry description function", func() { 67 Context("happy path", func() { 68 BeforeEach(func() { 69 success, _ := RunFixture("table with table-level entry description function", func() { 70 DescribeTable("hello", 71 func(a int, b string, c ...float64) {}, 72 func(a int, b string, c ...float64) string { 73 return fmt.Sprintf("%d | %s | %v", a, b, c) 74 }, 75 Entry(nil, 1, "b"), 76 Entry(nil, 1, "b", 2.71, 3.141), 77 Entry("C", 3, "b", 3.141), 78 ) 79 }) 80 Ω(success).Should(BeTrue()) 81 }) 82 83 It("renders the parameters for nil-described Entries using the provided function as It strings", func() { 84 Ω(reporter.Did.Names()).Should(Equal([]string{ 85 "1 | b | []", 86 "1 | b | [2.71 3.141]", 87 "C", 88 })) 89 }) 90 }) 91 92 Context("with more than one entry description function", func() { 93 BeforeEach(func() { 94 success, _ := RunFixture("table with multiple table-level entry description function", func() { 95 DescribeTable("hello", 96 func(a int, b string, c ...float64) {}, 97 func(a int, b string, c ...float64) string { 98 return fmt.Sprintf("%d | %s | %v", a, b, c) 99 }, 100 func(a int, b string, c ...float64) string { 101 return fmt.Sprintf("%d ~ %s ~ %v", a, b, c) 102 }, 103 Entry(nil, 1, "b"), 104 Entry(nil, 1, "b", 2.71, 3.141), 105 Entry("C", 3, "b", 3.141), 106 ) 107 }) 108 Ω(success).Should(BeTrue()) 109 }) 110 111 It("renders the parameters for nil-described Entries using the last provided function as It strings", func() { 112 Ω(reporter.Did.Names()).Should(Equal([]string{ 113 "1 ~ b ~ []", 114 "1 ~ b ~ [2.71 3.141]", 115 "C", 116 })) 117 }) 118 }) 119 120 Context("with a parameter mismatch", func() { 121 BeforeEach(func() { 122 success, _ := RunFixture("table with multiple table-level entry description function", func() { 123 DescribeTable("hello", 124 func(a int, b string, c ...float64) {}, 125 func(a int, b string) string { 126 return fmt.Sprintf("%d | %s", a, b) 127 }, 128 Entry(nil, 1, "b"), 129 Entry(nil, 1, "b", 2.71, 3.141), 130 Entry("C", 3, "b", 3.141), 131 ) 132 }) 133 Ω(success).Should(BeFalse()) 134 }) 135 136 It("fails the entry with a panic", func() { 137 Ω(reporter.Did.Find("1 | b")).Should(HavePassed()) 138 Ω(reporter.Did.Find("")).Should(HavePanicked("Too many parameters passed in to Entry Description function")) 139 Ω(reporter.Did.Find("C")).Should(HavePassed()) 140 }) 141 }) 142 }) 143 144 Describe("tables with a table-level entry description format strings", func() { 145 BeforeEach(func() { 146 success, _ := RunFixture("table with table-level entry description format strings", func() { 147 DescribeTable("hello", 148 func(a int, b string, c float64) {}, 149 func(a int, b string, c float64) string { return "ignored" }, 150 EntryDescription("%[2]s | %[1]d | %[3]v"), 151 Entry(nil, 1, "a", 1.2), 152 Entry(nil, 1, "b", 2.71), 153 Entry("C", 3, "b", 3.141), 154 ) 155 }) 156 Ω(success).Should(BeTrue()) 157 }) 158 159 It("renders the parameters for nil-described Entries using the provided function as It strings", func() { 160 Ω(reporter.Did.Names()).Should(Equal([]string{ 161 "a | 1 | 1.2", 162 "b | 1 | 2.71", 163 "C", 164 })) 165 }) 166 }) 167 168 Describe("entries with entry description functions and entry description format strings", func() { 169 BeforeEach(func() { 170 entryDescriptionBuilder := func(a, b int) string { 171 return fmt.Sprintf("%d vs %d", a, b) 172 } 173 invalidEntryDescriptionBuilder := func(a, b int) {} 174 175 success, _ := RunFixture("table happy-path with custom descriptions", func() { 176 DescribeTable("hello", 177 bodyFunc, 178 EntryDescription("table-level %d, %d"), 179 Entry(entryDescriptionBuilder, 1, 1), 180 Entry(entryDescriptionBuilder, 2, 2), 181 Entry(entryDescriptionBuilder, 1, 2), 182 Entry(entryDescriptionBuilder, 3, 3), 183 Entry("A", 4, 4), 184 Entry(nil, 5, 5), 185 Entry(EntryDescription("%dx%d"), 6, 6), 186 Entry(invalidEntryDescriptionBuilder, 4, 4), 187 ) 188 }) 189 Ω(success).Should(BeFalse()) 190 }) 191 192 It("runs all the entries, with the correct names", func() { 193 Ω(rt).Should(HaveTracked("1 vs 1", "2 vs 2", "1 vs 2", "3 vs 3", "A", "table-level 5, 5", "6x6")) 194 }) 195 196 It("catches invalid entry description functions", func() { 197 Ω(reporter.Did.Find("")).Should(HavePanicked("Invalid Entry description")) 198 }) 199 200 It("reports on the tests correctly", func() { 201 Ω(reporter.Did.Names()).Should(Equal([]string{"1 vs 1", "2 vs 2", "1 vs 2", "3 vs 3", "A", "table-level 5, 5", "6x6"})) 202 Ω(reporter.Did.Find("1 vs 2")).Should(HaveFailed("fail", types.NodeTypeIt)) 203 Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(8), NPassed(6), NFailed(2))) 204 }) 205 }) 206 207 }) 208 209 Describe("managing parameters", func() { 210 Describe("when table entries are passed incorrect parameters", func() { 211 BeforeEach(func() { 212 success, _ := RunFixture("table with invalid inputs", func() { 213 Describe("container", func() { 214 DescribeTable("with variadic parameters", func(a int, b string, c ...float64) { rt.Run(CurrentSpecReport().LeafNodeText) }, 215 Entry("var-A", 1, "b"), 216 Entry("var-B", 1, "b", 3.0, 4.0), 217 Entry("var-too-few", 1), 218 Entry("var-wrong-type", 1, 2), 219 Entry("var-wrong-type-variadic", 1, "b", 3.0, 4, 5.0), 220 ) 221 DescribeTable("without variadic parameters", func(a int, b string) { rt.Run(CurrentSpecReport().LeafNodeText) }, 222 Entry("nonvar-A", 1, "b"), 223 Entry("nonvar-too-few", 1), 224 Entry("nonvar-wrong-type", 1, 2), 225 Entry("nonvar-too-many", 1, "b", 2), 226 227 Entry(func(a int, b string) string { return "foo" }, 1, 2), 228 ) 229 }) 230 }) 231 Ω(success).Should(BeFalse()) 232 }) 233 234 It("runs all the valid entries, but not the invalid entries", func() { 235 Ω(rt).Should(HaveTracked("var-A", "var-B", "nonvar-A")) 236 }) 237 238 It("reports the invalid entries as having panicked", func() { 239 Ω(reporter.Did.Find("var-too-few")).Should(HavePanicked("The Table Body function expected 2 parameters but you passed in 1")) 240 Ω(reporter.Did.Find("var-wrong-type")).Should(HavePanicked("The Table Body function expected parameter #2 to be of type <string> but you\n passed in <int>")) 241 Ω(reporter.Did.Find("var-wrong-type-variadic")).Should(HavePanicked("The Table Body function expected its variadic parameters to be of type\n <float64> but you passed in <int>")) 242 243 Ω(reporter.Did.Find("nonvar-too-few")).Should(HavePanicked("The Table Body function expected 2 parameters but you passed in 1")) 244 Ω(reporter.Did.Find("nonvar-wrong-type")).Should(HavePanicked("The Table Body function expected parameter #2 to be of type <string> but you\n passed in <int>")) 245 Ω(reporter.Did.Find("nonvar-too-many")).Should(HavePanicked("The Table Body function expected 2 parameters but you passed in 3")) 246 247 Ω(reporter.Did.Find("")).Should(HavePanicked("The Entry Description function expected parameter #2 to be of type <string>")) 248 }) 249 250 It("reports on the tests correctly", func() { 251 Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(10), NPassed(3), NFailed(7))) 252 }) 253 }) 254 255 Describe("handling complex types", func() { 256 type ComplicatedThings struct { 257 Superstructure string 258 Substructure string 259 } 260 261 var A, B, C ComplicatedThings 262 263 BeforeEach(func() { 264 A = ComplicatedThings{Superstructure: "the sixth sheikh's sixth sheep's sick", Substructure: "emir"} 265 B = ComplicatedThings{Superstructure: "the sixth sheikh's sixth sheep's sick", Substructure: "sheep"} 266 C = ComplicatedThings{Superstructure: "the sixth sheikh's sixth sheep's sick", Substructure: "si"} 267 success, _ := RunFixture("table with complicated inputs`", func() { 268 DescribeTable("a more complicated table", 269 func(c ComplicatedThings, count int) { 270 rt.RunWithData(CurrentSpecReport().LeafNodeText, "thing", c, "count", count) 271 Ω(strings.Count(c.Superstructure, c.Substructure)).Should(BeNumerically("==", count)) 272 }, 273 Entry("A", A, 0), 274 Entry("B", B, 1), 275 Entry("C", C, 3), 276 ) 277 }) 278 Ω(success).Should(BeTrue()) 279 }) 280 281 It("passes the parameters in correctly", func() { 282 Ω(rt.DataFor("A")).Should(HaveKeyWithValue("thing", A)) 283 Ω(rt.DataFor("A")).Should(HaveKeyWithValue("count", 0)) 284 Ω(rt.DataFor("B")).Should(HaveKeyWithValue("thing", B)) 285 Ω(rt.DataFor("B")).Should(HaveKeyWithValue("count", 1)) 286 Ω(rt.DataFor("C")).Should(HaveKeyWithValue("thing", C)) 287 Ω(rt.DataFor("C")).Should(HaveKeyWithValue("count", 3)) 288 }) 289 }) 290 291 DescribeTable("it works when nils are passed in", func(a interface{}, b error) { 292 Ω(a).Should(BeNil()) 293 Ω(b).Should(BeNil()) 294 }, Entry("nils", nil, nil)) 295 296 DescribeTable("it supports variadic parameters", func(a int, b string, c ...interface{}) { 297 Ω(a).Should(Equal(c[0])) 298 Ω(b).Should(Equal(c[1])) 299 Ω(c[2]).Should(BeNil()) 300 }, Entry("variadic arguments", 1, "one", 1, "one", nil)) 301 }) 302 303 Describe("when table entries are marked pending", func() { 304 BeforeEach(func() { 305 success, _ := RunFixture("table with pending entries", func() { 306 DescribeTable("hello", bodyFunc, Entry("A", 1, 1), PEntry("B", 1, 1), Entry("C", 1, 2), Entry("D", 1, 1), Entry("E", Pending, 1, 1)) 307 }) 308 Ω(success).Should(BeFalse()) 309 }) 310 311 It("runs all the non-pending entries", func() { 312 Ω(rt).Should(HaveTracked("A", "C", "D")) 313 }) 314 315 It("reports on the tests correctly", func() { 316 Ω(reporter.Did.Names()).Should(Equal([]string{"A", "B", "C", "D", "E"})) 317 Ω(reporter.Did.Find("B")).Should(BePending()) 318 Ω(reporter.Did.Find("C")).Should(HaveFailed("fail", types.NodeTypeIt)) 319 Ω(reporter.Did.Find("E")).Should(BePending()) 320 Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(5), NPassed(2), NFailed(1), NPending(2))) 321 }) 322 }) 323 324 Describe("when table entries are marked focused", func() { 325 BeforeEach(func() { 326 success, _ := RunFixture("table with focused entries", func() { 327 DescribeTable("hello", bodyFunc, Entry("A", 1, 1), Entry("B", 1, 1), FEntry("C", 1, 2), FEntry("D", 1, 1), Entry("E", Focus, 1, 1)) 328 }) 329 Ω(success).Should(BeFalse()) 330 }) 331 332 It("runs all the focused entries", func() { 333 Ω(rt).Should(HaveTracked("C", "D", "E")) 334 }) 335 336 It("reports on the tests correctly", func() { 337 Ω(reporter.Did.Names()).Should(Equal([]string{"A", "B", "C", "D", "E"})) 338 Ω(reporter.Did.Find("A")).Should(HaveBeenSkipped()) 339 Ω(reporter.Did.Find("B")).Should(HaveBeenSkipped()) 340 Ω(reporter.Did.Find("C")).Should(HaveFailed("fail", types.NodeTypeIt)) 341 Ω(reporter.Did.Find("D")).Should(HavePassed(types.NodeTypeIt)) 342 Ω(reporter.Did.Find("E")).Should(HavePassed(types.NodeTypeIt)) 343 Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(5), NPassed(2), NFailed(1), NSkipped(2))) 344 }) 345 }) 346 347 Describe("when tables are marked pending", func() { 348 BeforeEach(func() { 349 success, _ := RunFixture("table marked pending", func() { 350 Describe("top-level", func() { 351 PDescribeTable("hello", bodyFunc, Entry("A", 1, 1), Entry("B", 1, 1)) 352 DescribeTable("hello", Pending, bodyFunc, Entry("C", 1, 2), Entry("D", 1, 1)) 353 It("runs", rt.T("runs")) 354 }) 355 }) 356 Ω(success).Should(BeTrue()) 357 }) 358 359 It("runs all the focused entries", func() { 360 Ω(rt).Should(HaveTracked("runs")) 361 }) 362 363 It("reports on the tests correctly", func() { 364 Ω(reporter.Did.Names()).Should(Equal([]string{"A", "B", "C", "D", "runs"})) 365 Ω(reporter.Did.Find("A")).Should(BePending()) 366 Ω(reporter.Did.Find("B")).Should(BePending()) 367 Ω(reporter.Did.Find("C")).Should(BePending()) 368 Ω(reporter.Did.Find("D")).Should(BePending()) 369 Ω(reporter.Did.Find("runs")).Should(HavePassed()) 370 371 Ω(reporter.End).Should(BeASuiteSummary(true, NSpecs(5), NPassed(1), NFailed(0), NPending(4))) 372 }) 373 }) 374 375 Describe("when tables are marked focused", func() { 376 BeforeEach(func() { 377 success, _ := RunFixture("table marked focused", func() { 378 Describe("top-level", func() { 379 FDescribeTable("hello", bodyFunc, Entry("A", 1, 1), Entry("B", 1, 1)) 380 DescribeTable("hello", Focus, bodyFunc, Entry("C", 1, 2), Entry("D", 1, 1)) 381 It("does not run", rt.T("does not run")) 382 }) 383 }) 384 Ω(success).Should(BeFalse()) 385 }) 386 387 It("runs all the focused entries", func() { 388 Ω(rt).Should(HaveTracked("A", "B", "C", "D")) 389 }) 390 391 It("reports on the tests correctly", func() { 392 Ω(reporter.Did.Names()).Should(Equal([]string{"A", "B", "C", "D", "does not run"})) 393 Ω(reporter.Did.Find("A")).Should(HavePassed()) 394 Ω(reporter.Did.Find("B")).Should(HavePassed()) 395 Ω(reporter.Did.Find("C")).Should(HaveFailed("fail")) 396 Ω(reporter.Did.Find("D")).Should(HavePassed()) 397 Ω(reporter.Did.Find("does not run")).Should(HaveBeenSkipped()) 398 399 Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(5), NPassed(3), NFailed(1), NSkipped(1))) 400 }) 401 }) 402 403 Describe("support for decorators", func() { 404 BeforeEach(func() { 405 success, _ := RunFixture("flaky table", func() { 406 var counter int 407 var currentSpec string 408 409 BeforeEach(func() { 410 if currentSpec != CurrentSpecReport().LeafNodeText { 411 counter = 0 412 currentSpec = CurrentSpecReport().LeafNodeText 413 } 414 }) 415 416 DescribeTable("contrived flaky table", FlakeAttempts(2), 417 func(failUntil int) { 418 rt.Run(CurrentSpecReport().LeafNodeText) 419 counter += 1 420 if counter < failUntil { 421 F("fail") 422 } 423 }, 424 Entry("A", 1), 425 Entry("B", 2), 426 Entry("C", 3), 427 Entry("D", []interface{}{FlakeAttempts(3), Offset(2)}, 3), 428 ) 429 }) 430 Ω(success).Should(BeFalse()) 431 }) 432 433 It("honors the flake attempts decorator", func() { 434 Ω(rt).Should(HaveTracked("A", "B", "B", "C", "C", "D", "D", "D")) 435 }) 436 437 It("reports on the specs appropriately", func() { 438 Ω(reporter.Did.Find("A")).Should(HavePassed(NumAttempts(1))) 439 Ω(reporter.Did.Find("B")).Should(HavePassed(NumAttempts(2))) 440 Ω(reporter.Did.Find("C")).Should(HaveFailed(NumAttempts(2))) 441 Ω(reporter.Did.Find("D")).Should(HavePassed(NumAttempts(3))) 442 }) 443 }) 444 })