Creating Your Own BeforeEach in Go

I'm developing my own budgeting app using Go and have been using it to learn new things as well. For testing, because I'm TDD'ing the entire project, I decided to just use the built-in Go testing framework. I use Ginkgo at work and enjoy it, but decided to see what vanilla testing in Go is like.

After writing a bunch of tests for a lot of my boilerplate functions, I quickly had a lot of duplicated set-up code that looked like this at the start of all my tests:

g := NewGomegaWithT(t)

db, err := createTestDb()
g.Expect(err).To(BeNil(), ErrorDidNotOccur)

api := NewApi(db, SelectedQueryLang)

I was having trouble figuring out how to pull this out into it's own function. Finally I saw a Stack Overflow answer that provided me with a solution.

Here's how you create your own BeforeEach() function when using Go's testing framework.

First, create a struct that will hold the objects your test needs to access. Mine looks like this:

type TestingBasics struct {
    GoMega *GomegaWithT
    Db     *sql.DB
    Api    *api
}

Then create your BeforeEach() function that will create this struct for your tests.

func BeforeEach(t *testing.T, SelectedQueryLang *QueryLang) (tb TestingBasics) {
    tb.GoMega = NewGomegaWithT(t)

    var err error
    tb.Db, err = createTestDb()
    tb.GoMega.Expect(err).To(BeNil(), ErrorDidNotOccur)

    tb.Api = NewApi(tb.Db, SelectedQueryLang)

    return tb
}

Now all you need to do is call BeforeEach() at the beginning of your tests. I was able to reduce 4 lines of code down to 1 across all of my tests. Now the start of each of my tests look like this:

t.Run("should add one transaction", func(t *testing.T) {
    tb := BeforeEach(t, SelectedQueryLang)
...

This can definitely be cleaned up even further, to the point where I wouldn't even need to call BeforeEach() at the start of each test. At that point though, I might as well have gone with Ginkgo. For me and this project, I am fine with this set up.

Posted by Taylor