Golang libs for tests

Ravil Akhtyamov
3 min readSep 21, 2020

--

Go provide built-in functionality to test your Go code. Testing will be even easier and graceful with these libraries.

stretchr/testify provide many tools for testifying

assert provide check equality, check nil, check error, check empty object, check json, check arrays and periodically checking target function.

How to use

func TestAssert(t *testing.T) {   assert.NoError(t, err)//assert not error   assert.Nil(t, err)//assert nil   assert.NotNil(t, user)//assert not nil   assert.Equal(t, 0, userEmpty.ID) //assert equal   assert.NotEqual(t, 100500, userEmpty.ID) //assert not equal   assert.Empty(t, userEmpty) // assert empty   assert.ElementsMatch(t, user.Books, []string{   "The Place in Dalhousie",   "Catch and Kill",   "Kit’s Wilderness",   "Peak",   "The Secret Garden",   }) //item comparison   go func() {      for i := 0; i < 100; i++ {         readed.M.Lock()         readed.Number++         readed.M.Unlock()         time.Sleep(1 * time.Millisecond)      }   }()     assert.Eventually(t, func() bool {      readed.M.Lock()      defer readed.M.Unlock()      if readed.Number > 2 {         return true      }   return false}, 50*time.Millisecond, 1*time.Millisecond) //periodically checking}

require provide the same as assert package, but terminate current test. Also has testing suite as a struct and mock package provides a mechanism for easily writing mock objects.

go-test/deep provide compare fields of objects, map

Functions compares all fields and returns differences.

How to use

func TestDeep(t *testing.T) {    if diff := deep.Equal(user, userEqual); diff != nil {       t.Error(diff)      }    if diff := deep.Equal(user, userNotEqual); diff != nil {      t.Error(diff)   }}

bitly/go-simplejson easy interact with arbitrary JSON

Very useful library not only for tests. Provides access to fields without unmarshaling.

How to use

func TestSimpleJson(t *testing.T) {   var userJson = `{      "id":       123456,      "name":     "Rauf",      "age":      30,      "password": "qwerty123",      "email":    "user@test.ru",      "books": [      "Peak"      ],      "weight": 77.5   }`   js, err := simplejson.NewJson([]byte(userJson))   assert.NoError(t, err)   assert.Equal(t, js.Get("id").MustInt64(), int64(123456))//get id    assert.Equal(t, js.Get("name").MustString(), "Rauf")//get name   arr, err := js.Get("books").Get("array").Array()//get array   assert.NotEqual(t, nil, arr)   for _, v := range arr {      r, ok := v.(string)      require.Equal(t, true, ok)      assert.Equal(t, "Peak", r)   }}

google/gofuzz populating objects with random values

How to use

func TestGoFuzz(t *testing.T) {   f := fuzz.New()   var (      object  User      testInt int    )   f.Fuzz(&object) //populate object   f.Fuzz(&testInt) //generate variable   assert.NotEmpty(t, object)   assert.NotEqual(t, 0, testInt)}

icrowley/fake fake data generator

Provide fake generation of email, ip, phone, password, names, city, country, addressess, coordinates and etc.

How to use

func TestFake(t *testing.T) {   user := &User{}   assert.Empty(t, user)   user.Email = fake.EmailAddress()//fake email   user.Name = fake.MaleFirstName()//fake name   user.Password = fake.Password(9, 9, true, true, true)//password   assert.True(t, govalidator.IsEmail(user.Email))   assert.NotEqual(t, "", user.Name)   assert.NotEqual(t, "", user.Password)}

DATA-DOG/go-sqlmock Sql driver mock

Simulate any sql driver behavior in tests, without needing a real database connection

How to use

//function to be tested
func UserPut(db *sql.DB, id int, name string) error {
if _, err := db.Exec(`
INSERT INTO
users(id, Name)
Values ($1, $2)", id, name); err != nil {
return err } return nil}func TestUserPut(t *testing.T) { db, mock, err := sqlmock.New() require.NoError(t, err) defer db.Close() mock.ExpectExec("INSERT INTO users").
WithArgs(1, "Bond").
WillReturnResult(sqlmock.NewResult(1, 1))
err = UserPut(db, 1, "Bond") require.NoError(t, err) err = mock.ExpectationsWereMet() require.NoError(t, err)}

jarcoal/httpmock easy mock of http responses

Simulate http responses.

How to use

const URL = "https://httpmock.test.com/users"//function to be tested
func getUser() error {
resp, err := http.Get(URL) if err != nil { return err } defer resp.Body.Close() return nil}func TestHttpMock(t *testing.T) { httpmock.Activate() defer httpmock.DeactivateAndReset() httpmock.RegisterResponder("GET", URL, httpmock.NewStringResponder(http.StatusOK, `{"id": 1, "name": "Bond"}`)) err := getUser() assert.NoError(t, err) info := httpmock.GetCallCountInfo() key := "GET" + " " + URL assert.Equal(t, 1, info[key])}

uber-go/goleak goroutine leak detector

A very common error goroutine leak, which is very difficult to identify. uber-go/goleak will help in this.

How to use

//function without leak
func Myfunc() {
go func() { }()}//function with leak
func MyfuncWithLeak() {
go func() { for { } }()}func TestLeak(t *testing.T) { t.Run("not leak", func(t *testing.T) { defer goleak.VerifyNone(t) Myfunc() }) t.Run("leak", func(t *testing.T) { defer goleak.VerifyNone(t) MyfuncWithLeak() })}

--

--

No responses yet