github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/internal_integration/report_after_suite_test.go (about) 1 package internal_integration_test 2 3 import ( 4 "time" 5 6 . "github.com/onsi/ginkgo" 7 "github.com/onsi/ginkgo/internal/interrupt_handler" 8 . "github.com/onsi/ginkgo/internal/test_helpers" 9 "github.com/onsi/ginkgo/types" 10 . "github.com/onsi/gomega" 11 ) 12 13 var _ = Describe("Sending reports to ReportAfterSuite procs", func() { 14 var failInReportAfterSuiteA, interruptSuiteB bool 15 var fixture func() 16 17 BeforeEach(func() { 18 failInReportAfterSuiteA = false 19 interruptSuiteB = false 20 conf.RandomSeed = 17 21 fixture = func() { 22 BeforeSuite(rt.T("before-suite", func() { 23 outputInterceptor.AppendInterceptedOutput("out-before-suite") 24 })) 25 Context("container", func() { 26 It("A", rt.T("A")) 27 It("B", rt.T("B", func() { 28 F("fail in B") 29 })) 30 It("C", rt.T("C")) 31 PIt("D", rt.T("D")) 32 }) 33 ReportAfterSuite("Report A", func(report Report) { 34 rt.RunWithData("report-A", "report", report) 35 writer.Print("gw-report-A") 36 outputInterceptor.AppendInterceptedOutput("out-report-A") 37 if failInReportAfterSuiteA { 38 F("fail in report-A") 39 } 40 }) 41 ReportAfterSuite("Report B", func(report Report) { 42 if interruptSuiteB { 43 interruptHandler.Interrupt(interrupt_handler.InterruptCauseTimeout) 44 time.Sleep(100 * time.Millisecond) 45 } 46 rt.RunWithData("report-B", "report", report, "emitted-interrupt", interruptHandler.EmittedInterruptPlaceholderMessage()) 47 writer.Print("gw-report-B") 48 outputInterceptor.AppendInterceptedOutput("out-report-B") 49 }) 50 AfterSuite(rt.T("after-suite", func() { 51 writer.Print("gw-after-suite") 52 F("fail in after-suite") 53 })) 54 55 } 56 }) 57 58 Context("when running in series", func() { 59 BeforeEach(func() { 60 conf.ParallelTotal = 1 61 conf.ParallelProcess = 1 62 }) 63 64 Context("the happy path", func() { 65 BeforeEach(func() { 66 success, _ := RunFixture("happy-path", fixture) 67 Ω(success).Should(BeFalse()) 68 }) 69 70 It("runs all the functions", func() { 71 Ω(rt).Should(HaveTracked( 72 "before-suite", 73 "A", "B", "C", 74 "after-suite", 75 "report-A", "report-B", 76 )) 77 }) 78 79 It("reports on the report procs", func() { 80 Ω(reporter.Did.Find("Report A")).Should(HavePassed( 81 types.NodeTypeReportAfterSuite, 82 CapturedGinkgoWriterOutput("gw-report-A"), 83 CapturedStdOutput("out-report-A"), 84 )) 85 86 Ω(reporter.Did.Find("Report B")).Should(HavePassed( 87 types.NodeTypeReportAfterSuite, 88 CapturedGinkgoWriterOutput("gw-report-B"), 89 CapturedStdOutput("out-report-B"), 90 )) 91 }) 92 93 It("passes the report in to each reporter", func() { 94 reportA := rt.DataFor("report-A")["report"].(types.Report) 95 reportB := rt.DataFor("report-B")["report"].(types.Report) 96 97 for _, report := range []types.Report{reportA, reportB} { 98 Ω(report.SuiteDescription).Should(Equal("happy-path")) 99 Ω(report.SuiteSucceeded).Should(BeFalse()) 100 Ω(report.SuiteConfig.RandomSeed).Should(Equal(int64(17))) 101 reports := Reports(report.SpecReports) 102 Ω(reports.FindByLeafNodeType(types.NodeTypeBeforeSuite)).Should(HavePassed(CapturedStdOutput("out-before-suite"))) 103 Ω(reports.Find("A")).Should(HavePassed()) 104 Ω(reports.Find("B")).Should(HaveFailed("fail in B")) 105 Ω(reports.Find("C")).Should(HavePassed()) 106 Ω(reports.Find("D")).Should(BePending()) 107 Ω(reports.FindByLeafNodeType(types.NodeTypeAfterSuite)).Should(HaveFailed("fail in after-suite", CapturedGinkgoWriterOutput("gw-after-suite"))) 108 } 109 110 Ω(len(reportB.SpecReports)-len(reportA.SpecReports)).Should(Equal(1), "Report B includes the invocation of ReporteAfterSuite A") 111 Ω(Reports(reportB.SpecReports).Find("Report A")).Should(Equal(reporter.Did.Find("Report A"))) 112 }) 113 }) 114 115 Context("when a ReportAfterSuite proc fails", func() { 116 BeforeEach(func() { 117 failInReportAfterSuiteA = true 118 success, _ := RunFixture("report-A-fails", fixture) 119 Ω(success).Should(BeFalse()) 120 }) 121 122 It("keeps running subseuqent reporting functions", func() { 123 Ω(rt).Should(HaveTracked( 124 "before-suite", 125 "A", "B", "C", 126 "after-suite", 127 "report-A", "report-B", 128 )) 129 }) 130 131 It("reports on the faitlure, to Ginkgo's reporter and any subsequent reporters", func() { 132 Ω(reporter.Did.Find("Report A")).Should(HaveFailed( 133 types.NodeTypeReportAfterSuite, 134 "fail in report-A", 135 CapturedGinkgoWriterOutput("gw-report-A"), 136 CapturedStdOutput("out-report-A"), 137 )) 138 139 reportB := rt.DataFor("report-B")["report"].(types.Report) 140 Ω(Reports(reportB.SpecReports).Find("Report A")).Should(Equal(reporter.Did.Find("Report A"))) 141 }) 142 }) 143 144 Context("when an interrupt is attempted in a ReportAfterSuiteNode", func() { 145 BeforeEach(func() { 146 interruptSuiteB = true 147 success, _ := RunFixture("report-B-interrupted", fixture) 148 Ω(success).Should(BeFalse()) 149 }) 150 151 It("ignores the interrupt and soliders on", func() { 152 Ω(rt).Should(HaveTracked( 153 "before-suite", 154 "A", "B", "C", 155 "after-suite", 156 "report-A", "report-B", 157 )) 158 159 Ω(rt.DataFor("report-B")["report"]).ShouldNot(BeZero()) 160 Ω(rt.DataFor("report-B")["emitted-interrupt"]).Should(ContainSubstring("The running ReportAfterSuite node is at:\n%s", reporter.Did.Find("Report B").LeafNodeLocation.FileName)) 161 }) 162 }) 163 }) 164 165 Context("when running in parallel", func() { 166 var otherNodeReport types.Report 167 168 BeforeEach(func() { 169 SetUpForParallel(2) 170 171 otherNodeReport = types.Report{ 172 SpecReports: types.SpecReports{ 173 types.SpecReport{LeafNodeText: "E", LeafNodeLocation: cl, State: types.SpecStatePassed, LeafNodeType: types.NodeTypeIt}, 174 types.SpecReport{LeafNodeText: "F", LeafNodeLocation: cl, State: types.SpecStateSkipped, LeafNodeType: types.NodeTypeIt}, 175 }, 176 } 177 }) 178 179 Context("on proc 1", func() { 180 BeforeEach(func() { 181 conf.ParallelProcess = 1 182 }) 183 184 Context("the happy path", func() { 185 BeforeEach(func() { 186 // proc 2 has reported back and exited 187 client.PostSuiteDidEnd(otherNodeReport) 188 close(exitChannels[2]) 189 success, _ := RunFixture("happy-path", fixture) 190 Ω(success).Should(BeFalse()) 191 }) 192 193 It("runs all the functions", func() { 194 Ω(rt).Should(HaveTracked( 195 "before-suite", 196 "A", "B", "C", 197 "after-suite", 198 "report-A", "report-B", 199 )) 200 }) 201 202 It("passes the report in to each reporter, including information from other procs", func() { 203 reportA := rt.DataFor("report-A")["report"].(types.Report) 204 reportB := rt.DataFor("report-B")["report"].(types.Report) 205 206 for _, report := range []types.Report{reportA, reportB} { 207 Ω(report.SuiteDescription).Should(Equal("happy-path")) 208 Ω(report.SuiteSucceeded).Should(BeFalse()) 209 reports := Reports(report.SpecReports) 210 Ω(reports.FindByLeafNodeType(types.NodeTypeBeforeSuite)).Should(HavePassed(CapturedStdOutput("out-before-suite"))) 211 Ω(reports.Find("A")).Should(HavePassed()) 212 Ω(reports.Find("B")).Should(HaveFailed("fail in B")) 213 Ω(reports.Find("C")).Should(HavePassed()) 214 Ω(reports.Find("D")).Should(BePending()) 215 Ω(reports.Find("E")).Should(HavePassed()) 216 Ω(reports.Find("F")).Should(HaveBeenSkipped()) 217 Ω(reports.FindByLeafNodeType(types.NodeTypeAfterSuite)).Should(HaveFailed("fail in after-suite", CapturedGinkgoWriterOutput("gw-after-suite"))) 218 } 219 220 Ω(len(reportB.SpecReports)-len(reportA.SpecReports)).Should(Equal(1), "Report B includes the invocation of ReporteAfterSuite A") 221 Ω(Reports(reportB.SpecReports).Find("Report A")).Should(Equal(reporter.Did.Find("Report A"))) 222 }) 223 }) 224 225 Describe("waiting for reports from other procs", func() { 226 It("blocks until the other procs have finished", func() { 227 done := make(chan interface{}) 228 go func() { 229 defer GinkgoRecover() 230 success, _ := RunFixture("happy-path", fixture) 231 Ω(success).Should(BeFalse()) 232 close(done) 233 }() 234 Consistently(done).ShouldNot(BeClosed()) 235 client.PostSuiteDidEnd(otherNodeReport) 236 Consistently(done).ShouldNot(BeClosed()) 237 close(exitChannels[2]) 238 Eventually(done).Should(BeClosed()) 239 }) 240 }) 241 242 Context("when a non-primary proc disappears before it reports", func() { 243 BeforeEach(func() { 244 close(exitChannels[2]) //proc 2 disappears before reporting 245 success, _ := RunFixture("disappearing-proc-2", fixture) 246 Ω(success).Should(BeFalse()) 247 }) 248 249 It("does not run the ReportAfterSuite procs", func() { 250 Ω(rt).Should(HaveTracked( 251 "before-suite", 252 "A", "B", "C", 253 "after-suite", 254 )) 255 }) 256 257 It("reports all the ReportAfterSuite procs as failed", func() { 258 Ω(reporter.Did.Find("Report A")).Should(HaveFailed(types.GinkgoErrors.AggregatedReportUnavailableDueToNodeDisappearing().Error())) 259 Ω(reporter.Did.Find("Report B")).Should(HaveFailed(types.GinkgoErrors.AggregatedReportUnavailableDueToNodeDisappearing().Error())) 260 }) 261 }) 262 }) 263 264 Context("on a non-primary proc", func() { 265 BeforeEach(func() { 266 conf.ParallelProcess = 2 267 success, _ := RunFixture("happy-path", fixture) 268 Ω(success).Should(BeFalse()) 269 }) 270 271 It("does not run the ReportAfterSuite procs", func() { 272 Ω(rt).Should(HaveTracked( 273 "before-suite", 274 "A", "B", "C", 275 "after-suite", 276 )) 277 }) 278 }) 279 }) 280 })