計算機科学のブログ

多国通貨(The Money Example) テストに聞いてみる(Interesting Times)

テスト駆動開発 (Kent Beck(著)、和田 卓人(翻訳)、オーム社)の第Ⅰ部(多国通貨(The Money Example))、第10章(テストに聞いてみる(Interesting Times))をJavaではなくGo言語で取り組んでみる。

コード

money_test.go

package money

import "testing"

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

func TestMoneyCurrency(t *testing.T) {
	tests := []struct {
		c string
		m Money
	}{
		{"USD", NewDollar(1)},
		{"CHF", NewFranc(1)},
	}
	for _, test := range tests {
		got := test.m.Currency()
		want := test.c
		if got != want {
			t.Errorf("%v.Currency() got %v, want %v",
				test.m, got, want)
		}
	}
}
func TestMoneyEq(t *testing.T) {
	tests := []struct {
		mx, my Money
		want   bool
	}{
		{NewDollar(5), NewDollar(5), true},
		{NewDollar(5), NewDollar(6), false},
		{NewFranc(5), NewFranc(5), true},
		{NewFranc(5), NewFranc(6), false},
		{NewFranc(5), NewDollar(5), false},
	}
	for _, test := range tests {
		got := test.mx.Eq(test.my)
		want := test.want
		if got != want {
			t.Errorf("%v.Eq(%v) got %v, want %v",
				test.mx, test.my, got, want)
		}
	}
}

// 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

import "fmt"

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

func (mx Money) String() string {
	return fmt.Sprintf("%v %v", mx.amount, mx.currency)
}

// NewMoney ...
func NewMoney(amount int, currency string) Money {
	return Money{amount, currency}
}

// Currency ...
func (mx Money) Currency() string {
	return mx.currency
}

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

// Times ...
func (mx Money) Times(m int) Money {
	return NewMoney(mx.amount*m, mx.currency)
}

// Eqer ...
// type Eqer interface {
// 	Eq(Eqer) bool
// }

// Dollar ...
// type Dollar struct {
// 	Money
// }

// NewDollar ...
func NewDollar(amount int) Money {
	return Money{amount: amount, currency: "USD"}
}

// Times ...
// func (d Dollar) Times(m int, currency string) Money {
// 	return NewMoney(d.amount*m, currency)
// }

// 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) Money {
	return Money{amount: amount, currency: "CHF"}
}

// Times ...
// func (f Franc) Times(m int, currency string) Money {
// 	return NewMoney(f.amount*m, currency)
// }

// 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
PASS
ok  	money	0.400s
% go test -v
=== RUN   TestMoneyTimes
--- PASS: TestMoneyTimes (0.00s)
=== RUN   TestMoneyCurrency
--- PASS: TestMoneyCurrency (0.00s)
=== RUN   TestMoneyEq
--- PASS: TestMoneyEq (0.00s)
PASS
ok  	money	0.101s
%