Introduction
最近Echoでサーバーを書く機会があった。
テストコードを書きたかった。
Echo Document Testingを見てみると
import (
"net/http" //<- わかる
"net/http/httptest" //<- わかる
"strings" //<- わかる
"testing" //<- 超わかる
"github.com/labstack/echo" //<- わかる
"github.com/stretchr/testify/assert" //<-なにこれ????
)
github.com/stretchr/testify/assert
とか言うのかimportされていた
もう少し見てみると
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読み行こ。」
「日本語版ないな」「和訳されたやつないかな」
Google[testify assert][Search]
「うんないな。書こう」
そんな経緯です、。ゆるく検証していきます
環境
go 1.9
assert 1.2.1
記載されている結果はすべて上記の環境により実行しております
比較
func ElementsMatch(リストの比較)
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool)
ElementMatchはlistA(array, slice...) とlistB(array, slice...)の要素が一致しているか判定します (順序は問わない)
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(比較検証)
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
2つのオブジェクトを比較します
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(厳密な比較検証)
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
厳密な比較検証します
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(JSONが同等であるか検証)
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool
JSONは2つのJSONが同等であるか検証。こちらも順序は問わないみたいですね
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(Errorを比較)
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool
EqualErrorは、ある関数がエラーを返し(error)
、
それが提供されたエラー(String)
と等しいことを検証します。
import "errors"
// errors.New() は Errorの作成
assert.EqualError(t, errors.New("HOGE"), "HOGE") //-> Success
assert.EqualError(t, errors.New("HOGE"), "FUGA") //-> Failed
func EqualValues
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
等しい値は、2つのオブジェクトが等しいか、同じ型に変換可能であり、等しいことを示します。
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(同じ型であるか検証)
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool
2つの構造体が同じ型であることを検証します
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(Errorが返却されるか検証)
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool
関数がErrorを返却することを検証
import "errors"
// errors.New() は Errorの作成
assert.Error(t, errors.New("HOGE")) //-> Success
assert.Error(t, nil) //-> Failed
func NoError(エラーが無いことを検証)
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool
import "errors"
assert.NoError(t, nil) //-> Success
assert.Error(t, errors.New("HOGE")) //-> Failed
func Fail(Fieldさせる)
Fieldを発生させます
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
assert.Fail(t, "HOGE") //->
/*--- FAIL: TestXxxx (0.03s)
Error Trace: xxx_test.go:xx
Error: HOGE
Test: TestXxxx
*/
func FailNow
func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
func Fail
と差がわからない
assert.FailNow(t, "HOGE") //->
/*--- FAIL: TestXxxx (0.03s)
Error Trace: xxx_test.go:xx
Error: HOGE
Test: TestXxxx
*/
func FileExists(ファイルのパスが存在するか検証)
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool
指定されたパスにファイルが存在するかどうかをチェックします。またディレクトリを指定した場合は失敗します
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(値が空か検証)
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool
Objectが空であることを判定します。
nil
、 ""
、false
、0
、またはlen == 0のスライス
は検証は成功します
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(検証対象がFalseか検証*)
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool
assert.False(t, false) //-> Success
assert.False(t, true) //-> Failed
また同じような挙動の関数に func True
とfunc Nill
があります
func Len(リストの要素数の検証)
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool
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(含まれることを検証)
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
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(含まれないことを検証)
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool
NotContainsは、指定された文字列、list(array、slice ...)またはmapに、指定された部分文字列または要素が含まれていないことを検証
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に書いてある関数多すぎて全部目を通すのにやっとった