計算機科学のブログ

多国通貨(The Money Example) テスト不足に気づいたら(Equality for All, Redux)

テスト駆動開発 (Kent Beck(著)、和田 卓人(翻訳)、オーム社)の第Ⅰ部(多国通貨(The Money Example))、第6章(テスト不足に気づいたら(Equality for All, Redux))をJavaではなくGo言語で取り組んでみる。

コード

money_test.go

package money

import "testing"

func TestMoneyTimes(t *testing.T) {
	five := NewDollar(5)
	tests := []struct {
		m, want int
	}{
		{2, 10},
		{3, 15},
	}
	for _, test := range tests {
		got := five.Times(test.m).amount
		want := test.want
		if got != want {
			t.Errorf("five.Times(%v) got %v, want %v", test.m, got, want)
		}
	}
}
func TestMoneyEq(t *testing.T) {
	five := NewDollar(5)
	tests := []struct {
		d    Dollar
		want bool
	}{
		{NewDollar(5), true},
		{NewDollar(6), false},
	}
	for _, test := range tests {
		got := five.Eq(test.d.Money)
		if got != test.want {
			t.Errorf("%v.Eq(%v) got %v, want %v",
				five, test.d, got, test.want)
		}
	}
	fiveFranc := NewFranc(5)
	francTests := []struct {
		fx, fy Franc
		want   bool
	}{
		{NewFranc(10), fiveFranc.Times(2), true},
		{NewFranc(15), fiveFranc.Times(3), true},
	}
	for _, test := range francTests {
		got := test.fx.Eq(test.fy.Money)
		if got != test.want {
			t.Errorf("%v.Eq(%v) got %v, want %v",
				test.fx, test.fy, got, test.want)
		}
	}
}

// func TestDollarTimes(t *testing.T) {
// 	five := NewDollar(5)
// 	tests := []struct {
// 		m, want int
// 	}{
// 		{2, 10},
// 		{3, 15},
// 	}
// 	for _, test := range tests {
// 		got := five.Times(test.m).amount
// 		want := test.want
// 		if got != want {
// 			t.Errorf("five.Times(%v) got %v, want %v", test.m, got, want)
// 		}
// 	}
// }

// func TestDollarEq(t *testing.T) {
// 	five := NewDollar(5)
// 	tests := []struct {
// 		d    Dollar
// 		want bool
// 	}{
// 		{NewDollar(5), true},
// 		{NewDollar(6), false},
// 	}
// 	for _, test := range tests {
// 		got := five.Eq(test.d.Money)
// 		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, want int
// 	}{
// 		{2, 10},
// 		{3, 15},
// 	}
// 	for _, test := range tests {
// 		got := five.Times(test.m).amount
// 		want := test.want
// 		if got != want {
// 			t.Errorf("five.Times(%v) got %v, want %v", test.m, got, want)
// 		}
// 	}
// }

money.go

package money

// Money ...
type Money struct {
	amount int
}

// Eq ...
func (mx Money) Eq(my Money) bool {
	return mx.amount == my.amount
}

// 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(c Dollar) bool {
// 	return d.amount == c.amount
// }
// func (d Dollar) Eq(m Money) bool {
// 	return d.amount == m.amount
// }

// 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(c Franc) bool {
// 	return f.amount == c.amount
// }
// func (f Franc) Eq(m Money) bool {
// 	return f.amount == m.amount
// }

入出力結果(Terminal, Zsh)

% go test
# money [money.test]
./money_test.go:32:22: cannot use test.d (type Dollar) as type Money in argument to five.Eq
FAIL	money [build failed]
% go test
PASS
ok  	money	0.286s
% go test
PASS
ok  	money	0.302s
% go test
PASS
ok  	money	0.275s
% go test
PASS
ok  	money	0.298s
% go test
PASS
ok  	money	0.244s
% go test
PASS
ok  	money	0.293s
% go test
PASS
ok  	money	0.296s
% go test
# money [money.test]
./money_test.go:46:25: cannot use test.fy (type Franc) as type Money in argument to test.fx.Money.Eq
FAIL	money [build failed]
% go test
PASS
ok  	money	0.294s
% go test
PASS
ok  	money	0.223s
% go test
PASS
ok  	money	0.279s
% go test
PASS
ok  	money	0.274s
%