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  })