多国通貨(The Money Example) 疑念をテストに翻訳する(Apples and Oranges) 異なる通貨間での比較
テスト駆動開発 (Kent Beck(著)、和田 卓人(翻訳)、オーム社)の第Ⅰ部(多国通貨(The Money Example))、第7章(疑念をテストに翻訳する(Apples and Oranges))をJavaではなくGo言語で取り組んでみる。
コード
money_test.go
package money
import "testing"
func TestDollarTimes(t *testing.T) {
five := NewDollar(5)
tests := []struct {
m int
want Dollar
}{
{2, NewDollar(10)},
{3, NewDollar(15)},
}
for _, test := range tests {
got := five.Times(test.m)
want := test.want
if !got.Eq(want) {
t.Errorf("%v.Times(%v) got %v, want %v", five, test.m, got, want)
}
}
}
func TestDollarEq(t *testing.T) {
five := NewDollar(5)
tests := []struct {
d Eqer
want bool
}{
{NewDollar(5), true},
{NewDollar(6), false},
}
for _, test := range tests {
got := five.Eq(test.d)
if got != test.want {
t.Errorf("%v.Eq(%v) got %v, want %v",
five, test.d, got, test.want)
}
}
}
func TestFrancTimes(t *testing.T) {
five := NewFranc(5)
tests := []struct {
m int
want Franc
}{
{2, NewFranc(10)},
{3, NewFranc(15)},
}
for _, test := range tests {
got := five.Times(test.m)
want := test.want
if !got.Eq(want) {
t.Errorf("%v.Eq(%v) got %v, want %v",
five, test.m, got, want)
}
}
}
func TestFrancEq(t *testing.T) {
five := NewFranc(5)
tests := []struct {
d Eqer
want bool
}{
{NewFranc(5), true},
{NewFranc(6), false},
{NewDollar(5), false},
}
for _, test := range tests {
got := five.Eq(test.d)
if got != test.want {
t.Errorf("%v.Eq(%v) got %v, want %v",
five, test.d, got, test.want)
}
}
}
money.go
package money
// Money ...
type Money struct {
amount int
}
// Eqer ...
type Eqer interface {
Eq(Eqer) bool
}
// Dollar ...
type Dollar struct {
Money
}
// NewDollar ...
func NewDollar(amount int) Dollar {
// return Dollar{amount:amount}
return Dollar{Money{amount: amount}}
}
// Times ...
func (d Dollar) Times(m int) Dollar {
return NewDollar(d.amount * m)
}
// Eq ...
func (d Dollar) Eq(y Eqer) bool {
dy, ok := y.(Dollar)
if ok {
return d.amount == dy.amount
}
return false
}
// Franc ...
type Franc struct {
Money
}
// NewFranc ...
func NewFranc(amount int) Franc {
return Franc{Money{amount: amount}}
}
// Times ...
func (f Franc) Times(m int) Franc {
return NewFranc(f.amount * m)
}
// Eq ...
func (f Franc) Eq(y Eqer) bool {
fy, ok := y.(Franc)
if ok {
return f.amount == fy.amount
}
return false
}
入出力結果(Terminal, Zsh)
% go test
--- FAIL: TestMoneyEq (0.00s)
money_test.go:63: {{5}}.Eq({{5}}) got true, want false
FAIL
exit status 1
FAIL money 0.407s
% go test
--- FAIL: TestMoneyEq (0.00s)
money_test.go:33: {{5}}.Eq({{5}}) got false, want true
money_test.go:63: {{5}}.Eq({{5}}) got true, want false
FAIL
exit status 1
FAIL money 0.309s
% go test
--- FAIL: TestMoneyEq (0.00s)
money_test.go:48: {{10}}.Eq({{10}}) got false, want true
money_test.go:48: {{15}}.Eq({{15}}) got false, want true
money_test.go:63: {{5}}.Eq({{5}}) got true, want false
FAIL
exit status 1
FAIL money 0.282s
% go test
# money [money.test]
./money_test.go:46:28: cannot use test.fy.Money (type Money) as type Eqer in argument to test.fx.Eq:
Money does not implement Eqer (missing Eq method)
./money_test.go:60:22: test.f.Money.Eq undefined (type Money has no field or method Eq)
FAIL money [build failed]
% go test
PASS
ok money 0.689s
% go test
PASS
ok money 0.290s
% go test
--- FAIL: TestDollarTimes (0.00s)
money_test.go:18: {{5}}.Times(2) got {{10}}, want {{10}}
money_test.go:18: {{5}}.Times(3) got {{15}}, want {{15}}
FAIL
exit status 1
FAIL money 0.293s
% go test
PASS
ok money 0.223s
% go test
--- FAIL: TestFrancEq (0.00s)
money_test.go:71: {{5}}.Eq({{5}}) got true, want false
FAIL
exit status 1
FAIL money 0.275s
% go test
PASS
ok money 0.223s
%