// Expect is a trivial wrapper of expectation.Alias for GSpec or Go tests. func Expect(fail interface{}, skip ...int) expectation.ExpectFunc { if f, ok := fail.(func(error)); ok { return expectation.Alias(f, skip...) } else if f, ok := fail.(func()); ok { return expectation.Alias(expectation.TFail(f), skip...) } panic("argument fail should be either an expectation.FailFunc or a func()") }
/* Scenario: Attach customized alias name and description for each test group method. Given the S object provided by GSpec When I define a customized name for the test group method And use it to attach a description to the test group Then the alias name and description are combined and passed to the reporter */ func TestDescribeTests(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) r := &ReporterStub{} NewController(r).Start(Path{}, false, func(s S) { describe, context, it := s.Alias("describe"), s.Alias("context"), s.Alias("it") describe("a", func() { context("b", func() { it("c", func() { }) }) }) }) clearGroupForTest(r.group) expect(r.group.Children).Equal(TestGroups{ { Description: "describe a", Children: TestGroups{ { Description: "context b", Children: TestGroups{ {Description: "it c"}, }, }, }, }, }) }
/* Scenario: Plain text progress indicator Given a nested test group with 5 leaves When the tests finished but 3 of test panics Then I should see 2 dots with 3 F: "F.F.F" */ func Test3Pass2Fail(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) var buf bytes.Buffer NewController(NewTextProgresser(&buf)).Start(Path{}, true, func(s S) { g := s.Alias("") g("a", func() { g("a-b", func() { }) g("a-c", func() { g("a-c-d", func() { s.Fail(errors.New("err: a-c-d")) }) }) g("a-e", func() { g("a-e-f", func() { s.Fail(errors.New("err: a-e-f")) }) g("a-e-g", func() { s.Fail(errors.New("123")) }) }) }) g("h", func() { }) }) out, _ := buf.ReadString('\n') expect(out).HasPrefix("^") expect(out).HasSuffix("$\n") out = out[1 : len(out)-2] expect(sortBytes(out)).Equal("..FFF") }
/* Scenario: Traversal over all test cases in the tree of nested test group Given a root TestGroup When the For method is called Then each test case will get visited once */ func TestTestCaseTraversal(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) g := &TestGroup{ Description: "a", Children: TestGroups{ &TestGroup{ Description: "b", Children: TestGroups{ &TestGroup{ Description: "c", }, &TestGroup{ Description: "d", Error: errors.New("err"), }, }, }, &TestGroup{ Description: "e", }, }, } cases := []string{} g.For(func(path TestGroups) bool { s := "" for _, g := range path { s += g.Description if g.Error != nil { s += ":" + g.Error.Error() } } cases = append(cases, s) return true }) expect(cases).Equal([]string{ "abc", "abd:err", "ae", }) cases = []string{} g.For(func(path TestGroups) bool { s := "" hasError := false for _, g := range path { s += g.Description if g.Error != nil { s += ":" + g.Error.Error() hasError = true } } cases = append(cases, s) return !hasError }) expect(cases).Equal([]string{ "abc", "abd:err", }) }
func TestSortingTestGroups(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) g0 := &TestGroup{ID: "0"} g1 := &TestGroup{ID: "1"} g2 := &TestGroup{ID: "2"} group := &TestGroup{Children: TestGroups{g2, g0, g1}} sortTestGroup(group) expect(group.Children).Equal(TestGroups{g0, g1, g2}) }
/* Scenario: reconstruct nested test group to a tree Given a treeCollector When it's groupStart method is called like real tests running Then it is able to reconstruct the tree structure */ func TestTreeCollector(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) co := newCollector(&ReporterStub{}) r := &TestGroup{} a := &TestGroup{ Description: "a", } b := &TestGroup{ Description: "b", } c := &TestGroup{ Description: "c", } d := &TestGroup{ Description: "d", } z := &TestGroup{ Description: "z", } co.groupStart(r, Path{1}) co.groupStart(a, Path{1, 2}) co.groupStart(b, Path{1, 2, 3}) co.groupStart(c, Path{1, 2, 3, 4}) c.Error = errors.New("c err") co.groupStart(r, Path{1}) co.groupStart(a, Path{1, 2}) co.groupStart(b, Path{1, 2, 3}) co.groupStart(d, Path{1, 2, 3, 5}) co.groupStart(r, Path{1}) co.groupStart(z, Path{1, 6}) exp := TestGroups{ &TestGroup{ Description: "a", Children: TestGroups{ &TestGroup{ Description: "b", Children: TestGroups{ &TestGroup{ Description: "c", Error: c.Error, }, &TestGroup{ Description: "d", }, }, }, }, }, &TestGroup{ Description: "z", }, } expect("the root group", co.group).NotEqual(nil) expect(co.group.Children).Equal(exp) //, "TreeCollector fail to reconstruct correct tree" }
func TestNewPanicError(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) e := NewPanicError(errors.New("a"), 0) expect(e.Error()).Equal(errors.New("a")) e = NewPanicError("b", 0) expect(e.Error()).Equal(errors.New("b")) e = NewPanicError(false, 0) expect(e.Error()).Equal(errors.New("false")) }
/* Scenario: test case panics Given a test case When it panics Then the error will be recorded and sent to the reporter */ func TestCasePanics(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) r := &ReporterStub{} NewController(r).Start(Path{}, true, func(s S) { g := aliasGroup(s) g(func() { panic("panic error") }) }) expect(r.group).NotEqual(nil) expect(len(r.group.Children)).Equal(1) expect(r.group.Children[0].Error).Equal(errors.New("panic error")) }
func TestFuncIDString(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) expect(Serial(0).String()).Equal("0") expect(Serial(3).String()).Equal("3") id, err := parseSerial("2") expect(err).Equal(nil) expect(id).Equal(Serial(2)) id, err = parseSerial("XYZ") expect(err).NotEqual(nil) expect(id).Equal(Serial(0)) }
func TestIDStack(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) p := serialStack{} p.push(Serial(1)) p.push(Serial(2)) expect(p.Path).Equal(Path{1, 2}) i := p.pop() expect(p.Path).Equal(Path{1}) expect(i).Equal(Serial(2)) i = p.pop() expect(i).Equal(Serial(1)) expect(p.Path).Equal(Path{}) expect(func() { p.pop() }).Panic() }
/* Scenario: Pending test group Given nested test groups When one of them has no test closure Then a PendingError is set. */ func TestPending(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) r := &ReporterStub{} NewController(r).Start(Path{}, true, func(s S) { g := aliasGroup(s) g(func() { }) g(nil) g(func() { }) }) expect(r.group).NotEqual(nil) expect(len(r.group.Children)).Equal(3) expect(r.group.Children[1].Error).Equal(&ext.PendingError{}) }
func TestPathSerialization(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) var p Path p.Set("0/1/2") expect(len(p)).Equal(3) expect(p[0]).Equal(Serial(0)) expect(p[1]).Equal(Serial(1)) expect(p[2]).Equal(Serial(2)) err := p.Set("UVW") expect(err).NotEqual(nil) p = Path{0, 1, 2} expect(p.String()).Equal("0/1/2") }
func TestGroupStack(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) s := groupStack{} s.push(&TestGroup{Description: "a"}) s.push(&TestGroup{Description: "b"}) expect(s.a).Equal( TestGroups{ {Description: "a"}, {Description: "b"}, }) g := s.pop() expect(s.a).Equal( TestGroups{ {Description: "a"}, }) expect(g).Equal(&TestGroup{Description: "b"}) g = s.pop() expect(g).Equal(&TestGroup{Description: "a"}) expect(s.a).Equal(TestGroups{}) expect(func() { s.pop() }).Panic() }
/* Scenario: FailNow Given the FailNow method of S When it is called with an error object Then the error Will be recorded and sent to the reporter And the defer functions get called And the rest of the test cases continue to run */ func TestFailNow(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) r := &ReporterStub{} ch := NewSS() NewController(r).Start(Path{}, true, func(s S) { g := aliasGroup(s) g(func() { defer func() { ch.Send("defer func") }() ch.Send("before FailNow") s.FailNow(errors.New("err a")) ch.Send("after FailNow") }) g(func() { ch.Send("another test case") }) }) expect(r.group).NotEqual(nil) expect(len(r.group.Children)).Equal(2) expect(r.group.Children[0].Error).Equal(errors.New("err a")) expect(ch.Sorted()).Equal([]string{"another test case", "before FailNow", "defer func"}) }
func TestNewPendingError(t *testing.T) { expect := exp.Alias(exp.TFail(t.FailNow)) e := NewPendingError() expect(e).IsType(&PendingError{}) expect(e.Error()).Contains("pending") }