Golangのtestify/assert 使えそうな関数まとめ

# Introduction
最近Echoでサーバーを書く機会があった。
テストコードを書きたかった。
[Echo Document Testing](https://echo.labstack.com/guide/testing)を見てみると

~~~golang
import (
	"net/http" //<- わかる
	"net/http/httptest" //<- わかる
	"strings" //<- わかる
	"testing" //<- 超わかる

	"github.com/labstack/echo" //<- わかる
	"github.com/stretchr/testify/assert" //<-なにこれ????
)
~~~

`github.com/stretchr/testify/assert`とか言うのかimportされていた

もう少し見てみると

~~~go
func TestCreateUser(t *testing.T) {
	// Setup
	e := echo.New()
	req := httptest.NewRequest(echo.POST, "/", strings.NewReader(userJSON))
	req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)
	h := &handler{mockDB}

	// Assertions
	if assert.NoError(t, h.createUser(c)) {
		assert.Equal(t, http.StatusCreated, rec.Code)
		assert.Equal(t, userJSON, rec.Body.String())
	}
}
~~~

「なるほど。 `assert`はRubyの`validation`的な立ち位置か。公式[README](https://godoc.org/github.com/stretchr/testify/assert)読み行こ。」

「日本語版ないな」「和訳されたやつないかな」

`Google[testify assert][Search]`

「うんないな。書こう」

そんな経緯です、。ゆるく検証していきます

## 環境
go 1.9
assert 1.2.1

記載されている結果はすべて上記の環境により実行しております

# 比較

## [func ElementsMatch](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L778)(リストの比較)

~~~golang
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool)
~~~
ElementMatchはlistA(array, slice...) とlistB(array, slice...)の要素が一致しているか判定します **(順序は問わない)**

~~~golang
assert.ElementMatch(t, [...]int{1,2}, [...]int{1, 2} ) //-> Success

assert.ElementMatch(t, [...]int{1,2}, [...]int{2, 1} ) //-> Success

assert.ElementMatch(t, [...]int{1,2}, [...]int{1} ) //-> Failed

assert.ElementMatch(t, [...]int{1,2}, [...]int{1, 3} ) //-> Failed


~~~

## [func Equal](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L326)(比較検証)

~~~golang
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
~~~
2つのオブジェクトを比較します

~~~golang
assert.Equal(t, 123, 123) //-> Success
assert.Equal(t, 123, 321) //-> Failed

assert.Equal(t, "123", "123") //-> Success
assert.Equal(t, "123", "321") //-> Failed

assert.Equal(t, [...]int{1}, [...]int{1}) //-> Success
assert.Equal(t, [...]int{1}, [...]int{2}) //-> Failed
~~~



## [func Exactly](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L387)(厳密な比較検証)

~~~golang
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
~~~
厳密な比較検証します

~~~golang
assert.Exactly(t, int32(123), int64(123)) //-> Failed
assert.Exactly(t, int32(123), uint32(123)) //-> Failed
assert.Exactly(t, int32(123), 123) //-> Failed
assert.Exactly(t, "123", 123) //-> Failed

assert.Exactly(t, 123, 123) //-> Success

//------------------------------------
import "strconv"
assert.Exactly(t strconv.Itoa(123), "123") //-> Success
~~~


## [func JSONEq](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L1299)(JSONが同等であるか検証)

~~~golang
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool
~~~
JSONは2つのJSONが同等であるか検証。こちらも順序は問わないみたいですね

~~~golang
assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) //-> Success

assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) //-> Success

assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world!"}`) //-> Failed

assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello!": "world"}`) //-> Failed

assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello!": "world""}`) //-> Failed(Syntax Error)
~~~

## [func EqualError](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L1170)(Errorを比較)

~~~golang
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool
~~~
EqualErrorは、ある関数がエラーを返し`(error)`、
それが提供されたエラー`(String)`と等しいことを検証します。

~~~golang
import "errors"

// errors.New() は Errorの作成
assert.EqualError(t, errors.New("HOGE"), "HOGE") //-> Success
assert.EqualError(t, errors.New("HOGE"), "FUGA") //-> Failed
~~~

## [func EqualValues](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L367)

~~~golang
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
~~~
等しい値は、2つのオブジェクトが等しいか、同じ型に変換可能であり、等しいことを示します。

~~~golang
assert.EqualValues(t, uint32(123), int32(123)) //-> Success
assert.EqualValues(t, 123, int32(123)) //-> Success

assert.EqualValues(t, string(123), int32(123)) //-> Success
~~~

## [func IsType](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L307)(同じ型であるか検証)

~~~golang
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool
~~~
2つの構造体が同じ型であることを検証します

~~~golang
type (
    User struct {
        ID   int
        Name string
        Age  int
        Have Have
    }
    Have struct {
        toy   bool
        drink bool
        bag   bool
    }
)
user1 := User{1, "Plata", 17, Have{true, false, true}}
user2 := User{2, "aznalo", 17, Have{false, false, true}}
have  := Have{true, false, true}
//----------------------------------------------------

assert.IsType(t, user1, user1) //-> Success

assert.IsType(t, user1, user2) //-> Success

assert.IsType(t, user1, new(User)) //-> Failed

assert.IsType(t, user1, new(Have)) //-> Failed

assert.IsType(t, user1, have) //-> Failed
~~~


# Error*

## [func Error](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L1153)(Errorが返却されるか検証)

~~~golang
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool
~~~
関数がErrorを返却することを検証

~~~golang
import "errors"

// errors.New() は Errorの作成
assert.Error(t, errors.New("HOGE")) //-> Success
assert.Error(t, nil) //-> Failed
~~~

## [func NoError](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L1136)(エラーが無いことを検証)

~~~golang
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool
~~~

~~~golang
import "errors"

assert.NoError(t, nil) //-> Success
assert.Error(t, errors.New("HOGE")) //-> Failed

~~~

## [func Fail](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L233)(Fieldさせる)

Fieldを発生させます

~~~golang
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
~~~

~~~golang
assert.Fail(t, "HOGE") //->
/*--- FAIL: TestXxxx (0.03s)
        Error Trace:    xxx_test.go:xx
        Error:          HOGE
        Test:           TestXxxx
*/
~~~

## [func FailNow](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L212)

~~~golang
func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
~~~
`func Fail`と差がわからない

~~~golang
assert.FailNow(t, "HOGE") //->
/*--- FAIL: TestXxxx (0.03s)
        Error Trace:    xxx_test.go:xx
        Error:          HOGE
        Test:           TestXxxx
*/
~~~

## [func FileExists](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L1261)(ファイルのパスが存在するか検証)

~~~golang
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool
~~~
指定されたパスにファイルが存在するかどうかをチェックします。またディレクトリを指定した場合は失敗します

~~~golang
assert.FileExists(t, "/go/src/app/controllers/API/main.go") //-> Success

assert.FileExists(t, "/go/src/app/controllers/API") //-> Failed

assert.FileExists(t, "/go/src/app/controllers/API/bash") //-> Failed

~~~

# 存在を検証

## [func Empty](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L476)(値が空か検証)

~~~golang
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
~~~

Objectが空であることを判定します。
`nil`、 `""`、`false`、`0`、または`len == 0のスライス`は検証は成功します

~~~golang
assert.Empty(t, nil) //-> Success

assert.Empty(t, 0) //-> Success
assert.Empty(t, 1) //-> Failed

assert.Empty(t, "") //-> Success
assert.Empty(t, "Qiita") //-> Failed

assert.Empty(t, [...]int{}) //-> Success
assert.Empty(t, [...]int{1}) //-> Failed
//--------------------------------------
type User struct {
  Name string
}
test := User{}
assert.Empty(t, test) //-> Success

~~~

## [func False](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L565)(検証対象がFalseか検証*)

~~~golang
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool
~~~

~~~golang
assert.False(t, false) //-> Success
assert.False(t, true) //-> Failed
~~~

また同じような挙動の関数に `func True`と`func Nill`があります

## [func Len](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L526)(リストの要素数の検証)

~~~golang
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool
~~~

~~~golang
assert.Len(t, [...]int{1,2,3}, 3) //-> Success
assert.Len(t, [...]int{1,2,3}, 4) //-> Failed

assert.Len(t, [...]string{"1","2","3"}, 3) //-> Success
assert.Len(t, [...]string{"1","2","3"}, 4) //-> Failed
~~~

#[func Contains](https://github.com/stretchr/testify/blob/master/assert/assertions.go#L645)(含まれることを検証)

~~~golang
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
~~~

~~~golang
assert.NotContains(t, "Hello World", "Earth") //-> Failed
assert.NotContains(t, [...]string{"Hello", "World"}, "Earth")//-> Failed
assert.NotContains(t, "Hello", "World")//-> Failed

assert.NotContains(t, "HelloWorld", "World")//-> Success
assert.NotContains(t, "Hello World", "World")//-> Success
assert.NotContains(t, [...]string{"Hello", "World"}, "World")//-> Success
~~~


# [func NotContains](https://godoc.org/github.com/stretchr/testify/assert)(含まれないことを検証)

~~~golang
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
~~~

NotContainsは、指定された文字列、list（array、slice ...）またはmapに、指定された部分文字列または要素が含まれていないことを検証

~~~golang
assert.NotContains(t, "Hello World", "Earth") //-> Success
assert.NotContains(t, [...]string{"Hello", "World"}, "Earth")//-> Success
assert.NotContains(t, "Hello", "World")//-> Success

assert.NotContains(t, "HelloWorld", "World")//-> Failed
assert.NotContains(t, "Hello World", "World")//-> Failed
assert.NotContains(t, [...]string{"Hello", "World"}, "World")//-> Failed
~~~


## やってみて

Documentに書いてある関数多すぎて全部目を通すのにやっとった