Skip to content

Commit 57c2b08

Browse files
committed
how to write tests
1 parent c439c1b commit 57c2b08

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

test/testing.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# How to write tests
2+
3+
1. You can have a separate function for faktory manager setup that you can call in func main(), for e.g.
4+
5+
``` go
6+
func faktoryManagerSetup() error {
7+
// create faktory manager
8+
mgr = worker.NewManager()
9+
10+
// set logger to the app's logger
11+
mgr.Logger = app.Log
12+
13+
// NewPool creates a new Pool object through which multiple clients
14+
// are managed.
15+
pool, err := faktory.NewPool(5)
16+
if err != nil {
17+
return err
18+
}
19+
20+
mgr.Pool = pool
21+
22+
mgr.Use(func(ctx context.Context, job *faktory.Job, next func(ctx context.Context) error) error {
23+
app.Log.Infof("Starting work on job %s of type %s\n", job.Jid, job.Type)
24+
err := next(ctx)
25+
app.Log.Infof("Finished work on job %s with error %v\n", job.Jid, err)
26+
return err
27+
})
28+
29+
// use up to N goroutines to execute jobs
30+
mgr.Concurrency = 20
31+
32+
// pull jobs from these queues, in this order of precedence
33+
mgr.ProcessStrictPriorityQueues("critical", "default", "bulk")
34+
35+
// register a job type and the handler
36+
// jobs will go into the "default" queue
37+
mgr.Register("UpdateWiki", UpdateWikiHandler)
38+
39+
// register another job type
40+
mgr.Register("UpdateReleaseStatus", UpdateReleaseStatusHandler)
41+
42+
return nil
43+
}
44+
45+
```
46+
47+
2. Now, when you are writing a test for a function where you enqueue a faktory job, you can call this function:
48+
49+
``` go
50+
func TestMain(m *testing.M) {
51+
testSetUp()
52+
faktoryManagerSetup()
53+
exitCode := m.Run()
54+
os.Exit(exitCode)
55+
56+
```
57+
58+
3. Table driven testing is a very good way of avoiding duplicate code, and it works really well in this case. Let's take an example:
59+
60+
``` go
61+
var payload []byte
62+
63+
func (suite *FunctionalTestSuite) TestJob_Errors() {
64+
uniqueID := uuid.NewUUID()
65+
testCases := []struct {
66+
name string
67+
hasError bool
68+
expectedError string
69+
jobEnqueued bool
70+
}{
71+
{
72+
"Malformed Payload",
73+
true,
74+
"unable to process payload",
75+
false,
76+
},
77+
{
78+
"Empty Payload",
79+
true,
80+
"empty payload",
81+
false,
82+
},
83+
{
84+
"Empty Metadata",
85+
true,
86+
"empty metadata",
87+
false,
88+
},
89+
}
90+
91+
for _, testCase := range testCases {
92+
fn := func() {
93+
payload = []byte("test payload")
94+
pool, _ := faktory.NewPool(5)
95+
perf := worker.NewTestExecutor(pool)
96+
someJob := faktory.NewJob("UpdateWiki", uniqueID, payload)
97+
98+
// now call the function that actually creates a job in your flow
99+
err = suite.processSomePayload(payload)
100+
101+
if testCase.jobEnqueued && testCase.hasError {
102+
err = perf.Execute(someJob, func(ctx context.Context, args ...interface{}) error {
103+
return fmt.Errorf(testCase.expectedError)
104+
})
105+
suite.require.Error(err)
106+
}
107+
108+
if !testCase.jobEnqueued && testCase.hasError {
109+
err = perf.Execute(someJob, func(ctx context.Context, args ...interface{}) error {
110+
return fmt.Errorf(testCase.expectedError)
111+
})
112+
suite.require.Error(err)
113+
suite.assert.Contains(err.Error(), testCase.expectedError)
114+
} else {
115+
err = perf.Execute(someJob, func(ctx context.Context, args ...interface{}) error {
116+
return nil
117+
})
118+
suite.NoError(err)
119+
}
120+
}
121+
122+
suite.Run(testCase.name, fn)
123+
}
124+
}
125+
126+
```
127+
128+
Another example for testing the handler response:
129+
130+
``` go
131+
func (suite *FunctionalTestSuite) TestJob_Errors() {
132+
uniqueID := uuid.NewUUID()
133+
testCases := []struct {
134+
name string
135+
hasError bool
136+
jobEnqueued bool
137+
}{
138+
{
139+
"Success",
140+
true,
141+
true,
142+
},
143+
}
144+
145+
for _, testCase := range testCases {
146+
fn := func() {
147+
pool, _ := faktory.NewPool(5)
148+
perf := worker.NewTestExecutor(pool)
149+
var i interface{} = []string{uniqueID.String(), "payload"}
150+
jobArgs := []interface{}{i}
151+
someJob := faktory.NewJob("UpdateWiki", jobArgs...)
152+
153+
err = perf.Execute(someJob, UpdateWikiHandler)
154+
suite.require.NotNil(err)
155+
}
156+
157+
suite.Run(testCase.name, fn)
158+
}
159+
}
160+
161+
```

0 commit comments

Comments
 (0)