github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/ordering_test.go (about) 1 package internal_test 2 3 import ( 4 "strings" 5 6 . "github.com/onsi/ginkgo" 7 . "github.com/onsi/gomega" 8 9 "github.com/onsi/ginkgo/internal" 10 "github.com/onsi/ginkgo/types" 11 ) 12 13 type SpecTexts []string 14 15 func getTexts(specs Specs, groupedSpecIndices internal.GroupedSpecIndices) SpecTexts { 16 out := []string{} 17 for _, specIndices := range groupedSpecIndices { 18 for _, idx := range specIndices { 19 out = append(out, specs[idx].Text()) 20 } 21 } 22 return out 23 } 24 25 func (tt SpecTexts) Join() string { 26 return strings.Join(tt, "") 27 } 28 29 var _ = Describe("OrderSpecs", func() { 30 var conf types.SuiteConfig 31 var specs Specs 32 33 BeforeEach(func() { 34 conf = types.SuiteConfig{} 35 conf.RandomSeed = 1 36 conf.ParallelTotal = 1 37 38 con1 := N(ntCon) 39 con2 := N(ntCon) 40 specs = Specs{ 41 S(N("A", ntIt)), 42 S(N("B", ntIt)), 43 S(con1, N("C", ntIt)), 44 S(con1, N("D", ntIt)), 45 S(con1, N(ntCon), N("E", ntIt)), 46 S(N("F", ntIt)), 47 S(con2, N("G", ntIt)), 48 S(con2, N("H", ntIt)), 49 } 50 }) 51 52 Context("when configured to only randomize top-level specs", func() { 53 It("shuffles top level specs only", func() { 54 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 55 groupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 56 Ω(serialSpecIndices).Should(BeEmpty()) 57 58 Ω(getTexts(specs, groupedSpecIndices).Join()).Should(ContainSubstring("CDE")) 59 Ω(getTexts(specs, groupedSpecIndices).Join()).Should(ContainSubstring("GH")) 60 } 61 62 conf.RandomSeed = 1 63 groupedSpecIndices1, _ := internal.OrderSpecs(specs, conf) 64 conf.RandomSeed = 2 65 groupedSpecIndices2, _ := internal.OrderSpecs(specs, conf) 66 Ω(getTexts(specs, groupedSpecIndices1)).ShouldNot(Equal(getTexts(specs, groupedSpecIndices2))) 67 }) 68 }) 69 70 Context("when configured to randomize all specs", func() { 71 BeforeEach(func() { 72 conf.RandomizeAllSpecs = true 73 }) 74 75 It("shuffles all specs", func() { 76 hasCDE := true 77 hasGH := true 78 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 79 groupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 80 Ω(serialSpecIndices).Should(BeEmpty()) 81 82 hasCDE, _ = ContainSubstring("CDE").Match(getTexts(specs, groupedSpecIndices).Join()) 83 hasGH, _ = ContainSubstring("GH").Match(getTexts(specs, groupedSpecIndices).Join()) 84 if !hasCDE && !hasGH { 85 break 86 } 87 } 88 89 Ω(hasCDE || hasGH).Should(BeFalse(), "after 10 randomizations, we really shouldn't have gotten CDE and GH in order as all specs should be shuffled, not just top-level containers and specs") 90 91 conf.RandomSeed = 1 92 groupedSpecIndices1, _ := internal.OrderSpecs(specs, conf) 93 conf.RandomSeed = 2 94 groupedSpecIndices2, _ := internal.OrderSpecs(specs, conf) 95 Ω(getTexts(specs, groupedSpecIndices1)).ShouldNot(Equal(getTexts(specs, groupedSpecIndices2))) 96 }) 97 }) 98 99 Context("when passed the same seed", func() { 100 It("always generates the same order", func() { 101 for _, conf.RandomizeAllSpecs = range []bool{true, false} { 102 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 103 groupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 104 Ω(serialSpecIndices).Should(BeEmpty()) 105 for i := 0; i < 10; i++ { 106 reshuffledGroupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 107 Ω(serialSpecIndices).Should(BeEmpty()) 108 109 Ω(getTexts(specs, groupedSpecIndices)).Should(Equal(getTexts(specs, reshuffledGroupedSpecIndices))) 110 } 111 } 112 } 113 }) 114 }) 115 116 Context("when specs are in different files and the files are loaded in an undefined order", func() { 117 var specsInFileA, specsInFileB Specs 118 BeforeEach(func() { 119 con1 := N(ntCon, CL("file_A", 10)) 120 specsInFileA = Specs{ 121 S(N("A", ntIt, CL("file_A", 1))), 122 S(N("B", ntIt, CL("file_A", 5))), 123 S(con1, N("C", ntIt, CL("file_A", 15))), 124 S(con1, N("D", ntIt, CL("file_A", 20))), 125 S(con1, N(ntCon, CL("file_A", 25)), N("E", ntIt, CL("file_A", 30))), 126 } 127 128 con2 := N(ntCon, CL("file_B", 10)) 129 specsInFileB = Specs{ 130 S(N("F", ntIt, CL("file_B", 1))), 131 S(con2, N("G", ntIt, CL("file_B", 15))), 132 S(con2, N("H", ntIt, CL("file_B", 20))), 133 } 134 135 }) 136 137 It("always generates a consistent randomization when given the same seed", func() { 138 for _, conf.RandomizeAllSpecs = range []bool{true, false} { 139 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 140 specsOrderAB := Specs{} 141 specsOrderAB = append(specsOrderAB, specsInFileA...) 142 specsOrderAB = append(specsOrderAB, specsInFileB...) 143 144 specsOrderBA := Specs{} 145 specsOrderBA = append(specsOrderBA, specsInFileB...) 146 specsOrderBA = append(specsOrderBA, specsInFileA...) 147 148 groupedSpecIndicesAB, serialSpecIndices := internal.OrderSpecs(specsOrderAB, conf) 149 Ω(serialSpecIndices).Should(BeEmpty()) 150 151 groupedSpecIndicesBA, serialSpecIndices := internal.OrderSpecs(specsOrderBA, conf) 152 Ω(serialSpecIndices).Should(BeEmpty()) 153 154 Ω(getTexts(specsOrderAB, groupedSpecIndicesAB)).Should(Equal(getTexts(specsOrderBA, groupedSpecIndicesBA))) 155 } 156 } 157 }) 158 }) 159 160 Context("when there are ordered specs", func() { 161 BeforeEach(func() { 162 con1 := N(ntCon, Ordered) 163 con2 := N(ntCon) 164 specs = Specs{ 165 S(N("A", ntIt)), 166 S(N("B", ntIt)), 167 S(con1, N("C", ntIt)), 168 S(con1, N("D", ntIt)), 169 S(con1, N(ntCon), N("E", ntIt)), 170 S(N("F", ntIt)), 171 S(con2, N("G", ntIt)), 172 S(con2, N("H", ntIt)), 173 } 174 175 conf.RandomizeAllSpecs = true 176 }) 177 178 It("never shuffles the specs in ordered specs", func() { 179 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 180 groupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 181 Ω(serialSpecIndices).Should(BeEmpty()) 182 183 Ω(getTexts(specs, groupedSpecIndices).Join()).Should(ContainSubstring("CDE")) 184 } 185 }) 186 }) 187 188 Context("when there are serial specs", func() { 189 BeforeEach(func() { 190 con1 := N(ntCon, Ordered, Serial) 191 con2 := N(ntCon) 192 specs = Specs{ 193 S(N("A", Serial, ntIt)), 194 S(N("B", ntIt)), 195 S(con1, N("C", ntIt)), 196 S(con1, N("D", ntIt)), 197 S(con1, N(ntCon), N("E", ntIt)), 198 S(N("F", ntIt)), 199 S(con2, N("G", ntIt)), 200 S(con2, N("H", ntIt, Serial)), 201 } 202 conf.RandomizeAllSpecs = true 203 }) 204 205 Context("and the tests are not running in parallel", func() { 206 BeforeEach(func() { 207 conf.ParallelTotal = 1 208 }) 209 210 It("puts all the tests in the parallelizable group and returns an empty serial group", func() { 211 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 212 groupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 213 Ω(serialSpecIndices).Should(BeEmpty()) 214 215 Ω(getTexts(specs, groupedSpecIndices).Join()).Should(ContainSubstring("CDE")) 216 Ω(getTexts(specs, groupedSpecIndices)).Should(ConsistOf("A", "B", "C", "D", "E", "F", "G", "H")) 217 } 218 219 conf.RandomSeed = 1 220 groupedSpecIndices1, _ := internal.OrderSpecs(specs, conf) 221 conf.RandomSeed = 2 222 groupedSpecIndices2, _ := internal.OrderSpecs(specs, conf) 223 Ω(getTexts(specs, groupedSpecIndices1)).ShouldNot(Equal(getTexts(specs, groupedSpecIndices2))) 224 }) 225 }) 226 227 Context("and the tests are running in parallel", func() { 228 BeforeEach(func() { 229 conf.ParallelTotal = 2 230 }) 231 232 It("puts all parallelizable tests in the parallelizable group and all serial tests in the serial group, preserving ordered test order", func() { 233 for conf.RandomSeed = 1; conf.RandomSeed < 10; conf.RandomSeed += 1 { 234 groupedSpecIndices, serialSpecIndices := internal.OrderSpecs(specs, conf) 235 236 Ω(getTexts(specs, groupedSpecIndices)).Should(ConsistOf("B", "F", "G")) 237 Ω(getTexts(specs, serialSpecIndices).Join()).Should(ContainSubstring("CDE")) 238 Ω(getTexts(specs, serialSpecIndices)).Should(ConsistOf("A", "C", "D", "E", "H")) 239 } 240 241 conf.RandomSeed = 1 242 groupedSpecIndices1, serialSpecIndices1 := internal.OrderSpecs(specs, conf) 243 conf.RandomSeed = 2 244 groupedSpecIndices2, serialSpecIndices2 := internal.OrderSpecs(specs, conf) 245 Ω(getTexts(specs, groupedSpecIndices1)).ShouldNot(Equal(getTexts(specs, groupedSpecIndices2))) 246 Ω(getTexts(specs, serialSpecIndices1)).ShouldNot(Equal(getTexts(specs, serialSpecIndices2))) 247 }) 248 }) 249 }) 250 })