github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/ginkgo/internal/testsuite_test.go (about) 1 package internal_test 2 3 import ( 4 "os" 5 "path/filepath" 6 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/ginkgo/ginkgo/internal" 9 "github.com/onsi/ginkgo/types" 10 . "github.com/onsi/gomega" 11 ) 12 13 func TS(path string, pkgName string, isGinkgo bool, state TestSuiteState) TestSuite { 14 return TestSuite{ 15 Path: path, 16 PackageName: pkgName, 17 IsGinkgo: isGinkgo, 18 Precompiled: false, 19 State: state, 20 } 21 } 22 23 func PTS(path string, pkgName string, isGinkgo bool, pathToCompiledTest string, state TestSuiteState) TestSuite { 24 return TestSuite{ 25 Path: path, 26 PackageName: pkgName, 27 IsGinkgo: isGinkgo, 28 Precompiled: true, 29 PathToCompiledTest: pathToCompiledTest, 30 State: state, 31 } 32 } 33 34 var _ = Describe("TestSuite", func() { 35 Describe("Finding Suites", func() { 36 var tmpDir string 37 var origWd string 38 var cliConf types.CLIConfig 39 40 writeFile := func(folder string, filename string, content string, mode os.FileMode) { 41 path := filepath.Join(tmpDir, folder) 42 err := os.MkdirAll(path, 0700) 43 Ω(err).ShouldNot(HaveOccurred()) 44 45 path = filepath.Join(path, filename) 46 os.WriteFile(path, []byte(content), mode) 47 } 48 49 BeforeEach(func() { 50 cliConf = types.CLIConfig{} 51 52 var err error 53 tmpDir, err = os.MkdirTemp("/tmp", "ginkgo") 54 Ω(err).ShouldNot(HaveOccurred()) 55 56 origWd, err = os.Getwd() 57 Ω(err).ShouldNot(HaveOccurred()) 58 Ω(os.Chdir(tmpDir)).Should(Succeed()) 59 60 //go files in the root directory (no tests) 61 writeFile("/", "main.go", "package main", 0666) 62 63 //non-go files in a nested directory 64 writeFile("/redherring", "big_test.jpg", "package ginkgo", 0666) 65 66 //ginkgo tests in ignored go files 67 writeFile("/ignored", ".ignore_dot_test.go", `import "github.com/onsi/ginkgo"`, 0666) 68 writeFile("/ignored", "_ignore_underscore_test.go", `import "github.com/onsi/ginkgo"`, 0666) 69 70 //non-ginkgo tests in a nested directory 71 writeFile("/professorplum", "professorplum_test.go", `import "testing"`, 0666) 72 73 //ginkgo tests in a nested directory 74 writeFile("/colonelmustard", "colonelmustard_test.go", `import "github.com/onsi/ginkgo"`, 0666) 75 76 //ginkgo tests in a deeply nested directory 77 writeFile("/colonelmustard/library", "library_test.go", `import "github.com/onsi/ginkgo"`, 0666) 78 79 //ginkgo tests deeply nested in a vendored dependency 80 writeFile("/vendor/mrspeacock/lounge", "lounge_test.go", `import "github.com/onsi/ginkgo"`, 0666) 81 82 //a precompiled ginkgo test 83 writeFile("/precompiled-dir", "precompiled.test", `fake-binary-file`, 0777) 84 writeFile("/precompiled-dir", "some-other-binary", `fake-binary-file`, 0777) 85 writeFile("/precompiled-dir", "windows.test.exe", `fake-binary-file`, 0666) 86 writeFile("/precompiled-dir", "windows.exe", `fake-binary-file`, 0666) 87 writeFile("/precompiled-dir", "nonexecutable.test", `fake-binary-file`, 0666) 88 }) 89 90 AfterEach(func() { 91 Ω(os.Chdir(origWd)).Should(Succeed()) 92 os.RemoveAll(tmpDir) 93 }) 94 95 Context("when passed no args", func() { 96 Context("when told to recurse", func() { 97 BeforeEach(func() { 98 cliConf.Recurse = true 99 }) 100 101 It("recurses through the current directory, returning all identified tests and skipping vendored, ignored, and precompiled tests", func() { 102 suites := FindSuites([]string{}, cliConf, false) 103 Ω(suites).Should(ConsistOf( 104 TS("./professorplum", "professorplum", false, TestSuiteStateUncompiled), 105 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 106 TS("./colonelmustard/library", "library", true, TestSuiteStateUncompiled), 107 )) 108 }) 109 }) 110 111 Context("when told to recurse and there is a skip-package filter", func() { 112 BeforeEach(func() { 113 cliConf.Recurse = true 114 cliConf.SkipPackage = "professorplum,library,floop" 115 }) 116 117 It("recurses through the current directory, returning all identified tests and skipping vendored, ignored, and precompiled tests", func() { 118 suites := FindSuites([]string{}, cliConf, false) 119 Ω(suites).Should(ConsistOf( 120 TS("./professorplum", "professorplum", false, TestSuiteStateSkippedByFilter), 121 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 122 TS("./colonelmustard/library", "library", true, TestSuiteStateSkippedByFilter), 123 )) 124 }) 125 }) 126 127 Context("when there are no tests in the current directory", func() { 128 BeforeEach(func() { 129 cliConf.Recurse = false 130 }) 131 132 It("returns empty", func() { 133 suites := FindSuites([]string{}, cliConf, false) 134 Ω(suites).Should(BeEmpty()) 135 }) 136 }) 137 138 Context("when told not to recurse", func() { 139 BeforeEach(func() { 140 Ω(os.Chdir("./colonelmustard")).Should(Succeed()) 141 }) 142 143 It("returns tests in the current directory if present", func() { 144 suites := FindSuites([]string{}, cliConf, false) 145 Ω(suites).Should(ConsistOf( 146 TS(".", "colonelmustard", true, TestSuiteStateUncompiled), 147 )) 148 }) 149 }) 150 }) 151 152 Context("when passed args", func() { 153 Context("when told to recurse", func() { 154 BeforeEach(func() { 155 cliConf.Recurse = true 156 }) 157 158 It("recurses through the passed-in directories, returning all identified tests and skipping vendored, ignored, and precompiled tests", func() { 159 suites := FindSuites([]string{"precompiled-dir", "colonelmustard"}, cliConf, false) 160 Ω(suites).Should(ConsistOf( 161 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 162 TS("./colonelmustard/library", "library", true, TestSuiteStateUncompiled), 163 )) 164 }) 165 }) 166 167 Context("when told to recurse and there is a skip-package filter", func() { 168 BeforeEach(func() { 169 cliConf.Recurse = true 170 cliConf.SkipPackage = "library" 171 }) 172 173 It("recurses through the passed-in directories, returning all identified tests and skipping vendored, ignored, and precompiled tests", func() { 174 suites := FindSuites([]string{"precompiled-dir", "professorplum", "colonelmustard"}, cliConf, false) 175 Ω(suites).Should(ConsistOf( 176 TS("./professorplum", "professorplum", false, TestSuiteStateUncompiled), 177 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 178 TS("./colonelmustard/library", "library", true, TestSuiteStateSkippedByFilter), 179 )) 180 }) 181 }) 182 183 Context("when told not to recurse", func() { 184 BeforeEach(func() { 185 cliConf.Recurse = false 186 }) 187 188 It("returns test packages at the passed in arguments", func() { 189 suites := FindSuites([]string{"precompiled-dir", "colonelmustard", "professorplum", "ignored"}, cliConf, false) 190 Ω(suites).Should(ConsistOf( 191 TS("./professorplum", "professorplum", false, TestSuiteStateUncompiled), 192 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 193 )) 194 }) 195 }) 196 197 Context("when told not to recurse, but an arg has /...", func() { 198 BeforeEach(func() { 199 cliConf.Recurse = false 200 }) 201 202 It("recurses through the directories it is told to recurse through, returning all identified tests and skipping vendored, ignored, and precompiled tests", func() { 203 suites := FindSuites([]string{"precompiled-dir", "colonelmustard/...", "professorplum/...", "ignored/..."}, cliConf, false) 204 Ω(suites).Should(ConsistOf( 205 TS("./professorplum", "professorplum", false, TestSuiteStateUncompiled), 206 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 207 TS("./colonelmustard/library", "library", true, TestSuiteStateUncompiled), 208 )) 209 }) 210 }) 211 212 Context("when told not to recurse and there is a skip-package filter", func() { 213 BeforeEach(func() { 214 cliConf.Recurse = false 215 cliConf.SkipPackage = "library,plum" 216 }) 217 218 It("returns skips packages that match", func() { 219 suites := FindSuites([]string{"colonelmustard", "professorplum", "colonelmustard/library"}, cliConf, false) 220 Ω(suites).Should(ConsistOf( 221 TS("./professorplum", "professorplum", false, TestSuiteStateSkippedByFilter), 222 TS("./colonelmustard", "colonelmustard", true, TestSuiteStateUncompiled), 223 TS("./colonelmustard/library", "library", true, TestSuiteStateSkippedByFilter), 224 )) 225 }) 226 }) 227 228 Context("when pointed at a directory containing a precompiled test suite", func() { 229 It("returns nothing", func() { 230 suites := FindSuites([]string{"precompiled-dir"}, cliConf, false) 231 Ω(suites).Should(BeEmpty()) 232 }) 233 }) 234 235 Context("when pointed at a precompiled test suite specifically", func() { 236 It("returns the precompiled suite", func() { 237 path, err := filepath.Abs("./precompiled-dir/precompiled.test") 238 Ω(err).ShouldNot(HaveOccurred()) 239 suites := FindSuites([]string{"precompiled-dir/precompiled.test"}, cliConf, true) 240 Ω(suites).Should(ConsistOf( 241 PTS("./precompiled-dir", "precompiled", true, path, TestSuiteStateCompiled), 242 )) 243 }) 244 }) 245 246 Context("when pointed at a precompiled test suite on windows", func() { 247 It("returns the precompiled suite", func() { 248 path, err := filepath.Abs("./precompiled-dir/windows.exe") 249 Ω(err).ShouldNot(HaveOccurred()) 250 suites := FindSuites([]string{"precompiled-dir/windows.exe"}, cliConf, true) 251 Ω(suites).Should(ConsistOf( 252 PTS("./precompiled-dir", "windows", true, path, TestSuiteStateCompiled), 253 )) 254 255 path, err = filepath.Abs("./precompiled-dir/windows.test.exe") 256 Ω(err).ShouldNot(HaveOccurred()) 257 suites = FindSuites([]string{"precompiled-dir/windows.test.exe"}, cliConf, true) 258 Ω(suites).Should(ConsistOf( 259 PTS("./precompiled-dir", "windows", true, path, TestSuiteStateCompiled), 260 )) 261 }) 262 }) 263 264 Context("when pointed at a fake precompiled test", func() { 265 It("returns nothing", func() { 266 suites := FindSuites([]string{"precompiled-dir/some-other-binary"}, cliConf, true) 267 Ω(suites).Should(BeEmpty()) 268 269 suites = FindSuites([]string{"precompiled-dir/nonexecutable.test"}, cliConf, true) 270 Ω(suites).Should(BeEmpty()) 271 }) 272 }) 273 274 Context("when pointed at a precompiled test suite specifically but allowPrecompiled is false", func() { 275 It("returns nothing", func() { 276 suites := FindSuites([]string{"precompiled-dir/some-other-binary"}, cliConf, false) 277 Ω(suites).Should(BeEmpty()) 278 }) 279 }) 280 }) 281 }) 282 283 Describe("NamespacedName", func() { 284 It("generates a name basd on the relative path to the package", func() { 285 plum := TS("./professorplum", "professorplum", false, TestSuiteStateUncompiled) 286 library := TS("./colonelmustard/library", "library", true, TestSuiteStateUncompiled) 287 root := TS(".", "root", true, TestSuiteStateUncompiled) 288 289 Ω(plum.NamespacedName()).Should(Equal("professorplum")) 290 Ω(library.NamespacedName()).Should(Equal("colonelmustard_library")) 291 Ω(root.NamespacedName()).Should(Equal("root")) 292 }) 293 }) 294 295 Describe("TestSuiteState", func() { 296 Describe("Is", func() { 297 It("returns true if it matches one of the passed in states", func() { 298 Ω(TestSuiteStateCompiled.Is(TestSuiteStateUncompiled, TestSuiteStateCompiled)).Should(BeTrue()) 299 Ω(TestSuiteStateCompiled.Is(TestSuiteStateUncompiled, TestSuiteStatePassed)).Should(BeFalse()) 300 }) 301 }) 302 303 Describe("TestSuiteStateFailureStates", func() { 304 It("should enumerate the failure states", func() { 305 Ω(TestSuiteStateFailureStates).Should(ConsistOf( 306 TestSuiteStateFailed, 307 TestSuiteStateFailedDueToTimeout, 308 TestSuiteStateFailedToCompile, 309 )) 310 }) 311 }) 312 }) 313 314 Describe("TestSuites", func() { 315 var A, B, C, D TestSuite 316 var suites TestSuites 317 BeforeEach(func() { 318 A = TS("/A", "A", true, TestSuiteStateUncompiled) 319 B = TS("/B", "B", true, TestSuiteStateUncompiled) 320 C = TS("/C", "C", true, TestSuiteStateUncompiled) 321 D = TS("/D", "D", true, TestSuiteStateUncompiled) 322 }) 323 324 JustBeforeEach(func() { 325 suites = TestSuites{A, B, C, D} 326 }) 327 328 Describe("AnyHaveProgrammaticFocus", func() { 329 Context("when any suites have programmatic focus", func() { 330 BeforeEach(func() { 331 B.HasProgrammaticFocus = true 332 }) 333 334 It("returns true", func() { 335 Ω(suites.AnyHaveProgrammaticFocus()).Should(BeTrue()) 336 }) 337 }) 338 Context("when any suites do not have programmatic focus", func() { 339 It("returns false", func() { 340 Ω(suites.AnyHaveProgrammaticFocus()).Should(BeFalse()) 341 }) 342 }) 343 }) 344 345 Describe("ThatAreGinkgoSuites", func() { 346 BeforeEach(func() { 347 B.IsGinkgo = false 348 D.IsGinkgo = false 349 }) 350 It("returns the subset that are Ginkgo suites", func() { 351 Ω(suites.ThatAreGinkgoSuites()).Should(Equal(TestSuites{A, C})) 352 }) 353 }) 354 355 Describe("CountWithState", func() { 356 BeforeEach(func() { 357 B.State = TestSuiteStateFailed 358 D.State = TestSuiteStateFailedToCompile 359 }) 360 361 It("returns the number with the matching state", func() { 362 Ω(suites.CountWithState(TestSuiteStateFailed)).Should(Equal(1)) 363 Ω(suites.CountWithState(TestSuiteStateFailed, TestSuiteStateFailedToCompile)).Should(Equal(2)) 364 }) 365 }) 366 367 Describe("WithState", func() { 368 BeforeEach(func() { 369 A.State = TestSuiteStatePassed 370 C.State = TestSuiteStateSkippedByFilter 371 }) 372 373 It("returns the suites matching the passed-in states", func() { 374 Ω(suites.WithState(TestSuiteStatePassed, TestSuiteStateSkippedByFilter)).Should(Equal(TestSuites{A, C})) 375 }) 376 }) 377 378 Describe("WithoutState", func() { 379 BeforeEach(func() { 380 A.State = TestSuiteStatePassed 381 C.State = TestSuiteStateSkippedByFilter 382 }) 383 384 It("returns the suites _not_ matching the passed-in states", func() { 385 Ω(suites.WithoutState(TestSuiteStatePassed, TestSuiteStateSkippedByFilter)).Should(Equal(TestSuites{B, D})) 386 }) 387 }) 388 389 Describe("ShuffledCopy", func() { 390 It("returns a shuffled copy of the test suites", func() { 391 shuffled := suites.ShuffledCopy(17) 392 Ω(suites).Should(Equal(TestSuites{A, B, C, D})) 393 Ω(shuffled).Should(ConsistOf(A, B, C, D)) 394 Ω(shuffled).ShouldNot(Equal(suites)) 395 }) 396 }) 397 }) 398 })