github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/test_helpers/fake_reporter.go (about) 1 package test_helpers 2 3 import ( 4 "reflect" 5 6 . "github.com/onsi/gomega" 7 . "github.com/onsi/gomega/gstruct" 8 9 "github.com/onsi/ginkgo/internal/interrupt_handler" 10 "github.com/onsi/ginkgo/types" 11 ) 12 13 /* 14 15 A FakeReporter and collection of matchers to match against reported suite and spec summaries 16 17 */ 18 19 type Reports []types.SpecReport 20 21 func (s Reports) FindByLeafNodeType(nodeTypes types.NodeType) types.SpecReport { 22 for _, report := range s { 23 if report.LeafNodeType.Is(nodeTypes) { 24 return report 25 } 26 } 27 28 return types.SpecReport{} 29 } 30 31 func (s Reports) Find(name string) types.SpecReport { 32 for _, report := range s { 33 if report.LeafNodeText == name { 34 return report 35 } 36 } 37 38 return types.SpecReport{} 39 } 40 41 func (s Reports) FindByFullText(text string) types.SpecReport { 42 for _, report := range s { 43 if report.FullText() == text { 44 return report 45 } 46 } 47 48 return types.SpecReport{} 49 } 50 51 func (s Reports) Names() []string { 52 out := []string{} 53 for _, report := range s { 54 if report.LeafNodeText != "" { 55 out = append(out, report.LeafNodeText) 56 } 57 } 58 return out 59 } 60 61 func (s Reports) WithState(state types.SpecState) Reports { 62 out := Reports{} 63 for _, report := range s { 64 if report.State == state { 65 out = append(out, report) 66 } 67 } 68 return out 69 } 70 71 func (s Reports) WithLeafNodeType(nodeTypes types.NodeType) Reports { 72 out := Reports{} 73 for _, report := range s { 74 if report.LeafNodeType.Is(nodeTypes) { 75 out = append(out, report) 76 } 77 } 78 return out 79 } 80 81 type FakeReporter struct { 82 Begin types.Report 83 Will Reports 84 Did Reports 85 End types.Report 86 } 87 88 func (r *FakeReporter) SuiteWillBegin(report types.Report) { 89 r.Begin = report 90 } 91 92 func (r *FakeReporter) WillRun(report types.SpecReport) { 93 r.Will = append(r.Will, report) 94 } 95 96 func (r *FakeReporter) DidRun(report types.SpecReport) { 97 r.Did = append(r.Did, report) 98 } 99 100 func (r *FakeReporter) SuiteDidEnd(report types.Report) { 101 r.End = report 102 } 103 104 type NSpecs int 105 type NWillRun int 106 type NPassed int 107 type NSkipped int 108 type NFailed int 109 type NPending int 110 type NFlaked int 111 112 func BeASuiteSummary(options ...interface{}) OmegaMatcher { 113 type ReportStats struct { 114 Succeeded bool 115 TotalSpecs int 116 WillRunSpecs int 117 Passed int 118 Skipped int 119 Failed int 120 Pending int 121 Flaked int 122 } 123 fields := Fields{ 124 "Passed": Equal(0), 125 "Skipped": Equal(0), 126 "Failed": Equal(0), 127 "Pending": Equal(0), 128 "Flaked": Equal(0), 129 "TotalSpecs": Equal(0), 130 } 131 for _, option := range options { 132 t := reflect.TypeOf(option) 133 if t.Kind() == reflect.Bool { 134 if option.(bool) { 135 fields["Succeeded"] = BeTrue() 136 } else { 137 fields["Succeeded"] = BeFalse() 138 } 139 } else if t == reflect.TypeOf(NSpecs(0)) { 140 fields["TotalSpecs"] = Equal(int(option.(NSpecs))) 141 } else if t == reflect.TypeOf(NWillRun(0)) { 142 fields["WillRunSpecs"] = Equal(int(option.(NWillRun))) 143 } else if t == reflect.TypeOf(NPassed(0)) { 144 fields["Passed"] = Equal(int(option.(NPassed))) 145 } else if t == reflect.TypeOf(NSkipped(0)) { 146 fields["Skipped"] = Equal(int(option.(NSkipped))) 147 } else if t == reflect.TypeOf(NFailed(0)) { 148 fields["Failed"] = Equal(int(option.(NFailed))) 149 } else if t == reflect.TypeOf(NPending(0)) { 150 fields["Pending"] = Equal(int(option.(NPending))) 151 } else if t == reflect.TypeOf(NFlaked(0)) { 152 fields["Flaked"] = Equal(int(option.(NFlaked))) 153 } 154 } 155 return WithTransform(func(report types.Report) ReportStats { 156 specs := report.SpecReports.WithLeafNodeType(types.NodeTypeIt) 157 return ReportStats{ 158 Succeeded: report.SuiteSucceeded, 159 TotalSpecs: report.PreRunStats.TotalSpecs, 160 WillRunSpecs: report.PreRunStats.SpecsThatWillRun, 161 Passed: specs.CountWithState(types.SpecStatePassed), 162 Skipped: specs.CountWithState(types.SpecStateSkipped), 163 Failed: specs.CountWithState(types.SpecStateFailureStates), 164 Pending: specs.CountWithState(types.SpecStatePending), 165 Flaked: specs.CountOfFlakedSpecs(), 166 } 167 }, MatchFields(IgnoreExtras, fields)) 168 } 169 170 type CapturedGinkgoWriterOutput string 171 type CapturedStdOutput string 172 type NumAttempts int 173 174 func HavePassed(options ...interface{}) OmegaMatcher { 175 matchers := []OmegaMatcher{ 176 HaveField("State", types.SpecStatePassed), 177 HaveField("Failure", BeZero()), 178 } 179 for _, option := range options { 180 var matcher OmegaMatcher 181 switch v := option.(type) { 182 case CapturedGinkgoWriterOutput: 183 matcher = HaveField("CapturedGinkgoWriterOutput", string(v)) 184 case CapturedStdOutput: 185 matcher = HaveField("CapturedStdOutErr", string(v)) 186 case types.NodeType: 187 matcher = HaveField("LeafNodeType", v) 188 case NumAttempts: 189 matcher = HaveField("NumAttempts", int(v)) 190 } 191 if matcher != nil { 192 matchers = append(matchers, matcher) 193 } 194 } 195 196 return And(matchers...) 197 } 198 199 func BePending() OmegaMatcher { 200 return And( 201 HaveField("State", types.SpecStatePending), 202 HaveField("Failure", BeZero()), 203 ) 204 } 205 206 func HaveBeenSkipped() OmegaMatcher { 207 return And( 208 HaveField("State", types.SpecStateSkipped), 209 HaveField("Failure", BeZero()), 210 ) 211 } 212 213 func HaveBeenSkippedWithMessage(message string, options ...interface{}) OmegaMatcher { 214 matchers := []OmegaMatcher{ 215 HaveField("State", types.SpecStateSkipped), 216 HaveField("Failure.Message", Equal(message)), 217 } 218 219 for _, option := range options { 220 switch v := option.(type) { 221 case NumAttempts: 222 matchers = append(matchers, HaveField("NumAttempts", int(v))) 223 } 224 } 225 return And(matchers...) 226 } 227 228 func HaveBeenInterrupted(cause interrupt_handler.InterruptCause) OmegaMatcher { 229 return And( 230 HaveField("State", types.SpecStateInterrupted), 231 HaveField("Failure.Message", HavePrefix(cause.String())), 232 ) 233 } 234 235 type FailureNodeType types.NodeType 236 237 func failureMatcherForState(state types.SpecState, messageField string, options ...interface{}) OmegaMatcher { 238 matchers := []OmegaMatcher{ 239 HaveField("State", state), 240 } 241 for _, option := range options { 242 var matcher OmegaMatcher 243 switch v := option.(type) { 244 case CapturedGinkgoWriterOutput: 245 matcher = HaveField("CapturedGinkgoWriterOutput", string(v)) 246 case CapturedStdOutput: 247 matcher = HaveField("CapturedStdOutErr", string(v)) 248 case types.NodeType: 249 matcher = HaveField("LeafNodeType", v) 250 case types.FailureNodeContext: 251 matcher = HaveField("Failure.FailureNodeContext", v) 252 case string: 253 matcher = HaveField(messageField, ContainSubstring(v)) 254 case types.CodeLocation: 255 matcher = HaveField("Failure.Location", v) 256 case FailureNodeType: 257 matcher = HaveField("Failure.FailureNodeType", types.NodeType(v)) 258 case NumAttempts: 259 matcher = HaveField("NumAttempts", int(v)) 260 } 261 if matcher != nil { 262 matchers = append(matchers, matcher) 263 } 264 } 265 266 return And(matchers...) 267 } 268 269 func HaveFailed(options ...interface{}) OmegaMatcher { 270 return failureMatcherForState(types.SpecStateFailed, "Failure.Message", options...) 271 } 272 273 func HaveAborted(options ...interface{}) OmegaMatcher { 274 return failureMatcherForState(types.SpecStateAborted, "Failure.Message", options...) 275 } 276 277 func HavePanicked(options ...interface{}) OmegaMatcher { 278 return failureMatcherForState(types.SpecStatePanicked, "Failure.ForwardedPanic", options...) 279 }