go で unit test をやってみた
TRANSCRIPT
Go で Unit Test をやってみたGo 言語と React で考える
Web アプリの「いい感じな URL 設計」入門
自己紹介• 矢納正浩 ( ヤノウマサヒロ )– ( 株 )zabuton– 平成 5 年生まれ、社会人 4 年目– Java, Python, Go, Angular 1 系 , React
• 新規サービス開発をしてます!• バレーボールやってます!
目標達成を支援するクラウドサービス• 明確なゴールがない• ゴールが共有されてな
い• ゴールに向かってない• 達成度が見えない• 自律型組織が進まない https://info.zealup.jp
これらの問題を解決
https://info.zealup.jp
https://info.zealup.jp
Router
Middlew
are
Controller
Service
Database
Service
• Database とのやり取りのレイヤー• Couchbase を使用– NoSQL– 1ms 以下のレイテンシ– 個人的に好き
• とは違う DB です (^_^;)
type UserService interface { GetUserByEmail(email string) (*entity.User, error)}
type UserServiceImpl struct {}
func (_ UserServiceImpl) GetUserByEmail(email string) (*entity.User, error) { var params []interface{} params = append(params, email)
query := db.NewN1QLQuery("select * from sample where email=$1") rows, _ := db.GetBucket().ExecuteN1qlQuery(query, params)
var row map[string]*entity.User rows.One(&row) return row["sample"], nil}
import ( "github.com/stretchr/testify/assert" "testing")
func init() { before()}
func TestGetUserByEmail_success_to_get(t *testing.T) { sut := UserServiceImpl{} user, err := sut.GetUserByEmail("[email protected]") if err != nil { assert.Fail(t, err.Error()) return } assert.Equal(t, "0904a8b4611d4ed757939c2593ba9da6", user.Id) assert.Equal(t, "Yanou", user.Name) assert.Equal(t, "[email protected]", user.Email)}
func before() { connectTestDatabase() bucket := database.GetBucket()
opes := database.NewBulkOpes() opes = append(removeOpes, db.NewRemoveOpe("user_0904a8")) if err := bucket.Do(removeOpes); err != nil { panic(err) }
opes = database.NewBulkOpes() opes = append(insertOpes, db.NewInsertOpe("user_0904a8", &entity.User{ Id: "0904a8", Type: "user", Name: "Yanou", Email: "[email protected]", })) if err := bucket.Do(insertOpes); err != nil { panic(err) }}
テスト用 DB への接続
テストデータの削除
テストデータの作成
func TestSaveTrackingList_success_to_save(t *testing.T) { beforeMetaList()
// テスト対象実行 afterMetaList()
diffMetaList := diffMetaList() // アサーション}
テスト対象実行前の DB 状態を取得この際に ID と REV を取得テスト対象実行後の DB 状態を取得この際に ID と REV を取得
上記ふたつの差分を習得
Controller
• リクエストの処理• Service へのデータ渡し・受け取り– Service はモックします
import ( "github.com/stretchr/testify/mock" "jp.co.zabuton/service")
type MockCompanyService struct { service.CompanyService mock.Mock}
func (m *MockCompanyService) GetCompany(id string) *entity.Company { args := m.Called(id) if args.Get(0) == nil { return nil } else { return args.Get(0).(*entity.Company) }}
func TestGetCompanies_no_data(t *testing.T) { mockCS := new(MockCompanyService) mockCS.On("GetCompanies").Return([]entity.Company{}, nil) SetCompanyService(mockCS)
r := createRequest("GET", "/companies", nil) w := httptest.NewRecorder() m.ServeHTTP(w, r)
assert.Equal(t, w.Code, http.StatusOK) assert.Equal(t, "[]", string(w.Body.Bytes()))}
テストカバレッジgo test -coverprofile=cover.out service
go tool cover -html=cover.out
テストカバレッジgo test -coverprofile=cover.out ${package}
複数のパッケージを同時に出すことができないgo test -coverprofile=cover.out servicego test -coverprofile=cover.out controllergo test -coverprofile=cover.out middlewarego test -coverprofile=cover.out util
じゃあ……くっつけちゃいましょう!
export GOPATH=`pwd`mkdir -p coverrm -fr cover/*
packages=("controller" "service" "middleware")
for package in ${packages[@]}do go test -coverprofile=cover/${package}.out ${package}done
for package in ${packages[@]}do go tool cover -html=cover/${package}.out -o=cover/${package}.htmldone
./logmerge ${COVER_DIR}open ${COVER_DIR}/merge.html
export GOPATH=`pwd`mkdir -p coverrm -fr cover/*
packages=("controller" "service" "middleware")
for package in ${packages[@]}do go test -coverprofile=cover/${package}.out jp.co.zabuton/time/${package}done
for package in ${packages[@]}do go tool cover -html=cover/${package}.out -o=cover/${package}.htmldone
./logmerge ${COVER_DIR}open ${COVER_DIR}/merge.html ?
./logmerge ${COVER_DIR}
• つくりました• 作成された HTML を解析• selectbox の内容のマージ• テスト対象のコードをマージ• マージした HTML を出力
Go で Unit Test をやってみた1st Product Zealup https://info.zealup.jp
矢納正浩株式会社 zabuton https://zabuton.co.jp