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