【Go】ユニットテストのMock、Table driven Testとか
下記のコースのアウトプットになります。
Unit testing for Go developers | Udemy
参考にした記事
Goでテストを書く(テストの実装パターン集) - Qiita
Golang のテスト
実行コマンド
go test ./...
詳細を知りたい場合
go test -v ./...
特定のファイルを実行する
go test app/domain/service/survey_test.go
メッセージ
TODO
Table driven Test
Table Driven Testとは、それぞれの行が入力と期待する出力を含んだテストケースになっているテーブルを作り、それをループして実行する形式のテストです。
DMMにおけるユーザーレビュー基盤の変革(Goのテスト技法編) - DMM inside
テスト対象のコードです。
下記からは、コースで使用したソースを使っていきます。
package calculator
import "errors"
type DiscountCalculator struct {
minimumPurchaseAmount int
discountAmount int
}
func NewDiscountCalculator(minimumPurchaseAmount int, discountAmount int) (*DiscountCalculator, error) {
if minimumPurchaseAmount == 0 {
return &DiscountCalculator{}, errors.New("minimum purchase amount could not be zero")
}
return &DiscountCalculator{
minimumPurchaseAmount: minimumPurchaseAmount,
discountAmount: discountAmount,
}, nil
}
func (c *DiscountCalculator) Calculate(purchaseAmount int) int {
if purchaseAmount > c.minimumPurchaseAmount {
multiplier := purchaseAmount / c.minimumPurchaseAmount
return purchaseAmount - (c.discountAmount * multiplier)
}
return purchaseAmount
}
下記でもわかる通り、テストデータが非常にわかりやすいです。
package calculator
import "testing"
// testingの宣言は下記のような感じ
func TestDiscountCalculator(t *testing.T) {
type testCase struct {
name string
minimumPurchaseAmount int
discount int
purchaseAmount int
exepectedAmount int
}
// テストケーズをまとめているところ
// テストケースが一目でわかりやすい
testCases := []testCase{
{name: "should apply 20", minimumPurchaseAmount: 100, discount: 20, purchaseAmount: 150, exepectedAmount: 130},
{name: "should apply 40", minimumPurchaseAmount: 100, discount: 20, purchaseAmount: 200, exepectedAmount: 160},
{name: "should apply 60", minimumPurchaseAmount: 100, discount: 20, purchaseAmount: 350, exepectedAmount: 290},
{name: "should not apply", minimumPurchaseAmount: 100, discount: 20, purchaseAmount: 50, exepectedAmount: 50},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
calculator := NewDiscountCalculator(tc.minimumPurchaseAmount, tc.discount)
amount := calculator.Calculate(tc.purchaseAmount)
if amount != tc.exepectedAmount {
t.Errorf("exepected %v, got %v", tc.exepectedAmount, amount)
}
})
}
}
// 実行結果
=== RUN TestDiscountCalculator
=== RUN TestDiscountCalculator/should_apply_20
=== RUN TestDiscountCalculator/should_apply_40
=== RUN TestDiscountCalculator/should_apply_60
=== RUN TestDiscountCalculator/should_not_apply
--- PASS: TestDiscountCalculator (0.00s)
--- PASS: TestDiscountCalculator/should_apply_20 (0.00s)
--- PASS: TestDiscountCalculator/should_apply_40 (0.00s)
--- PASS: TestDiscountCalculator/should_apply_60 (0.00s)
--- PASS: TestDiscountCalculator/should_not_apply (0.00s)
golangでテストを書くならテーブルドリブンテスト - Qiita
例外処理
TODO
Assert
assert.Equal(t, tc.exepectedAmount, amount)
Mock(モック)
Mockは、必要なテスト条件を容易に作ることができます。
Mockでユニットテストを簡単にしよう! | GMOアドパートナーズグループ TECH BLOG byGMO
Golangでは、下記記事が一番わかりやすかったです。
testify/mockでgolangのテストを書く - Qiita
// Mock の宣言
type DiscountRepositoryMock struct {
mock.Mock
}
// interface 宣言
type Discount interface {
FindCurrentDiscount() int
}
// Mockを使ったメソッドの呼び出し
func (drm DiscountRepositoryMock) FindCurrentDiscount() int {
// 条件にあったReturn設定値を返す
args := drm.Called()
return args.Int(0)
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Mockを初期化
discountRepositoryMock := DiscountRepositoryMock{}
// 使用するメソッドと返り値を設定する
discountRepositoryMock.On("FindCurrentDiscount").Return(tc.discount)
calculator, err := NewDiscountCalculator(tc.minimumPurchaseAmount, discountRepositoryMock)
if err != nil {
// FailNow + log
t.Fatalf("could not instantiate the calculator %s", err.Error())
}
amount := calculator.Calculate(tc.purchaseAmount)
assert.Equal(t, tc.exepectedAmount, amount)
})
}
Author And Source
この問題について(【Go】ユニットテストのMock、Table driven Testとか), 我々は、より多くの情報をここで見つけました https://qiita.com/wqwq/items/ea71bc8244047acb55fb著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .