Testing in Go : Some tools you can use

Testing in Go : Some tools you can use

Today I want to write about some tools I’ve found helpful to use when testing in Go. Unit testing is an important part of writing principled Go programs. Package testing provides support for automated testing of Go packages. It is intended to be used in concert with the "go test" command, which automates execution of any function of the form

I’ve been working with the Go programming language for almost a year now. As someone who comes from the Javascript world, there have been things I’ve found easier, others that I’ve found harder, and some others have just been interesting.

Unit testing in Go is one of those things I’ve found interesting (and sometimes quite hard too). With Javascript, I could just mock almost everything using Jest. But because Go is a strictly typed language, that was no longer an option. It took me a while to figure some things out.

Today I want to write about some tools I’ve found helpful to use when testing in Go. Some of them are very popular with the Golang community, but some others not so much. Bear in mind that I’m still not an expert with this language. So take everything that I write here with a grain of salt. Let’s begin!

A basic knowledge of the Go language is required for understanding this article.

The Go Standard Library

The first tool I want to talk about is the one you get out of the box. The Testing package comes with all the core capabilities required for setting up your testing suite.

In order to use it, first, you have to create a file with a _test suffix. Let’s see this through an example.

Let’s suppose we have the following function in a util.go file:

package util

// IsEven determines whether or not a number is even
func IsEven(number int) bool {
    if number%2 == 0 {
        return true
    }

    return false
}

This function is quite easy to understand. It will return true or false whether the input value is even or not. This function is also within a package called utilso that it can be exported easily to any part of our project.

The next step is to create a util_test.go file, which will contain all of our test functions and cases. A good rule of thumb is trying to keep one test file per Go file (that contains functionality), making it easier to identify where the test cases of any given function are located. Initially, our util_test.go file would have the following content:

package util

import "testing"

func Test_IsEven(t *testing.T) {
    // Your test here
}

As you can see, we’re already importing the testing package. The t argument is a Go struct that we’re going to use to run all of our tests and assertions, as well as reporting any errors found. In addition to that, any test should start with the word “Test,”, otherwise, the test runner will not recognize that function as a Test. As a personal convention, I like to name my test functions in the form of Test_<Function_Name> so that it’s easy for me to identify which test belongs to which function.

So far this test function is doing pretty much nothing. So how do we define our tests? If you have already taken some Go tutorials, you’ve probably stumbled upon the following design pattern:

package util

import (
    "testing"
)

func Test_IsEven(t *testing.T) {

    tests := []struct {
        name   string
        number int
        want   bool
    }{
        {"Even number", 4, true},
        {"Odd number", 3, false},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := IsEven(tt.number); got != tt.want {
                t.Errorf("IsEven() = %v, want %v", got, tt.want)
            }
        })
    }
}

With this approach, all test cases are being defined using the tests slice. Each test consists of a string name , an input argument (number) and the expected return value ( want ). Then we proceed to iterate over this slice by using the t.Run method, which will run every test case. Finally, we use if-statements to perform our intended assertions and the t.Errorf method to report any error found.

Honestly, I dislike the previous approach. It’s too verbose, difficult to read and it doesn’t work well when you have to include specific test cases that don’t follow a given pattern. The only good thing about this strategy is that you keep your tests in a very DRY form. However, I always prefer to use the following approach:

package util

import (
    "testing"
)

func Test_IsEven(t *testing.T) {
    t.Run("Should return true if an even number is entered", func(t *testing.T) {
        if got := IsEven(4); got != true {
            t.Errorf("Got = %v, expected %v", got, true)
        }
    })

    t.Run("Should return false if an odd number is entered", func(t *testing.T) {
        if got := IsEven(3); got != false {
            t.Errorf("Got = %v, expected %v", got, false)
        }
    })
}

In my humble opinion, the approach above is way cleaner than the previous one. What we lose by violating the DRY rule, we gain in better readability, which in the end I consider more important to have when working with Unit tests. Nevertheless, this is just me. If you prefer the first approach, it’s OK! Go with it.

go golang testing programming developer

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Golang Web Development:Th Best Programming Language in 2020

Golang Web Development is the new trend globally. Get all the details about the Golang development here. Hire Golang Developers.

Golang Tutorial: Learn Go Programming Language for Beginners

An Introduction to the basics of Go programming language. I will try to introduce some of the basic concepts of Go: Variables and Constants; Loops and Conditional Statements; Functions; Structs, arrays, slices, and maps; ...

5 Useful Golang Modules Developers Should Know in 2021

We look into the best Go modules to make working with Go even easier in 2021: Gen, Go Kit, Fuzzy, Etcd and Ginkgo. Go is an incredibly powerful and versatile language for multiple purposes. It’s reliable, fast, and easy to use. Golang has fantastic documentation. Go also is very easy to scale.

Wondering how to upgrade your skills in the pandemic? Here's a simple way you can do it.

Corona Virus Pandemic has brought the world to a standstill. Countries are on a major lockdown. Schools, colleges, theatres, gym, clubs, and all other public

4 Useful Go Tools That Every Web Developer Should Know

We’ll look at 4 of the most useful tools that provide a better development experience when coding in Go: go vet; gofmt; GoDoc; go get