DEV Community

Cover image for Go Test with Testify: Most Simple Way to Implement Unit Test
Nightsilver Academy
Nightsilver Academy

Posted on • Edited on

Go Test with Testify: Most Simple Way to Implement Unit Test

Preamble

Unit test is testing specific method using several test cases, that performed by the developer who create the method, to prove the method running as expected.


Preparation

Let’s say we have a method that generate OTP code that we can specify the length of the generated OTP code, and we want to test it, in this story I’ll using testify for assertion toolkit. Please take a look this library Testify Go.


Coding Time

OTP Generator Code

package generator

import (
    "crypto/rand"
    "errors"
    "fmt"
)

func OTP(length int) (string, error) {
    const otpChars = "1234567890"
    if length < 1 {
        return "", errors.New("can't generate code with less than 1")
    }
    buffer := make([]byte, length)
    _, err := rand.Read(buffer)
    if err != nil {
        return "", fmt.Errorf("OTP generator error : %+v", err)
    }
    otpCharsLength := len(otpChars)
    for i := 0; i < length; i++ {
        buffer[i] = otpChars[int(buffer[i])%otpCharsLength]
    }
    return string(buffer), nil
}
Enter fullscreen mode Exit fullscreen mode

Let's Test it!

In golang test file should be inside the same package of the function which will be tested, for better understand your OTP generator method is inside otp.go and the test file should be otp_test.go, here is the sample structure of file.
File Structure

Unit Testing Code for OTP Generator Code

package generator

import (
    "github.com/stretchr/testify/suite"
    "testing"
)

// otpTestSuite embedding suite.Suite of testify
type otpTestSuite struct {
    suite.Suite
}

// TestOTPTestSuite initialize test suite
func TestOTPTestSuite(t *testing.T) {
    suite.Run(t, new(otpTestSuite))
}

// TestOTP testing OTP() function using several test cases
func (s *otpTestSuite) TestOTP() {

    // make test cases
    tests := []struct {
        TestCaseName string
        Length       int
        WantError    bool
    }{
        {
            TestCaseName: "Test case generate otp with 6 digit and no error",
            Length:       6,
            WantError:    false,
        },
        {
            TestCaseName: "Test case generate otp with 12 digit and no error",
            Length:       12,
            WantError:    false,
        },
        {
            TestCaseName: "Test case generate otp with 0 digit and error",
            Length:       0,
            WantError:    true,
        },
    }

    // scan test cases
    for _, test := range tests {
        s.Run(test.TestCaseName, func() {
            // start test based on test case
            otp, err := OTP(test.Length)
            if test.WantError {
                s.Assert().Error(err)
            } else {
                s.Assert().NoError(err)
            }
            s.Assert().Len(otp, test.Length)
        })
    }

}
Enter fullscreen mode Exit fullscreen mode

Run Through The Go Unit Test Files.

To run go test recursively change your current directory to root of project, then you can runing this command.

go test -v ./...
Enter fullscreen mode Exit fullscreen mode

And the result should look like this.
Running through all Unit Test


Run Through The Go Unit Test Files with Coverage Details.

Still in side the root directory of your project. You can run this command.

go test ./... -coverprofile cover.out
go tool cover -html=cover.out
Enter fullscreen mode Exit fullscreen mode

And automatically open browser and show the detail coverage of the OTP code statements.
Running through all Unit Test with Detail Coverage


Conclusion

So, to sum it up, unit testing in Golang is like having a trusty sidekick for your code. With tools like Testify, you can easily check if your functions are doing what they're supposed to, running tests and checking coverage is as simple as a couple of commands.


My Thanks

Thank you for visiting! This article was originally published on another website. You can find the original source here. I'm excited to bring it over here. I hope you found it useful and enjoyable. Don't hesitate to reach out if you have any questions or feedback. Happy reading!

Top comments (3)

Collapse
 
ccoveille profile image
Christophe Colombier • Edited

Good introduction to testify, I recommend it.

About your article, I barely found people using testify suite, most people uses assert/require package.
So, no TestMain.

Using the suite make it less readable I think.

BTW, I would recommend everyone using testify to use testifylint

This linter is integrated in golangci-lint

Collapse
 
nghtslvr profile image
Nightsilver Academy

Thanks for coming up, I will consider checking testifylint, and its linter, for entire career I just use testify and its test suite, thanks for your advice and recommendation.

Btw can you refers a link if you have, where specifically giving tutors how to use testifylint and golangci-lint?

I know there is a github page, but maybe it could be helping, when reading direct instruction from an article.

Collapse
 
ccoveille profile image
Christophe Colombier

golangci-lint --enable-only testifylint ./... is what you are looking for.

Then about the page/article, you can find the documentation from the golangci-lint github