golang

Golang Assert

There are three principal components in a developer’s lifecycle: write code, test code, fix the code, repeat. Although it is an extreme oversimplification, it illustrates a concept that all developers encounter.

In this article, we will focus on a single entity of a developer’s lifecycle: testing. Testing code is a very useful feature for any developer. It allows finding and fixing of bugs before deploying code to production. Although there are lots of ways and features to implement code testing, this article will focus on the Go assert package.

Getting Started with Testing

Before we dive into how to work with the testify package, let us learn how to get started with go testing.

The first step is to know what you want to test. This could be a simple function to a collection of methods.

Let us take a simple example program that just multiplies it’s input by 10.

Start by creating a directory to store your code.

mkidr testing

Navigate into the directory and create a go file containing your program. For simplicity, we will call this file main.go

cd testing

touch main.go

Edit the file with your text editor and create your program. To follow along with this tutorial, you can add the code as shown below:

package main
import (
    "fmt"
)

funcmultiply(x int) (result int) {
    result = x * 10
    return result
}
funcmain() {
    fmt.Println("getting started with testing")
}

In the example program, we have a function that takes an integer input and returns the integer multiplied by 10.

Save and close the file.

The next step is to create test for the program above. To do this, we need to create a file in the same directory with the _test suffix. This tells the Go testing module that this file contains a test suite for the program in the directory.

Since we want to create a test for the main.go program, we will call the testing file as:

touch main_test.go

In the test file, we can create test instructions for our program.

Since we want to use the use the assert package, we need to import the testing and the assert package.

You can include the imports as:

package
import (
  "testing"
  "github.com/stretchr/testify/assert"
)

Next, create a testing function to test for the main program. We can create test instructions as shown:

package main
import (
    "testing"

    "github.com/stretchr/testify/assert"
)
funcTestMultiply(t *testing.T) {
    assert.Equal(t, multiply(10), 100)
}

In the above program, we create a test function that takes a testing.T object. The testing framework allows the function to write fails to the appropriate location provided this object.

Inside the function, we use the assert package to check if the function returns a result equal to the provided parameters. If the multiply function takes the integer 10 and returns a value equal to 100, then it passes the test.

Save the test file and run the test using the command:

go test

The above command should take the test file and run the configured tests.

An example output is as shown:

=== RUN TestMultiply

--- PASS: TestMultiply (0.00s)

PASS

ok linuxhint/go-assert

> Test run finished at 1/31/2022, 1:38:17 PM <

As you will notice from the above output, the function passes the test.

Let us change the value of the function to illustrate a fail instruction. For example, change the third parameter of the test function to an incorrect value. For example:

funcTestMultiply(t *testing.T) {
    assert.Equal(t, multiply(10), 10)
}

In this example, we are telling the program that if the function does not return 10, then the function fails.

NOTE: Keep in mind that the testing function is incorrect.

If we run the test, we should get a fail as:

=== RUN TestMultiply

assert\main_test.go:10:

Error Trace:

Error: Not equal:

expected: 100

actual : 10

Test: TestMultiply

--- FAIL: TestMultiply (0.00s)

FAIL

FAIL linuxhint/go-assert 0.040s

> Test run finished at 1/31/2022, 1:40:59 PM <

The above output illustrates a failed test.

Golang Assert

Now that we have the basics of testing out of the way, let us shift our focus to the assert package. In our previous example, we used the equal method to check if the function returns the expected value. However, the assert package provides a plethora of testing tools and methods to make code testing easier.

Let us explore a few more examples to illustrate the functionality of the assert package.

Golang Test Inequality

We can use the assert package to check for inequality using the NotEqual() method. The function syntax is as shown:

func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs …interface{}) bool

The function takes a t.testing object, the expected and the actual value and a print message. It checks if the expected and actual value are not equal. If true, the test passes, otherwise, fail.

An example is as shown:

funcTestNotEqual(t *testing.T) {
    assert.NotEqual(t, 100, 10, "values should not be equal")
}

The code above checks if the values are not equal. An example output is as shown:

=== RUN TestNotEqual

--- PASS: TestNotEqual (0.00s)

PASS

ok linuxhint/go-assert 0.037s

Golang Test HTTP Status Code

We can use the HTTPStatusCode() method to check if a handler returns the specified status code.

Let us assume we have a HTTP server, that if we make a request to returns status code of 200. We will not dive deep into how to create a HTTP server in Go. Check out our tutorial on the topic to learn more.

An example HTTP Server is as shown:

package main
import (
    "io"
    "net/http"
)
var mux map[string]func(http.ResponseWriter, *http.Request)

funcmain() {
    server := http.Server{
        Addr:    ":8080",
        Handler: &myHandler{},
    }
    mux = make(map[string]func(http.ResponseWriter, *http.Request))
    mux["/"] = sayHello

    server.ListenAndServe()
}

typemyHandlerstruct{}

func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if h, ok := mux[r.URL.String()]; ok {
        h(w, r)
        return
    }
    io.WriteString(w, "Server running: "+r.URL.String())
}
funcsayHello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "Hi!")
}

We can create a test to check if whether the http handler function returns the specified status code. In our case, the http handler function is the sayHello method. The test function is as shown:

func TestStatusCode(t *testing.T) {

assert.HTTPStatusCode(t, sayHello, "GET", "/", nil, 200)

}

In the example above, we create a test function to check sending a GET request to the server with the HTTP Handler function sayHello, returns the status code of 200.

The code returns:

=== RUN TestStatusCode

--- PASS: TestStatusCode (0.00s)

PASS

ok linuxhint/go-assert 0.034s

> Test run finished at 1/31/2022, 2:44:39 PM <

Golang Test Panic

Another test we can run is to check if a specific function panics. We can use the assert.Panicks() method as shown:

funcTestPanic(t *testing.T) {
    assert.Panics(t, func() {
        panic("I definitely panic!")
    }, "Should panic")
}

In the example above, we check if the function if it panics.

Golang Check if Directory Exists

If you want to test whether a specific directory exists within a specified path, you can use the DirExists() method.

For example:

funcTestDir(t *testing.T) {
    assert.DirExists(t, "../assert")
}

Conclusion

This was a comprehensive guide on how to get started with testing in the Go programming language. Testing is heavily used in multi-developer projects. Hence, learning how to perform tests is exceptional.

There is a lot more provided by the assert package than ones shown in this tutorial. The documentation expands on this.

https://pkg.go.dev/github.com/stretchr/testify/assert

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list