-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbdd.go
107 lines (88 loc) · 2.43 KB
/
bdd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package mspec
import (
"fmt"
"runtime"
"strings"
"testing"
)
func (spec *Specification) run() {
// execute the Assertion
spec.AssertFn(config.assertFn(spec))
// if there was no error (which handles its own printing),
// print the spec here.
if spec.notImplemented {
spec.PrintSpecNotImplemented()
} else if !spec.AssertionFailed {
spec.PrintSpec()
}
}
// Given defines the Feature's specific context to be spec'd out.
func Given(t *testing.T, given string, when ...func(When)) {
// setup the spec that we will be using
spec := &Specification{
T: t,
Feature: featureDesc(2),
Given: given,
}
spec.PrintFeature()
spec.PrintContext()
for _, whenFn := range when {
whenFn(func(when string, its ...func(It)) {
spec.When = when
spec.PrintWhen()
for _, itFn := range its {
itFn(func(it string, assertFns ...func(Assert)) {
spec.Spec = it
// Spec output is handled in the spec.run() below
if len(assertFns) > 0 {
// having at least 1 assert means we are implemented
for _, assertFn := range assertFns {
spec.AssertFn = assertFn
spec.notImplemented = false
}
} else {
spec.AssertFn = notImplemented()
spec.notImplemented = true
}
// run() handles contextual printing and some delegation
// to the Assert's implementation for error handling
spec.run()
})
}
})
}
// reset to default
config.resetLasts()
if config.output != outputNone {
fmt.Println()
}
}
// When defines the action or event when Given a specific context.
type When func(when string, it ...func(It))
// It defines the specification of When something happens.
type It func(title string, assert ...func(Assert))
// Setup is used to define before/after (setup/teardown) functions.
func Setup(before, after func()) func(fn func(Assert)) func(Assert) {
return func(fn func(Assert)) func(Assert) {
before()
return func(assert Assert) {
fn(assert)
after()
}
}
}
// notImplemented is used to mark a specification that needs coding out.
var notImplemented = func() func(Assert) {
return func(assert Assert) {
// nothing to do here
}
}
var featureDesc = func(callerDepth int) string {
pc, _, _, _ := runtime.Caller(callerDepth)
m := fmt.Sprintf("%s", runtime.FuncForPC(pc).Name())
i := strings.LastIndex(m, ".")
m = m[i+1 : len(m)]
m = strings.Replace(m, "Test_", "", 1)
m = strings.Replace(m, "Test", "", 1)
return strings.Replace(m, "_", " ", -1)
}