Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a readme for how to write tests #50

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions test/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# How to write tests

1. You can have a separate function for faktory manager setup that you can call in func main(), for e.g.

``` go
func faktoryManagerSetup() error {
// create faktory manager
mgr = worker.NewManager()

// set logger to the app's logger
mgr.Logger = app.Log

// NewPool creates a new Pool object through which multiple clients
// are managed.
pool, err := faktory.NewPool(5)
if err != nil {
return err
}

mgr.Pool = pool

mgr.Use(func(ctx context.Context, job *faktory.Job, next func(ctx context.Context) error) error {
app.Log.Infof("Starting work on job %s of type %s\n", job.Jid, job.Type)
err := next(ctx)
app.Log.Infof("Finished work on job %s with error %v\n", job.Jid, err)
return err
})

// use up to N goroutines to execute jobs
mgr.Concurrency = 20

// pull jobs from these queues, in this order of precedence
mgr.ProcessStrictPriorityQueues("critical", "default", "bulk")

// register a job type and the handler
// jobs will go into the "default" queue
mgr.Register("UpdateWiki", UpdateWikiHandler)

// register another job type
mgr.Register("UpdateReleaseStatus", UpdateReleaseStatusHandler)

return nil
}

```

2. Now, when you are writing a test for a function where you enqueue a faktory job, you can call this function:

``` go
func TestMain(m *testing.M) {
testSetUp()
faktoryManagerSetup()
exitCode := m.Run()
os.Exit(exitCode)

```

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:

``` go
var payload []byte

func (suite *FunctionalTestSuite) TestJob_Errors() {
uniqueID := uuid.NewUUID()
testCases := []struct {
name string
hasError bool
expectedError string
jobEnqueued bool
}{
{
"Malformed Payload",
true,
"unable to process payload",
false,
},
{
"Empty Payload",
true,
"empty payload",
false,
},
{
"Empty Metadata",
true,
"empty metadata",
false,
},
}

for _, testCase := range testCases {
fn := func() {
payload = []byte("test payload")
pool, _ := faktory.NewPool(5)
perf := worker.NewTestExecutor(pool)
someJob := faktory.NewJob("UpdateWiki", uniqueID, payload)

// now call the function that actually creates a job in your flow
err = suite.processSomePayload(payload)

if testCase.jobEnqueued && testCase.hasError {
err = perf.Execute(someJob, func(ctx context.Context, args ...interface{}) error {
return fmt.Errorf(testCase.expectedError)
})
suite.require.Error(err)
}

if !testCase.jobEnqueued && testCase.hasError {
err = perf.Execute(someJob, func(ctx context.Context, args ...interface{}) error {
return fmt.Errorf(testCase.expectedError)
})
suite.require.Error(err)
suite.assert.Contains(err.Error(), testCase.expectedError)
} else {
err = perf.Execute(someJob, func(ctx context.Context, args ...interface{}) error {
return nil
})
suite.NoError(err)
}
}

suite.Run(testCase.name, fn)
}
}

```

Another example for testing the handler response:

``` go
func (suite *FunctionalTestSuite) TestJob_Errors() {
uniqueID := uuid.NewUUID()
testCases := []struct {
name string
hasError bool
jobEnqueued bool
}{
{
"Success",
true,
true,
},
}

for _, testCase := range testCases {
fn := func() {
pool, _ := faktory.NewPool(5)
perf := worker.NewTestExecutor(pool)
var i interface{} = []string{uniqueID.String(), "payload"}
jobArgs := []interface{}{i}
someJob := faktory.NewJob("UpdateWiki", jobArgs...)

err = perf.Execute(someJob, UpdateWikiHandler)
suite.require.NotNil(err)
}

suite.Run(testCase.name, fn)
}
}

```