func (runnable *runnableNode) run() (outcome runOutcome, failure failureData) { done := make(chan interface{}, 1) defer func() { if e := recover(); e != nil { outcome = runOutcomePanicked failure = failureData{ message: "Test Panicked", codeLocation: types.GenerateCodeLocation(2), forwardedPanic: e, } } }() if runnable.isAsync { go runnable.asyncFunc(done) } else { runnable.syncFunc() done <- true } select { case <-done: outcome = runOutcomeCompleted case <-time.After(runnable.timeoutThreshold): outcome = runOutcomeTimedOut failure = failureData{ message: "Timed out", codeLocation: runnable.codeLocation, } } return }
func (suite *suite) fail(message string, callerSkip int) { if suite.exampleCollection != nil { suite.exampleCollection.fail(failureData{ message: message, codeLocation: types.GenerateCodeLocation(callerSkip + 2), }) } }
func (runnable *runnableNode) run() (outcome runOutcome, failure failureData) { done := make(chan interface{}, 1) lock := &sync.Mutex{} panicRecovery := func() { if e := recover(); e != nil { lock.Lock() outcome = runOutcomePanicked failure = failureData{ message: "Test Panicked", codeLocation: types.GenerateCodeLocation(2), forwardedPanic: e, } lock.Unlock() select { case <-done: break default: close(done) } } } defer panicRecovery() if runnable.isAsync { go func() { defer panicRecovery() runnable.asyncFunc(done) }() } else { runnable.syncFunc() close(done) } select { case <-done: lock.Lock() if outcome != runOutcomePanicked { outcome = runOutcomeCompleted } lock.Unlock() case <-time.After(runnable.timeoutThreshold): lock.Lock() if outcome != runOutcomePanicked { outcome = runOutcomeTimedOut failure = failureData{ message: "Timed out", codeLocation: runnable.codeLocation, } } lock.Unlock() } return }
func (node *measureNode) run() (outcome runOutcome, failure failureData) { defer func() { if e := recover(); e != nil { outcome = runOutcomePanicked failure = failureData{ message: "Test Panicked", codeLocation: types.GenerateCodeLocation(2), forwardedPanic: e, } } }() node.body(node.benchmarker) outcome = runOutcomeCompleted return }
func init() { Describe("MeasureNode", func() { var measure *measureNode var i int var codeLocation types.CodeLocation BeforeEach(func() { i = 0 codeLocation = types.GenerateCodeLocation(0) measure = newMeasureNode("foo", func(b Benchmarker) { b.RecordValue("bar", float64(i)) i += 1 }, flagTypeFocused, codeLocation, 10) }) It("should report on itself accurately", func() { Ω(measure.getText()).Should(Equal("foo")) Ω(measure.getFlag()).Should(Equal(flagTypeFocused)) Ω(measure.getCodeLocation()).Should(Equal(codeLocation)) Ω(measure.nodeType()).Should(Equal(nodeTypeMeasure)) Ω(measure.samples).Should(Equal(10)) }) Context("when run", func() { It("should provide the body function with a benchmarker and be able to aggregate reports", func() { measure.run() measure.run() measure.run() measure.run() report := measure.measurementsReport() Ω(report).Should(HaveLen(1)) Ω(report["bar"].Name).Should(Equal("bar")) Ω(report["bar"].Results).Should(Equal([]float64{0, 1, 2, 3})) }) }) }) }
func init() { Describe("RunnableNode", func() { Describe("basic construction parameters", func() { It("should store off the passed in code location", func() { codeLocation := types.GenerateCodeLocation(0) Ω(newRunnableNode(func() {}, codeLocation, 0).codeLocation).Should(Equal(codeLocation)) }) }) Describe("running the passed in function", func() { Context("when the function is synchronous and does not panic", func() { It("should run the function and report a runOutcomeCompleted", func() { didRun := false runnableNode := newRunnableNode(func() { didRun = true }, types.GenerateCodeLocation(0), 0) outcome, failure := runnableNode.run() Ω(didRun).Should(BeTrue()) Ω(outcome).Should(Equal(runOutcomeCompleted)) Ω(failure).Should(BeZero()) }) }) Context("when the function is synchronous and *does* panic", func() { var ( codeLocation types.CodeLocation outcome runOutcome failure failureData ) BeforeEach(func() { node := newRunnableNode(func() { codeLocation = types.GenerateCodeLocation(0) panic("ack!") }, types.GenerateCodeLocation(0), 0) outcome, failure = node.run() }) It("should run the function and report a runOutcomePanicked", func() { Ω(outcome).Should(Equal(runOutcomePanicked)) Ω(failure.message).Should(Equal("Test Panicked")) }) It("should include the code location of the panic itself", func() { Ω(failure.codeLocation.FileName).Should(Equal(codeLocation.FileName)) Ω(failure.codeLocation.LineNumber).Should(Equal(codeLocation.LineNumber + 1)) }) It("should include the panic data", func() { Ω(failure.forwardedPanic).Should(Equal("ack!")) }) }) Context("when the function is asynchronous", func() { var ( node *runnableNode sleepDuration time.Duration timeoutDuration time.Duration numberOfGoRoutines int ) BeforeEach(func() { sleepDuration = time.Duration(0.001 * float64(time.Second)) timeoutDuration = time.Duration(1 * float64(time.Second)) }) JustBeforeEach(func() { node = newRunnableNode(func(done Done) { numberOfGoRoutines = runtime.NumGoroutine() time.Sleep(sleepDuration) done <- true }, types.GenerateCodeLocation(0), timeoutDuration) }) It("should run the function as a goroutine", func() { initialNumberOfGoRoutines := runtime.NumGoroutine() outcome, failure := node.run() Ω(outcome).Should(Equal(runOutcomeCompleted)) Ω(failure).Should(BeZero()) Ω(numberOfGoRoutines).Should(Equal(initialNumberOfGoRoutines + 1)) }) Context("when the function takes longer than the timeout", func() { BeforeEach(func() { sleepDuration = time.Duration(0.002 * float64(time.Second)) timeoutDuration = time.Duration(0.001 * float64(time.Second)) }) It("should timeout", func() { outcome, failure := node.run() Ω(outcome).Should(Equal(runOutcomeTimedOut)) Ω(failure.message).Should(Equal("Timed out")) Ω(failure.codeLocation).Should(Equal(node.codeLocation)) }) }) }) Context("when the function is asynchronous and panics", func() { var ( codeLocation types.CodeLocation outcome runOutcome failure failureData ) BeforeEach(func() { node := newRunnableNode(func(done Done) { codeLocation = types.GenerateCodeLocation(0) panic("ack!") }, types.GenerateCodeLocation(0), time.Duration(0.01*float64(time.Second))) outcome, failure = node.run() }) It("should run the function and report a runOutcomePanicked", func() { Ω(outcome).Should(Equal(runOutcomePanicked)) Ω(failure.message).Should(Equal("Test Panicked")) }) It("should include the code location of the panic itself", func() { Ω(failure.codeLocation.FileName).Should(Equal(codeLocation.FileName)) Ω(failure.codeLocation.LineNumber).Should(Equal(codeLocation.LineNumber + 1)) }) It("should include the panic data", func() { Ω(failure.forwardedPanic).Should(Equal("ack!")) }) }) Context("when the function takes the wrong kind of argument", func() { It("should panic", func() { Ω(func() { newRunnableNode(func(oops string) { }, types.GenerateCodeLocation(0), 0) }).Should(Panic()) }) }) Context("when the function takes more than one argument", func() { It("should panic", func() { Ω(func() { newRunnableNode(func(done Done, oops string) { }, types.GenerateCodeLocation(0), 0) }).Should(Panic()) }) }) }) }) Describe("ItNodes", func() { It("should save off the text and flags", func() { codeLocation := types.GenerateCodeLocation(0) it := newItNode("my it node", func() {}, flagTypeFocused, codeLocation, 0) Ω(it.flag).Should(Equal(flagTypeFocused)) Ω(it.text).Should(Equal("my it node")) Ω(it.codeLocation).Should(Equal(codeLocation)) }) }) }
func init() { Describe("Suite", func() { var ( specSuite *suite fakeT *fakeTestingT fakeR *fakeReporter ) BeforeEach(func() { fakeT = &fakeTestingT{} fakeR = &fakeReporter{} specSuite = newSuite() }) Describe("running a suite", func() { var ( runOrder []string randomizeAllSpecs bool randomSeed int64 focusString string parallelNode int parallelTotal int ) var f = func(runText string) func() { return func() { runOrder = append(runOrder, runText) } } BeforeEach(func() { randomizeAllSpecs = false randomSeed = 11 parallelNode = 1 parallelTotal = 1 focusString = "" runOrder = make([]string, 0) specSuite.pushBeforeEachNode(f("top BE"), types.GenerateCodeLocation(0), 0) specSuite.pushJustBeforeEachNode(f("top JBE"), types.GenerateCodeLocation(0), 0) specSuite.pushAfterEachNode(f("top AE"), types.GenerateCodeLocation(0), 0) specSuite.pushContainerNode("container", func() { specSuite.pushBeforeEachNode(f("BE"), types.GenerateCodeLocation(0), 0) specSuite.pushJustBeforeEachNode(f("JBE"), types.GenerateCodeLocation(0), 0) specSuite.pushAfterEachNode(f("AE"), types.GenerateCodeLocation(0), 0) specSuite.pushItNode("it", f("IT"), flagTypeNone, types.GenerateCodeLocation(0), 0) specSuite.pushContainerNode("inner container", func() { specSuite.pushItNode("inner it", f("inner IT"), flagTypeNone, types.GenerateCodeLocation(0), 0) }, flagTypeNone, types.GenerateCodeLocation(0)) }, flagTypeNone, types.GenerateCodeLocation(0)) specSuite.pushContainerNode("container 2", func() { specSuite.pushBeforeEachNode(f("BE 2"), types.GenerateCodeLocation(0), 0) specSuite.pushItNode("it 2", f("IT 2"), flagTypeNone, types.GenerateCodeLocation(0), 0) }, flagTypeNone, types.GenerateCodeLocation(0)) specSuite.pushItNode("top level it", f("top IT"), flagTypeNone, types.GenerateCodeLocation(0), 0) }) JustBeforeEach(func() { specSuite.run(fakeT, "suite description", []Reporter{fakeR}, config.GinkgoConfigType{ RandomSeed: randomSeed, RandomizeAllSpecs: randomizeAllSpecs, FocusString: focusString, ParallelNode: parallelNode, ParallelTotal: parallelTotal, }) }) It("provides the config and suite description to the reporter", func() { Ω(fakeR.config.RandomSeed).Should(Equal(int64(randomSeed))) Ω(fakeR.config.RandomizeAllSpecs).Should(Equal(randomizeAllSpecs)) Ω(fakeR.beginSummary.SuiteDescription).Should(Equal("suite description")) }) Measure("should run measurements", func(b Benchmarker) { r := rand.New(rand.NewSource(time.Now().UnixNano())) runtime := b.Time("sleeping", func() { sleepTime := time.Duration(r.Float64() * 0.01 * float64(time.Second)) time.Sleep(sleepTime) }) Ω(runtime.Seconds()).Should(BeNumerically("<=", 0.011)) Ω(runtime.Seconds()).Should(BeNumerically(">=", 0)) randomValue := r.Float64() * 10.0 b.RecordValue("random value", randomValue) Ω(randomValue).Should(BeNumerically("<=", 10.0)) Ω(randomValue).Should(BeNumerically(">=", 0.0)) }, 10) It("creates a node hierarchy, converts it to an example collection, and runs it", func() { Ω(runOrder).Should(Equal([]string{ "top BE", "BE", "top JBE", "JBE", "IT", "AE", "top AE", "top BE", "BE", "top JBE", "JBE", "inner IT", "AE", "top AE", "top BE", "BE 2", "top JBE", "IT 2", "top AE", "top BE", "top JBE", "top IT", "top AE", })) }) Context("when told to randomize all examples", func() { BeforeEach(func() { randomizeAllSpecs = true }) It("does", func() { Ω(runOrder).Should(Equal([]string{ "top BE", "top JBE", "top IT", "top AE", "top BE", "BE", "top JBE", "JBE", "inner IT", "AE", "top AE", "top BE", "BE", "top JBE", "JBE", "IT", "AE", "top AE", "top BE", "BE 2", "top JBE", "IT 2", "top AE", })) }) }) Describe("with ginkgo.parallel.total > 1", func() { BeforeEach(func() { parallelTotal = 2 randomizeAllSpecs = true }) Context("for one worker", func() { BeforeEach(func() { parallelNode = 1 }) It("should run a subset of tests", func() { Ω(runOrder).Should(Equal([]string{ "top BE", "top JBE", "top IT", "top AE", "top BE", "BE", "top JBE", "JBE", "inner IT", "AE", "top AE", })) }) }) Context("for another worker", func() { BeforeEach(func() { parallelNode = 2 }) It("should run a (different) subset of tests", func() { Ω(runOrder).Should(Equal([]string{ "top BE", "BE", "top JBE", "JBE", "IT", "AE", "top AE", "top BE", "BE 2", "top JBE", "IT 2", "top AE", })) }) }) }) Context("when provided with a filter", func() { BeforeEach(func() { focusString = `inner|\d` }) It("converts the filter to a regular expression and uses it to filter the running examples", func() { Ω(runOrder).Should(Equal([]string{ "top BE", "BE", "top JBE", "JBE", "inner IT", "AE", "top AE", "top BE", "BE 2", "top JBE", "IT 2", "top AE", })) }) }) Context("when the specs pass", func() { It("doesn't report a failure", func() { Ω(fakeT.didFail).Should(BeFalse()) }) }) Context("when a spec fails", func() { var location types.CodeLocation BeforeEach(func() { specSuite.pushItNode("top level it", func() { location = types.GenerateCodeLocation(0) func() { specSuite.fail("oops!", 0) }() }, flagTypeNone, types.GenerateCodeLocation(0), 0) }) It("reports a failure", func() { Ω(fakeT.didFail).Should(BeTrue()) }) It("generates the correct failure data", func() { Ω(fakeR.exampleSummaries[0].Failure.Message).Should(Equal("oops!")) Ω(fakeR.exampleSummaries[0].Failure.Location.FileName).Should(Equal(location.FileName)) Ω(fakeR.exampleSummaries[0].Failure.Location.LineNumber).Should(Equal(location.LineNumber + 1)) }) }) }) }) }
func (node *panickySubject) getCodeLocation() types.CodeLocation { return types.GenerateCodeLocation(1) }
func init() { Describe("Example", func() { var it *itNode BeforeEach(func() { it = newItNode("It", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) }) Describe("creating examples and adding container nodes", func() { var ( containerA *containerNode containerB *containerNode ex *example ) BeforeEach(func() { containerA = newContainerNode("A", flagTypeNone, types.GenerateCodeLocation(0)) containerB = newContainerNode("B", flagTypeNone, types.GenerateCodeLocation(0)) }) JustBeforeEach(func() { ex = newExample(it) ex.addContainerNode(containerB) ex.addContainerNode(containerA) }) It("should store off the it node", func() { Ω(ex.subject).Should(Equal(it)) }) It("should store off the container nodes in reverse order", func() { Ω(ex.containers).Should(Equal([]*containerNode{containerA, containerB})) }) It("should provide the concatenated strings", func() { Ω(ex.concatenatedString()).Should(Equal("A B It")) }) Context("when neither the It node nor the containers is focused or pending", func() { It("should not be focused or pending", func() { Ω(ex.focused).Should(BeFalse()) Ω(ex.state).Should(BeZero()) }) }) Context("when the It node is focused", func() { BeforeEach(func() { it.flag = flagTypeFocused }) It("should be focused", func() { Ω(ex.focused).Should(BeTrue()) }) }) Context("when one of the containers is focused", func() { BeforeEach(func() { containerB.flag = flagTypeFocused }) It("should be focused", func() { Ω(ex.focused).Should(BeTrue()) }) }) Context("when the It node is pending", func() { BeforeEach(func() { it.flag = flagTypePending }) It("should be in the pending state", func() { Ω(ex.state).Should(Equal(types.ExampleStatePending)) }) }) Context("when one of the containers is pending", func() { BeforeEach(func() { containerB.flag = flagTypePending }) It("should be in the pending state", func() { Ω(ex.state).Should(Equal(types.ExampleStatePending)) }) }) Context("when one container is pending and another container is focused", func() { BeforeEach(func() { containerA.flag = flagTypeFocused containerB.flag = flagTypePending }) It("should be focused and have the pending state", func() { Ω(ex.focused).Should(BeTrue()) Ω(ex.state).Should(Equal(types.ExampleStatePending)) }) }) }) Describe("Skipping an example", func() { It("should mark the example as skipped", func() { ex := newExample(it) ex.skip() Ω(ex.state).Should(Equal(types.ExampleStateSkipped)) }) }) Describe("skippedOrPending", func() { It("should be false if the example is neither pending nor skipped", func() { ex := newExample(it) Ω(ex.skippedOrPending()).Should(BeFalse()) }) It("should be true if the example is pending", func() { it.flag = flagTypePending ex := newExample(it) Ω(ex.skippedOrPending()).Should(BeTrue()) }) It("should be true if the example is skipped", func() { ex := newExample(it) ex.skip() Ω(ex.skippedOrPending()).Should(BeTrue()) }) }) Describe("pending", func() { It("should be false if the example is not pending", func() { ex := newExample(it) Ω(ex.pending()).Should(BeFalse()) }) It("should be true if the example is pending", func() { it.flag = flagTypePending ex := newExample(it) Ω(ex.pending()).Should(BeTrue()) }) }) Describe("running examples and getting summaries", func() { var ( orderedList []string it *itNode innerContainer *containerNode outerContainer *containerNode ex *example ) newNode := func(identifier string) *runnableNode { return newRunnableNode(func() { orderedList = append(orderedList, identifier) }, types.GenerateCodeLocation(0), 0) } BeforeEach(func() { orderedList = make([]string, 0) it = newItNode("it", func() { orderedList = append(orderedList, "IT") time.Sleep(time.Duration(0.01 * float64(time.Second))) }, flagTypeNone, types.GenerateCodeLocation(0), 0) ex = newExample(it) innerContainer = newContainerNode("inner", flagTypeNone, types.GenerateCodeLocation(0)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_A")) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_B")) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_A")) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_B")) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_A")) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_B")) ex.addContainerNode(innerContainer) outerContainer = newContainerNode("outer", flagTypeNone, types.GenerateCodeLocation(0)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_A")) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_B")) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_A")) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_B")) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_A")) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_B")) ex.addContainerNode(outerContainer) }) It("should report that it has an it node", func() { Ω(ex.subjectComponentType()).Should(Equal(types.ExampleComponentTypeIt)) }) It("runs the before/justBefore/after nodes in each of the containers, and the it node, in the correct order", func() { ex.run() Ω(orderedList).Should(Equal([]string{ "OUTER_BEFORE_A", "OUTER_BEFORE_B", "INNER_BEFORE_A", "INNER_BEFORE_B", "OUTER_JUST_BEFORE_A", "OUTER_JUST_BEFORE_B", "INNER_JUST_BEFORE_A", "INNER_JUST_BEFORE_B", "IT", "INNER_AFTER_A", "INNER_AFTER_B", "OUTER_AFTER_A", "OUTER_AFTER_B", })) }) Describe("the summary", func() { It("has the texts and code locations for the container nodes and the it node", func() { ex.run() summary := ex.summary() Ω(summary.ComponentTexts).Should(Equal([]string{ "outer", "inner", "it", })) Ω(summary.ComponentCodeLocations).Should(Equal([]types.CodeLocation{ outerContainer.codeLocation, innerContainer.codeLocation, it.codeLocation, })) }) }) Context("when none of the runnable nodes fail", func() { It("has a summary reporting no failure", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStatePassed)) Ω(summary.RunTime.Seconds()).Should(BeNumerically(">", 0.01)) Ω(summary.IsMeasurement).Should(BeFalse()) }) }) componentTypes := []string{"BeforeEach", "JustBeforeEach", "AfterEach"} expectedComponentTypes := []types.ExampleComponentType{types.ExampleComponentTypeBeforeEach, types.ExampleComponentTypeJustBeforeEach, types.ExampleComponentTypeAfterEach} pushFuncs := []func(container *containerNode, node *runnableNode){(*containerNode).pushBeforeEachNode, (*containerNode).pushJustBeforeEachNode, (*containerNode).pushAfterEachNode} for i := range componentTypes { Context(fmt.Sprintf("when a %s node fails", componentTypes[i]), func() { var componentCodeLocation types.CodeLocation BeforeEach(func() { componentCodeLocation = types.GenerateCodeLocation(0) }) Context("because an expectation failed", func() { var failure failureData BeforeEach(func() { failure = failureData{ message: fmt.Sprintf("%s failed", componentTypes[i]), codeLocation: types.GenerateCodeLocation(0), } node := newRunnableNode(func() { ex.fail(failure) ex.fail(failureData{message: "IGNORE ME!"}) }, componentCodeLocation, 0) pushFuncs[i](innerContainer, node) }) It("has a summary with the correct failure report", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStateFailed)) Ω(summary.Failure.Message).Should(Equal(failure.message)) Ω(summary.Failure.Location).Should(Equal(failure.codeLocation)) Ω(summary.Failure.ForwardedPanic).Should(BeNil()) Ω(summary.Failure.ComponentIndex).Should(Equal(1), "Should be the inner container that failed") Ω(summary.Failure.ComponentType).Should(Equal(expectedComponentTypes[i])) Ω(summary.Failure.ComponentCodeLocation).Should(Equal(componentCodeLocation)) Ω(ex.failed()).Should(BeTrue()) }) }) Context("because the function panicked", func() { var panicCodeLocation types.CodeLocation BeforeEach(func() { node := newRunnableNode(func() { panicCodeLocation = types.GenerateCodeLocation(0) panic("kaboom!") }, componentCodeLocation, 0) pushFuncs[i](innerContainer, node) }) It("has a summary with the correct failure report", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStatePanicked)) Ω(summary.Failure.Message).Should(Equal("Test Panicked")) Ω(summary.Failure.Location.FileName).Should(Equal(panicCodeLocation.FileName)) Ω(summary.Failure.Location.LineNumber).Should(Equal(panicCodeLocation.LineNumber+1), "Expect panic code location to be correct") Ω(summary.Failure.ForwardedPanic).Should(Equal("kaboom!")) Ω(summary.Failure.ComponentIndex).Should(Equal(1), "Should be the inner container that failed") Ω(summary.Failure.ComponentType).Should(Equal(expectedComponentTypes[i])) Ω(summary.Failure.ComponentCodeLocation).Should(Equal(componentCodeLocation)) Ω(ex.failed()).Should(BeTrue()) }) }) Context("because the function timed out", func() { BeforeEach(func() { node := newRunnableNode(func(done Done) { time.Sleep(time.Duration(0.002 * float64(time.Second))) done <- true }, componentCodeLocation, time.Duration(0.001*float64(time.Second))) pushFuncs[i](innerContainer, node) }) It("has a summary with the correct failure report", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStateTimedOut)) Ω(summary.Failure.Message).Should(Equal("Timed out")) Ω(summary.Failure.Location).Should(Equal(componentCodeLocation)) Ω(summary.Failure.ForwardedPanic).Should(BeNil()) Ω(summary.Failure.ComponentIndex).Should(Equal(1), "Should be the inner container that failed") Ω(summary.Failure.ComponentType).Should(Equal(expectedComponentTypes[i])) Ω(summary.Failure.ComponentCodeLocation).Should(Equal(componentCodeLocation)) Ω(ex.failed()).Should(BeTrue()) }) }) }) } Context("when the it node fails", func() { var componentCodeLocation types.CodeLocation BeforeEach(func() { componentCodeLocation = types.GenerateCodeLocation(0) }) Context("because an expectation failed", func() { var failure failureData BeforeEach(func() { failure = failureData{ message: "it failed", codeLocation: types.GenerateCodeLocation(0), } ex.subject = newItNode("it", func() { ex.fail(failure) ex.fail(failureData{message: "IGNORE ME!"}) }, flagTypeNone, componentCodeLocation, 0) }) It("has a summary with the correct failure report", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStateFailed)) Ω(summary.Failure.Message).Should(Equal(failure.message)) Ω(summary.Failure.Location).Should(Equal(failure.codeLocation)) Ω(summary.Failure.ForwardedPanic).Should(BeNil()) Ω(summary.Failure.ComponentIndex).Should(Equal(2), "Should be the it node that failed") Ω(summary.Failure.ComponentType).Should(Equal(types.ExampleComponentTypeIt)) Ω(summary.Failure.ComponentCodeLocation).Should(Equal(componentCodeLocation)) Ω(ex.failed()).Should(BeTrue()) }) }) Context("because the function panicked", func() { var panicCodeLocation types.CodeLocation BeforeEach(func() { ex.subject = newItNode("it", func() { panicCodeLocation = types.GenerateCodeLocation(0) panic("kaboom!") }, flagTypeNone, componentCodeLocation, 0) }) It("has a summary with the correct failure report", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStatePanicked)) Ω(summary.Failure.Message).Should(Equal("Test Panicked")) Ω(summary.Failure.Location.FileName).Should(Equal(panicCodeLocation.FileName)) Ω(summary.Failure.Location.LineNumber).Should(Equal(panicCodeLocation.LineNumber+1), "Expect panic code location to be correct") Ω(summary.Failure.ForwardedPanic).Should(Equal("kaboom!")) Ω(summary.Failure.ComponentIndex).Should(Equal(2), "Should be the it node that failed") Ω(summary.Failure.ComponentType).Should(Equal(types.ExampleComponentTypeIt)) Ω(summary.Failure.ComponentCodeLocation).Should(Equal(componentCodeLocation)) Ω(ex.failed()).Should(BeTrue()) }) }) Context("because the function timed out", func() { BeforeEach(func() { ex.subject = newItNode("it", func(done Done) { time.Sleep(time.Duration(0.002 * float64(time.Second))) done <- true }, flagTypeNone, componentCodeLocation, time.Duration(0.001*float64(time.Second))) }) It("has a summary with the correct failure report", func() { ex.run() summary := ex.summary() Ω(summary.State).Should(Equal(types.ExampleStateTimedOut)) Ω(summary.Failure.Message).Should(Equal("Timed out")) Ω(summary.Failure.Location).Should(Equal(componentCodeLocation)) Ω(summary.Failure.ForwardedPanic).Should(BeNil()) Ω(summary.Failure.ComponentIndex).Should(Equal(2), "Should be the it node that failed") Ω(summary.Failure.ComponentType).Should(Equal(types.ExampleComponentTypeIt)) Ω(summary.Failure.ComponentCodeLocation).Should(Equal(componentCodeLocation)) Ω(ex.failed()).Should(BeTrue()) }) }) }) }) Describe("running measurement examples and getting summaries", func() { var ( runs int componentCodeLocation types.CodeLocation ex *example ) BeforeEach(func() { runs = 0 componentCodeLocation = types.GenerateCodeLocation(0) }) It("should report that it has a measurement", func() { ex = newExample(newMeasureNode("measure", func(b Benchmarker) {}, flagTypeNone, componentCodeLocation, 1)) Ω(ex.subjectComponentType()).Should(Equal(types.ExampleComponentTypeMeasure)) }) Context("when the measurement does not fail", func() { BeforeEach(func() { ex = newExample(newMeasureNode("measure", func(b Benchmarker) { b.RecordValue("foo", float64(runs)) runs++ }, flagTypeNone, componentCodeLocation, 5)) }) It("runs the measurement samples number of times and returns statistics", func() { ex.run() summary := ex.summary() Ω(runs).Should(Equal(5)) Ω(summary.State).Should(Equal(types.ExampleStatePassed)) Ω(summary.IsMeasurement).Should(BeTrue()) Ω(summary.NumberOfSamples).Should(Equal(5)) Ω(summary.Measurements).Should(HaveLen(1)) Ω(summary.Measurements["foo"].Name).Should(Equal("foo")) Ω(summary.Measurements["foo"].Results).Should(Equal([]float64{0, 1, 2, 3, 4})) }) }) Context("when one of the measurement samples fails", func() { BeforeEach(func() { ex = newExample(newMeasureNode("measure", func(b Benchmarker) { b.RecordValue("foo", float64(runs)) runs++ if runs == 3 { ex.fail(failureData{}) } }, flagTypeNone, componentCodeLocation, 5)) }) It("marks the measurement as failed and doesn't run any more samples", func() { ex.run() summary := ex.summary() Ω(runs).Should(Equal(3)) Ω(summary.State).Should(Equal(types.ExampleStateFailed)) Ω(summary.IsMeasurement).Should(BeTrue()) Ω(summary.NumberOfSamples).Should(Equal(5)) Ω(summary.Measurements).Should(BeEmpty()) }) }) }) Describe("running AfterEach nodes when other nodes fail", func() { var ( orderedList []string ex *example ) newNode := func(identifier string, fail bool) *runnableNode { return newRunnableNode(func() { orderedList = append(orderedList, identifier) if fail { ex.fail(failureData{ message: identifier + " failed", }) } }, types.GenerateCodeLocation(0), 0) } newIt := func(identifier string, fail bool) *itNode { return newItNode(identifier, func() { orderedList = append(orderedList, identifier) if fail { ex.fail(failureData{}) } }, flagTypeNone, types.GenerateCodeLocation(0), 0) } BeforeEach(func() { orderedList = make([]string, 0) }) Context("when the it node fails", func() { BeforeEach(func() { ex = newExample(newIt("it", true)) innerContainer := newContainerNode("inner", flagTypeNone, types.GenerateCodeLocation(0)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_A", false)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_B", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_A", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_B", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_A", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_B", false)) ex.addContainerNode(innerContainer) outerContainer := newContainerNode("outer", flagTypeNone, types.GenerateCodeLocation(0)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_A", false)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_B", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_A", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_B", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_A", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_B", false)) ex.addContainerNode(outerContainer) ex.run() }) It("should run all the AfterEach nodes", func() { Ω(orderedList).Should(Equal([]string{ "OUTER_BEFORE_A", "OUTER_BEFORE_B", "INNER_BEFORE_A", "INNER_BEFORE_B", "OUTER_JUST_BEFORE_A", "OUTER_JUST_BEFORE_B", "INNER_JUST_BEFORE_A", "INNER_JUST_BEFORE_B", "it", "INNER_AFTER_A", "INNER_AFTER_B", "OUTER_AFTER_A", "OUTER_AFTER_B", })) }) }) Context("when an inner BeforeEach node fails", func() { BeforeEach(func() { ex = newExample(newIt("it", true)) innerContainer := newContainerNode("inner", flagTypeNone, types.GenerateCodeLocation(0)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_A", true)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_B", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_A", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_B", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_A", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_B", false)) ex.addContainerNode(innerContainer) outerContainer := newContainerNode("outer", flagTypeNone, types.GenerateCodeLocation(0)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_A", false)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_B", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_A", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_B", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_A", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_B", false)) ex.addContainerNode(outerContainer) ex.run() }) It("should run all the AfterEach nodes at nesting levels equal to or lower than the failed BeforeEach block", func() { Ω(orderedList).Should(Equal([]string{ "OUTER_BEFORE_A", "OUTER_BEFORE_B", "INNER_BEFORE_A", "INNER_AFTER_A", "INNER_AFTER_B", "OUTER_AFTER_A", "OUTER_AFTER_B", })) }) }) Context("when an outer BeforeEach node fails", func() { BeforeEach(func() { ex = newExample(newIt("it", true)) innerContainer := newContainerNode("inner", flagTypeNone, types.GenerateCodeLocation(0)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_A", false)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_B", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_A", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_B", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_A", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_B", false)) ex.addContainerNode(innerContainer) outerContainer := newContainerNode("outer", flagTypeNone, types.GenerateCodeLocation(0)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_A", false)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_B", true)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_A", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_B", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_A", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_B", false)) ex.addContainerNode(outerContainer) ex.run() }) It("should run all the AfterEach nodes at nesting levels equal to or lower than the failed BeforeEach block", func() { Ω(orderedList).Should(Equal([]string{ "OUTER_BEFORE_A", "OUTER_BEFORE_B", "OUTER_AFTER_A", "OUTER_AFTER_B", })) }) }) Context("when a JustBeforeEach node fails", func() { BeforeEach(func() { ex = newExample(newIt("it", true)) innerContainer := newContainerNode("inner", flagTypeNone, types.GenerateCodeLocation(0)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_A", false)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_B", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_A", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_B", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_A", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_B", false)) ex.addContainerNode(innerContainer) outerContainer := newContainerNode("outer", flagTypeNone, types.GenerateCodeLocation(0)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_A", false)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_B", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_A", true)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_B", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_A", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_B", false)) ex.addContainerNode(outerContainer) ex.run() }) It("should run all the AfterEach nodes", func() { Ω(orderedList).Should(Equal([]string{ "OUTER_BEFORE_A", "OUTER_BEFORE_B", "INNER_BEFORE_A", "INNER_BEFORE_B", "OUTER_JUST_BEFORE_A", "INNER_AFTER_A", "INNER_AFTER_B", "OUTER_AFTER_A", "OUTER_AFTER_B", })) }) }) Context("when an AfterEach node fails", func() { BeforeEach(func() { ex = newExample(newIt("it", true)) innerContainer := newContainerNode("inner", flagTypeNone, types.GenerateCodeLocation(0)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_A", false)) innerContainer.pushBeforeEachNode(newNode("INNER_BEFORE_B", false)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_A", true)) innerContainer.pushJustBeforeEachNode(newNode("INNER_JUST_BEFORE_B", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_A", false)) innerContainer.pushAfterEachNode(newNode("INNER_AFTER_B", true)) ex.addContainerNode(innerContainer) outerContainer := newContainerNode("outer", flagTypeNone, types.GenerateCodeLocation(0)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_A", false)) outerContainer.pushBeforeEachNode(newNode("OUTER_BEFORE_B", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_A", false)) outerContainer.pushJustBeforeEachNode(newNode("OUTER_JUST_BEFORE_B", false)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_A", true)) outerContainer.pushAfterEachNode(newNode("OUTER_AFTER_B", false)) ex.addContainerNode(outerContainer) ex.run() }) It("should nonetheless continue to run subsequent after each nodes", func() { Ω(orderedList).Should(Equal([]string{ "OUTER_BEFORE_A", "OUTER_BEFORE_B", "INNER_BEFORE_A", "INNER_BEFORE_B", "OUTER_JUST_BEFORE_A", "OUTER_JUST_BEFORE_B", "INNER_JUST_BEFORE_A", "INNER_AFTER_A", "INNER_AFTER_B", "OUTER_AFTER_A", "OUTER_AFTER_B", })) }) It("should not override the failure data of the earliest failure", func() { Ω(ex.summary().Failure.Message).Should(Equal("INNER_JUST_BEFORE_A failed")) }) }) }) }) }
func init() { Describe("Example Collection", func() { var ( fakeT *fakeTestingT fakeR *fakeReporter examplesThatWereRun []string collection *exampleCollection ) exampleWithItFunc := func(itText string, flag flagType, fail bool) *example { return newExample(newItNode(itText, func() { examplesThatWereRun = append(examplesThatWereRun, itText) time.Sleep(time.Duration(0.001 * float64(time.Second))) if fail { collection.fail(failureData{ message: itText + " Failed", }) } }, flag, types.GenerateCodeLocation(0), 0)) } BeforeEach(func() { fakeT = &fakeTestingT{} fakeR = &fakeReporter{} examplesThatWereRun = make([]string, 0) }) Describe("shuffling the collection", func() { BeforeEach(func() { collection = newExampleCollection(fakeT, "collection description", []*example{ exampleWithItFunc("C", flagTypeNone, false), exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), }, []Reporter{fakeR}, config.GinkgoConfigType{}) }) It("should be sortable", func() { sort.Sort(collection) collection.run() Ω(examplesThatWereRun).Should(Equal([]string{"A", "B", "C"})) }) It("shuffles all the examples after sorting them", func() { collection.shuffle(rand.New(rand.NewSource(17))) collection.run() Ω(examplesThatWereRun).Should(Equal(shuffleStrings([]string{"A", "B", "C"}, 17)), "The permutation should be the same across test runs") }) }) Describe("reporting to multiple reporter", func() { var otherFakeR *fakeReporter BeforeEach(func() { otherFakeR = &fakeReporter{} collection = newExampleCollection(fakeT, "collection description", []*example{ exampleWithItFunc("C", flagTypeNone, false), exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), }, []Reporter{fakeR, otherFakeR}, config.GinkgoConfigType{}) collection.run() }) It("reports to both reporters", func() { Ω(otherFakeR.beginSummary).Should(Equal(fakeR.beginSummary)) Ω(otherFakeR.endSummary).Should(Equal(fakeR.endSummary)) Ω(otherFakeR.exampleSummaries).Should(Equal(fakeR.exampleSummaries)) }) }) Describe("running an example collection", func() { var ( example1 *example example2 *example example3 *example conf config.GinkgoConfigType ) BeforeEach(func() { conf = config.GinkgoConfigType{FocusString: "", ParallelTotal: 1, ParallelNode: 1} example1 = exampleWithItFunc("it 1", flagTypeNone, false) example2 = exampleWithItFunc("it 2", flagTypeNone, false) example3 = exampleWithItFunc("it 3", flagTypeNone, false) }) JustBeforeEach(func() { collection = newExampleCollection(fakeT, "collection description", []*example{example1, example2, example3}, []Reporter{fakeR}, conf) collection.run() }) Context("when all the examples pass", func() { It("runs all the tests", func() { Ω(examplesThatWereRun).Should(Equal([]string{"it 1", "it 2", "it 3"})) }) It("marks the suite as passed", func() { Ω(fakeT.didFail).Should(BeFalse()) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(3)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleWillRunSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(3)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(3)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) Context("when examples fail", func() { BeforeEach(func() { example2 = exampleWithItFunc("failing it 2", flagTypeNone, true) example3 = exampleWithItFunc("failing it 3", flagTypeNone, true) }) It("runs all the tests", func() { Ω(examplesThatWereRun).Should(Equal([]string{"it 1", "failing it 2", "failing it 3"})) }) It("marks the suite as failed", func() { Ω(fakeT.didFail).Should(BeTrue()) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(3)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeFalse()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(3)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(1)) Ω(summary.NumberOfFailedExamples).Should(Equal(2)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) Context("when examples are pending", func() { BeforeEach(func() { example1 = exampleWithItFunc("pending it 1", flagTypePending, false) }) It("skips the pending examples", func() { Ω(examplesThatWereRun).Should(Equal([]string{"it 2", "it 3"})) }) It("marks the suite as passed", func() { Ω(fakeT.didFail).Should(BeFalse()) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(1)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(1)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(2)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) Context("and --failOnPending is set", func() { BeforeEach(func() { conf.FailOnPending = true }) It("should mark the suite as failed", func() { Ω(fakeT.didFail).Should(BeTrue()) summary := fakeR.endSummary Ω(summary.SuiteSucceeded).Should(BeFalse()) }) }) }) Context("when examples are focused", func() { BeforeEach(func() { example1 = exampleWithItFunc("focused it 1", flagTypeFocused, false) example3 = exampleWithItFunc("focused it 3", flagTypeFocused, false) }) It("skips the non-focused examples", func() { Ω(examplesThatWereRun).Should(Equal([]string{"focused it 1", "focused it 3"})) }) It("marks the suite as passed", func() { Ω(fakeT.didFail).Should(BeFalse()) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(1)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(1)) Ω(summary.NumberOfPassedExamples).Should(Equal(2)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) Context("when a regexp focusString is provided", func() { BeforeEach(func() { conf.FocusString = `collection description.*pickles\d$` example1 = exampleWithItFunc("focused it 1", flagTypeFocused, false) example2 = exampleWithItFunc("another it pickles2", flagTypeNone, false) example3 = exampleWithItFunc("focused it pickles3", flagTypeFocused, false) }) It("ignores the programmatic focus and applies the regexp focusString", func() { Ω(examplesThatWereRun).Should(Equal([]string{"another it pickles2", "focused it pickles3"})) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(1)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(1)) Ω(summary.NumberOfPassedExamples).Should(Equal(2)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) Context("when a regexp skipString is provided", func() { BeforeEach(func() { conf.SkipString = `collection description.*pickles\d$` example1 = exampleWithItFunc("focused it 1", flagTypeFocused, false) example2 = exampleWithItFunc("another it pickles2", flagTypeNone, false) example3 = exampleWithItFunc("focused it pickles3", flagTypeFocused, false) }) It("ignores the programmatic focus and applies the regexp skipString", func() { Ω(examplesThatWereRun).Should(Equal([]string{"focused it 1"})) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(1)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(2)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(1)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(2)) Ω(summary.NumberOfPassedExamples).Should(Equal(1)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) Context("when both a regexp skipString and focusString are provided", func() { BeforeEach(func() { conf.SkipString = `collection description.*2` conf.FocusString = `collection description.*A` example1 = exampleWithItFunc("A1", flagTypeFocused, false) example2 = exampleWithItFunc("A2", flagTypeNone, false) example3 = exampleWithItFunc("B1", flagTypeFocused, false) }) It("ignores the programmatic focus and ANDs the focusString and skipString", func() { Ω(examplesThatWereRun).Should(Equal([]string{"A1"})) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(1)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(2)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(3)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example1.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[2]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(3)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(1)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(2)) Ω(summary.NumberOfPassedExamples).Should(Equal(1)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) Context("when a examples are run in parallel", func() { BeforeEach(func() { conf.ParallelTotal = 2 conf.ParallelNode = 2 }) It("trims the example set before running them", func() { Ω(examplesThatWereRun).Should(Equal([]string{"it 2", "it 3"})) }) It("publishes the correct starting suite summary", func() { summary := fakeR.beginSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(2)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(0)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime).Should(Equal(time.Duration(0))) }) It("publishes the correct example summaries", func() { Ω(fakeR.exampleSummaries).Should(HaveLen(2)) Ω(fakeR.exampleSummaries[0]).Should(Equal(example2.summary())) Ω(fakeR.exampleSummaries[1]).Should(Equal(example3.summary())) }) It("publishes the correct ending suite summary", func() { summary := fakeR.endSummary Ω(summary.SuiteDescription).Should(Equal("collection description")) Ω(summary.SuiteSucceeded).Should(BeTrue()) Ω(summary.NumberOfExamplesBeforeParallelization).Should(Equal(3)) Ω(summary.NumberOfTotalExamples).Should(Equal(2)) Ω(summary.NumberOfExamplesThatWillBeRun).Should(Equal(2)) Ω(summary.NumberOfPendingExamples).Should(Equal(0)) Ω(summary.NumberOfSkippedExamples).Should(Equal(0)) Ω(summary.NumberOfPassedExamples).Should(Equal(2)) Ω(summary.NumberOfFailedExamples).Should(Equal(0)) Ω(summary.RunTime.Seconds()).Should(BeNumerically("~", 3*0.001, 0.01)) }) }) }) Describe("measurements", func() { exampleWithMeasure := func(text string) *example { return newExample(newMeasureNode(text, func(b Benchmarker) { examplesThatWereRun = append(examplesThatWereRun, text) }, flagTypeNone, types.GenerateCodeLocation(0), 1)) } var conf config.GinkgoConfigType BeforeEach(func() { conf = config.GinkgoConfigType{} }) JustBeforeEach(func() { collection = newExampleCollection(fakeT, "collection description", []*example{ exampleWithItFunc("C", flagTypeNone, false), exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), exampleWithMeasure("measure"), }, []Reporter{fakeR}, conf) collection.run() }) It("runs the measurement", func() { Ω(examplesThatWereRun).Should(ContainElement("A")) Ω(examplesThatWereRun).Should(ContainElement("measure")) }) Context("when instructed to skip measurements", func() { BeforeEach(func() { conf = config.GinkgoConfigType{ SkipMeasurements: true, } }) It("skips the measurements", func() { Ω(examplesThatWereRun).Should(ContainElement("A")) Ω(examplesThatWereRun).ShouldNot(ContainElement("measure")) }) }) }) }) }
func init() { Describe("Container Node", func() { var ( codeLocation types.CodeLocation container *containerNode ) BeforeEach(func() { codeLocation = types.GenerateCodeLocation(0) container = newContainerNode("description text", flagTypeFocused, codeLocation) }) Describe("creating a container node", func() { It("stores off the passed in properties", func() { Ω(container.text).Should(Equal("description text")) Ω(container.flag).Should(Equal(flagTypeFocused)) Ω(container.codeLocation).Should(Equal(codeLocation)) }) }) Describe("appending", func() { Describe("it nodes", func() { Context("appending nodes", func() { var itA, itB *itNode var subContainer *containerNode BeforeEach(func() { itA = newItNode("itA", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itB = newItNode("itB", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) subContainer = newContainerNode("subcontainer", flagTypeNone, types.GenerateCodeLocation(0)) container.pushSubjectNode(itA) container.pushContainerNode(subContainer) container.pushSubjectNode(itB) }) It("can append container nodes and it nodes", func() { Ω(container.subjectAndContainerNodes).Should(Equal([]node{ itA, subContainer, itB, })) }) It("will append only subject nodes to subjects list", func() { Ω(container.subjects).Should(Equal([]exampleSubject{ itA, itB, })) }) It("will signal container that subjects have run", func() { bex := newExample(itB) bex.addContainerNode(container) bex.runSample(1) Ω(container.subjectRunCount).Should(BeNumerically("==", 1)) }) Describe("run once containers", func() { var bex, aex *example BeforeEach(func() { bex = newExample(itB) bex.addContainerNode(container) aex = newExample(itA) aex.addContainerNode(container) }) Context("BeforeAll is specified", func() { var beforeAllRun = false BeforeEach(func() { beforeAllRun = false container.pushBeforeAllNode( newRunnableNode(func() { beforeAllRun = true }, types.GenerateCodeLocation(1), 6*time.Second), ) }) It("beforeAll runs when first contained element is run", func() { bex.runSample(1) Ω(beforeAllRun).Should(BeTrue()) }) It("beforeAll runs only 1 time even if 2 subjects run", func() { bex.runSample(1) Ω(beforeAllRun).Should(BeTrue()) beforeAllRun = false aex.runSample(1) Ω(beforeAllRun).Should(BeFalse()) }) }) Context("AfterAll is specified", func() { var afterAllRun = false BeforeEach(func() { afterAllRun = false container.pushAfterAllNode( newRunnableNode(func() { afterAllRun = true }, types.GenerateCodeLocation(1), 6*time.Second), ) }) It("afterAll runs if both containers run", func() { bex.runSample(1) Ω(afterAllRun).Should(BeFalse()) aex.runSample(1) Ω(afterAllRun).Should(BeTrue()) }) It("afterAll runs if subject panics", func() { panicking := &panickySubject{} container.pushSubjectNode(panicking) bex.runSample(1) Ω(afterAllRun).Should(BeFalse()) aex.runSample(1) pex := newExample(panicking) pex.addContainerNode(container) defer func() { if r := recover(); r != nil { if !Ω(afterAllRun).Should(BeTrue()) { panic(r) } } }() pex.runSample(1) }) }) }) }) }) Describe("other runnable nodes", func() { var ( runnableA *runnableNode runnableB *runnableNode ) BeforeEach(func() { runnableA = newRunnableNode(func() {}, types.GenerateCodeLocation(0), 0) runnableB = newRunnableNode(func() {}, types.GenerateCodeLocation(0), 0) }) It("can append multiple beforeEach nodes", func() { container.pushBeforeEachNode(runnableA) container.pushBeforeEachNode(runnableB) Ω(container.beforeEachNodes).Should(Equal([]*runnableNode{ runnableA, runnableB, })) }) It("can append multiple justBeforeEach nodes", func() { container.pushJustBeforeEachNode(runnableA) container.pushJustBeforeEachNode(runnableB) Ω(container.justBeforeEachNodes).Should(Equal([]*runnableNode{ runnableA, runnableB, })) }) It("can append multiple afterEach nodes", func() { container.pushAfterEachNode(runnableA) container.pushAfterEachNode(runnableB) Ω(container.afterEachNodes).Should(Equal([]*runnableNode{ runnableA, runnableB, })) }) }) }) Describe("generating examples", func() { var ( itA *itNode itB *itNode subContainer *containerNode subItA *itNode subItB *itNode ) BeforeEach(func() { itA = newItNode("itA", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itB = newItNode("itB", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) subContainer = newContainerNode("subcontainer", flagTypeNone, types.GenerateCodeLocation(0)) subItA = newItNode("subItA", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) subItB = newItNode("subItB", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) container.pushSubjectNode(itA) container.pushContainerNode(subContainer) container.pushSubjectNode(itB) subContainer.pushSubjectNode(subItA) subContainer.pushSubjectNode(subItB) }) It("generates an example for each It in the hierarchy", func() { examples := container.generateExamples() Ω(examples).Should(HaveLen(4)) Ω(examples[0].subject).Should(Equal(itA)) Ω(examples[0].containers).Should(Equal([]*containerNode{container})) Ω(examples[1].subject).Should(Equal(subItA)) Ω(examples[1].containers).Should(Equal([]*containerNode{container, subContainer})) Ω(examples[2].subject).Should(Equal(subItB)) Ω(examples[2].containers).Should(Equal([]*containerNode{container, subContainer})) Ω(examples[3].subject).Should(Equal(itB)) Ω(examples[3].containers).Should(Equal([]*containerNode{container})) }) It("ignores containers in the hierarchy that are empty", func() { emptyContainer := newContainerNode("empty container", flagTypeNone, types.GenerateCodeLocation(0)) emptyContainer.pushBeforeEachNode(newRunnableNode(func() {}, types.GenerateCodeLocation(0), 0)) container.pushContainerNode(emptyContainer) examples := container.generateExamples() Ω(examples).Should(HaveLen(4)) }) }) Describe("shuffling the container", func() { texts := func(container *containerNode) []string { texts := make([]string, 0) for _, node := range container.subjectAndContainerNodes { texts = append(texts, node.getText()) } return texts } BeforeEach(func() { itA := newItNode("Banana", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itB := newItNode("Apple", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itC := newItNode("Orange", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) containerA := newContainerNode("Cucumber", flagTypeNone, types.GenerateCodeLocation(0)) containerB := newContainerNode("Airplane", flagTypeNone, types.GenerateCodeLocation(0)) container.pushSubjectNode(itA) container.pushContainerNode(containerA) container.pushSubjectNode(itB) container.pushContainerNode(containerB) container.pushSubjectNode(itC) }) It("should be sortable", func() { sort.Sort(container) Ω(texts(container)).Should(Equal([]string{"Airplane", "Apple", "Banana", "Cucumber", "Orange"})) }) It("shuffles all the examples after sorting them", func() { container.shuffle(rand.New(rand.NewSource(17))) expectedOrder := shuffleStrings([]string{"Airplane", "Apple", "Banana", "Cucumber", "Orange"}, 17) Ω(texts(container)).Should(Equal(expectedOrder), "The permutation should be the same across test runs") }) }) }) }
{types.ExampleStateFailed, "Failure"}, {types.ExampleStateTimedOut, "Timeout"}, {types.ExampleStatePanicked, "Panic"}, } for _, exampleStateCase := range exampleStateCases { exampleStateCase := exampleStateCase Describe("a failing test", func() { var example *types.ExampleSummary BeforeEach(func() { example = &types.ExampleSummary{ ComponentTexts: []string{"[Top Level]", "A", "B", "C"}, State: exampleStateCase.state, RunTime: 5 * time.Second, Failure: types.ExampleFailure{ ComponentCodeLocation: types.GenerateCodeLocation(0), Message: "I failed", }, } reporter.ExampleWillRun(example) reporter.ExampleDidComplete(example) reporter.SpecSuiteDidEnd(&types.SuiteSummary{ NumberOfExamplesThatWillBeRun: 1, NumberOfFailedExamples: 1, RunTime: 10 * time.Second, }) }) It("should record test as failing", func() { actual := buffer.String()
//You can focus individual Measures using FMeasure func FMeasure(text string, body func(Benchmarker), samples int) bool { globalSuite.pushMeasureNode(text, body, flagTypeFocused, types.GenerateCodeLocation(1), samples) return true }
func init() { Describe("MeasureNode", func() { var measure *measureNode var i int var codeLocation types.CodeLocation BeforeEach(func() { i = 0 codeLocation = types.GenerateCodeLocation(0) measure = newMeasureNode("foo", func(b Benchmarker) { b.RecordValue("bar", float64(i)) i += 1 }, flagTypeFocused, codeLocation, 10) }) It("should report on itself accurately", func() { Ω(measure.getText()).Should(Equal("foo")) Ω(measure.getFlag()).Should(Equal(flagTypeFocused)) Ω(measure.getCodeLocation()).Should(Equal(codeLocation)) Ω(measure.nodeType()).Should(Equal(nodeTypeMeasure)) Ω(measure.samples).Should(Equal(10)) }) Context("when run", func() { It("should provide the body function with a benchmarker and be able to aggregate reports", func() { measure.run() measure.run() measure.run() measure.run() report := measure.measurementsReport() Ω(report).Should(HaveLen(1)) Ω(report["bar"].Name).Should(Equal("bar")) Ω(report["bar"].Results).Should(Equal([]float64{0, 1, 2, 3})) }) }) Context("when run, and the function panics", func() { var ( codeLocation types.CodeLocation outcome runOutcome failure failureData ) BeforeEach(func() { measure = newMeasureNode("foo", func(Benchmarker) { codeLocation = types.GenerateCodeLocation(0) panic("kaboom") }, flagTypeFocused, codeLocation, 10) outcome, failure = measure.run() }) It("should run the function and report a runOutcomePanicked", func() { Ω(outcome).Should(Equal(runOutcomePanicked)) Ω(failure.message).Should(Equal("Test Panicked")) }) It("should include the code location of the panic itself", func() { Ω(failure.codeLocation.FileName).Should(Equal(codeLocation.FileName)) Ω(failure.codeLocation.LineNumber).Should(Equal(codeLocation.LineNumber + 1)) }) It("should include the panic data", func() { Ω(failure.forwardedPanic).Should(Equal("kaboom")) }) }) }) }
func BeforeAll(body interface{}, timeout ...float64) bool { globalSuite.pushBeforeAllNode(body, types.GenerateCodeLocation(1), parseTimeout(timeout...)) return true }
//You can focus individual Its using FIt func FIt(text string, body interface{}, timeout ...float64) bool { globalSuite.pushItNode(text, body, flagTypeFocused, types.GenerateCodeLocation(1), parseTimeout(timeout...)) return true }
//AfterEach blocks are run after It blocks. When multiple AfterEach blocks are defined in nested //Describe and Context blocks the innermost AfterEach blocks are run first. // //Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts //a Done channel func AfterEach(body interface{}, timeout ...float64) bool { globalSuite.pushAfterEachNode(body, types.GenerateCodeLocation(1), parseTimeout(timeout...)) return true }
//You can mark Maeasurements as pending using XMeasure func XMeasure(text string, _ ...interface{}) bool { globalSuite.pushMeasureNode(text, func(b Benchmarker) {}, flagTypePending, types.GenerateCodeLocation(1), 0) return true }
//You can focus the tests within a describe block using FDescribe func FDescribe(text string, body func()) bool { globalSuite.pushContainerNode(text, body, flagTypeFocused, types.GenerateCodeLocation(1)) return true }
//You can mark the tests within a describe block as pending using XContext func XContext(text string, body func()) bool { globalSuite.pushContainerNode(text, body, flagTypePending, types.GenerateCodeLocation(1)) return true }
func init() { Describe("Container Node", func() { var ( codeLocation types.CodeLocation container *containerNode ) BeforeEach(func() { codeLocation = types.GenerateCodeLocation(0) container = newContainerNode("description text", flagTypeFocused, codeLocation) }) Describe("creating a container node", func() { It("stores off the passed in properties", func() { Ω(container.text).Should(Equal("description text")) Ω(container.flag).Should(Equal(flagTypeFocused)) Ω(container.codeLocation).Should(Equal(codeLocation)) }) }) Describe("appending", func() { Describe("it nodes", func() { It("can append container nodes and it nodes", func() { itA := newItNode("itA", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itB := newItNode("itB", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) subContainer := newContainerNode("subcontainer", flagTypeNone, types.GenerateCodeLocation(0)) container.pushSubjectNode(itA) container.pushContainerNode(subContainer) container.pushSubjectNode(itB) Ω(container.subjectAndContainerNodes).Should(Equal([]node{ itA, subContainer, itB, })) }) }) Describe("other runnable nodes", func() { var ( runnableA *runnableNode runnableB *runnableNode ) BeforeEach(func() { runnableA = newRunnableNode(func() {}, types.GenerateCodeLocation(0), 0) runnableB = newRunnableNode(func() {}, types.GenerateCodeLocation(0), 0) }) It("can append multiple beforeEach nodes", func() { container.pushBeforeEachNode(runnableA) container.pushBeforeEachNode(runnableB) Ω(container.beforeEachNodes).Should(Equal([]*runnableNode{ runnableA, runnableB, })) }) It("can append multiple justBeforeEach nodes", func() { container.pushJustBeforeEachNode(runnableA) container.pushJustBeforeEachNode(runnableB) Ω(container.justBeforeEachNodes).Should(Equal([]*runnableNode{ runnableA, runnableB, })) }) It("can append multiple afterEach nodes", func() { container.pushAfterEachNode(runnableA) container.pushAfterEachNode(runnableB) Ω(container.afterEachNodes).Should(Equal([]*runnableNode{ runnableA, runnableB, })) }) }) }) Describe("generating examples", func() { var ( itA *itNode itB *itNode subContainer *containerNode subItA *itNode subItB *itNode ) BeforeEach(func() { itA = newItNode("itA", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itB = newItNode("itB", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) subContainer = newContainerNode("subcontainer", flagTypeNone, types.GenerateCodeLocation(0)) subItA = newItNode("subItA", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) subItB = newItNode("subItB", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) container.pushSubjectNode(itA) container.pushContainerNode(subContainer) container.pushSubjectNode(itB) subContainer.pushSubjectNode(subItA) subContainer.pushSubjectNode(subItB) }) It("generates an example for each It in the hierarchy", func() { examples := container.generateExamples() Ω(examples).Should(HaveLen(4)) Ω(examples[0].subject).Should(Equal(itA)) Ω(examples[0].containers).Should(Equal([]*containerNode{container})) Ω(examples[1].subject).Should(Equal(subItA)) Ω(examples[1].containers).Should(Equal([]*containerNode{container, subContainer})) Ω(examples[2].subject).Should(Equal(subItB)) Ω(examples[2].containers).Should(Equal([]*containerNode{container, subContainer})) Ω(examples[3].subject).Should(Equal(itB)) Ω(examples[3].containers).Should(Equal([]*containerNode{container})) }) It("ignores containers in the hierarchy that are empty", func() { emptyContainer := newContainerNode("empty container", flagTypeNone, types.GenerateCodeLocation(0)) emptyContainer.pushBeforeEachNode(newRunnableNode(func() {}, types.GenerateCodeLocation(0), 0)) container.pushContainerNode(emptyContainer) examples := container.generateExamples() Ω(examples).Should(HaveLen(4)) }) }) Describe("shuffling the container", func() { texts := func(container *containerNode) []string { texts := make([]string, 0) for _, node := range container.subjectAndContainerNodes { texts = append(texts, node.getText()) } return texts } BeforeEach(func() { itA := newItNode("Banana", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itB := newItNode("Apple", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) itC := newItNode("Orange", func() {}, flagTypeNone, types.GenerateCodeLocation(0), 0) containerA := newContainerNode("Cucumber", flagTypeNone, types.GenerateCodeLocation(0)) containerB := newContainerNode("Airplane", flagTypeNone, types.GenerateCodeLocation(0)) container.pushSubjectNode(itA) container.pushContainerNode(containerA) container.pushSubjectNode(itB) container.pushContainerNode(containerB) container.pushSubjectNode(itC) }) It("should be sortable", func() { sort.Sort(container) Ω(texts(container)).Should(Equal([]string{"Airplane", "Apple", "Banana", "Cucumber", "Orange"})) }) It("shuffles all the examples after sorting them", func() { container.shuffle(rand.New(rand.NewSource(17))) expectedOrder := shuffleStrings([]string{"Airplane", "Apple", "Banana", "Cucumber", "Orange"}, 17) Ω(texts(container)).Should(Equal(expectedOrder), "The permutation should be the same across test runs") }) }) }) }
//You can mark Its as pending using XIt func XIt(text string, _ ...interface{}) bool { globalSuite.pushItNode(text, func() {}, flagTypePending, types.GenerateCodeLocation(1), 0) return true }