狠狠撸

狠狠撸Share a Scribd company logo
エクストリーム?エンジニアへの道
(Ruby編)第4回
テスト駆動開発
TDD	
 ?
テクノロジックアート	
 ?
??長瀬? 嘉秀	
 ?
?? テスト駆動開発	
内容	
 ?
テスト駆動開発(TDD)とは	
 ?
Test	
 ? 	
 ?  	
 ? ? テストが	
 ?
Driven	
 ?  	
 ? ? 駆動する	
 ?
Development	
 ? ? 開発	
開発の手法である
(テスト手法ではない)
TDDとは:	
 ?XP	
 ?のプラクティス	
 ?
?? XP	
 ?のプラクティスの一つである	
アジャイル開発手法	
XP	
プラクティス	
リファクタリング	
最適ペース	
継続的結合	
テスト駆動開発(TDD)	
全員同席	
シンプル設計	
:	
その他のXPプラクティスと密接に関係しています
TDDとは:より具体的に	
 ?
?? 定義	
–? ソフトウェアの小さな機能ごとに、テスト?実装の細かいステップを	
 ?
繰り返して、プログラムの設計?開発を行う開発手法	
?? 進め方	
–? ToDo リストで実装すべき機能を管理する	
?? メモに作るべき振る舞いや作業を ToDo として洗い出す	
–? 各 ToDo 毎に以下の手順を繰り返す	
?? まず、テストコードを書く	
?? テストを実行する ? 失敗する	
	
 ? (RED)	
?? 次に、テストをパスするよう機能コードを書く	
?? テストを実行する ? 成功する	
 ? 	
 ? (GREEN)	
?? 機能コードを本来あるべき姿にリファクタリングする	
?? テストを実行する ? 成功していることを確認 (REFACTORING)
TDDとは: TDDのサイクル	
テスト	
テスト動作確認	
リファクタリング	
動作	
最初にテストを書く	
コンパイルを通しテストに失敗させる	
確実にテストが通るコードを書く	
 ?
きれいなコードにする	
 ?
? これから追加しようとする機能の振る舞いを明らかにする	
  テストで仕様を表現する	
? 作成したテストが確実に動いていること、	
 ?
  問題のある結果が返ればレッドになることを確認する	
? 正しい結果が返ればグリーンになることを確認する	
 ?
  必要最小限の実装を少しずつ安全に積み重ねていく	
? リファクタリングでコードの臭いをとる	
 ?
  現在のテストに必要な、最小限の実装にとどめる(YAGNI)	
 ?
RubyUnit
テスト駆動開発(TDD)の本質	
 ?
?? 設計手法である	
–? テストを書くことで、機能コードの振る舞いを明らかにしていく設計
作業である	
–? 進化的設計を前提としている	
?? 信頼性を積み重ねる開発手法である	
–? 少しずつ、必ずテストによって検証可能な実装を積み重ねる開発
促進の為の技法である	
–? テストは開発者自らが作成する	
–? テスト範囲は開発者が決める	
–? 一定のリズムで実施する為、迅速なビルド?テスト環境が必要であ
る
TDDの本質:設計?手法である①	
 ?
?? TDDとは振る舞いを明らかにする設計作業である	
–? 先に外から見た振る舞いを明らかにする	
 ?
?? テストを書くことによって、クラスやメソッドの振る舞いを考える	
–? 振る舞いを保ちつつ内部を進化的に作っていく	
 ?
?? 動作するきれいなコード	
そのコードは今日行うべきことを実行する	
明日必要な変更をスムーズに行える	
動作する	
きれいなコード
TDDの本質:設計?手法である②	
 ?
?? TDDとは、進化的設計を前提としている	
–? あらかじめ詳細まで設計するのではなく、	
 ?
実装しながら詳細を設計する(コードによる設計)	
 ?
テストによって
インターフェースを
規定する	
内部の詳細は	
 ?
進化的に作成
する
TDDの本質:	
 ?信頼性を積み重ねる①	
 ?
?? 開発促進の為の技法である	
–? 特徴	
?? 従来	
 ?
–? 全体の信頼性を後工程で引き上げた (V字カーブ)	
 ?
?? TDD	
 ?
–? 信頼できる部分を積み重ねる (反復型)	
 ?
–? 自動化テストによる検証可能性	
?? テストを自動実行可能にして、常に検証し続けることで、デグレードし
ていないことを保証する
TDDの本質:	
 ?信頼性を積み重ねる②	
 ?
?? テストは開発者自らが作る	
–? テスターが品質保証のために作るテストではない	
 ?
–? 開発者が開発を進めるために作るテストである	
 ?
?? テスト範囲は開発者が決める	
 ?
品質保証のためのテスト	
担当者:
 テスター
対象コード:
 作成済み実装コード
TDDのテスト	
担当者:
 開発者
対象コード:
 テスト開始時点には
 存在しないコード
TDDの本質:	
 ?信頼性を積み重ねる③	
 ?
?? TDDには、迅速なビルド?テスト環境が必要である	
–? 少しずつ作る為、コンパイル?テスト?動作を細かいサイクルで繰り
返す	
 ?
–? ビルド?テストは自動化され、実行時間は短くなければならない	
 ?
テスト	
テスト動作確認	
リファクタリング	
動作
演習:?足し算? -? テストケース?一覧	
 ?
?? テストケース一覧	
 ?
–? 足す数字が2つともゼロの場合	
 ?
–? 最初の数字がゼロの場合	
 ?
–? 2つ目の数字がゼロの場合	
 ?
–? 両方ともゼロではない場合	
これをToDoリストにする	
準備ができたので、	
演習を始めます。	
14
演習:?足し算? -? 最初に考えること	
 ?
?? まずは “2つの数字がゼロ” を対象とする	
 ?
?? 足し算をするメソッドがあるとよい	
–? 2つの数字を指定できる	
–? 結果を戻す	
 ?
?? これをテストの形で表現する	
 ?
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
15
演習:?足し算? -? 最初のテストコード	
 ?
?? まずテストコードを書く	
?? assertEquals() は2つの引数が等しくない
時にエラーを出す	
?? まだコンパイルできない	
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
16
Require	
 ?'test/unit'	
 ?
class	
 ?TestCalc	
 ?<	
 ?Test::Unit::TestCase	
 ?
	
 ?	
 ?	
 ?	
 ?def	
 ?test_both_zero()	
 ?
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?assert_equal(0,	
 ?add(0,	
 ?0))	
 ?
	
 ?	
 ?	
 ?	
 ?end	
 ?
end	
 ?
演習:?足し算? 最初のテストコードエラー	
 ?
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
17
JUnitの基礎	
 ?
?? テストの指定	
 ?
–? テストメソッドは、testで始まる名前である。	
 ?
?? 検証	
 ?
–? assert(test,[failure_message])
–? assert_block(failure_message = nil)
–? assert_equal(expected, actual,failure_messgae = nil)
 他、多くのアサーションメソッドがある	
18
演習:?足し算? -? コンパイルを通す	
 ?
?? add メソッドを作成	
 ?
–? コンパイルしてテスト	
 ?
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
最初はテストを失敗させるコードを書く	
 ?
? 作成したテストが確実に動いていること、	
 ?
  問題のある結果が返ればレッドになることを確認する	
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?1	
 ?
end	
 ?
演習:?足し算? -? テストを通す	
 ?
?? テストを通す	
 ?
–? コンパイルしてテスト	
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
確実にテストが通るコードを書く	
 ?
? 正しい結果が返ればグリーンになることを確認する	
 ?
  実装を少しずつ安全に積み重ねていく	
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?0	
 ?
end	
 ?
演習:?足し算? -? テストを通す	
 ?
?? 実行結果 成功	
 ?
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない
演習:?足し算? -? 2つめのテスト	
 ?
?? テストを追加	
 ?
–? コンパイルしてテスト	
 ?
?? add メソッドを修正	
 ?
–? コンパイルしてテスト	
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
def	
 ?test_?rst_zero()	
 ?
	
 ?	
 ?	
 ?assert_equal(3,	
 ?add(0,	
 ?3))	
 ?
end	
 ?
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?second	
 ?
end	
 ?
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?if	
 ?(second	
 ?	
 ?==	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?end	
 ?
	
 ?	
 ?	
 ?second	
 ?
end	
 ?
演習:?足し算? -? 3つめのテスト	
 ?
?? テストを追加	
 ?
–? コンパイルしてテスト	
 ?
?? add メソッドを修正	
 ?
–? コンパイルしてテスト	
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
def	
 ?test_second_zero()	
 ?
	
 ?	
 ?	
 ?assert_equal(2,	
 ?add(2,	
 ?0))	
 ?
end	
 ?
演習:?足し算? -? 最後のテスト	
 ?
?? テストを追加	
 ?
–? コンパイルしてテスト	
 ?
?? add メソッドを修正	
 ?
–? コンパイルしてテスト	
2つの数字がゼロ	
最初の数字がゼロ	
2つ目の数字がゼロ	
どちらもゼロではない	
def	
 ?test_both_not_zero()	
 ?
	
 ?	
 ?	
 ?assert_equal(5,	
 ?add(2,	
 ?3))	
 ?
end	
 ?
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?	
 ?if	
 ?(?rst	
 ?!=	
 ?0	
 ?&&	
 ?second	
 ?!=	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?+	
 ?second	
 ?end	
 ?
	
 ?	
 ?	
 ?if	
 ?(second	
 ?	
 ?==	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?end	
 ?
	
 ?	
 ?	
 ?second	
 ?
end	
 ?
演習:?足し算? -? リファクタリング	
 ?
?? add メソッドを修正	
 ?
second	
 ?==	
 ?0	
 ?の時、?rst	
 ?は ?rst	
 ?+	
 ?second	
 ?と同じ	
?rst	
 ?==	
 ?0	
 ?の時、second	
 ?は ?rst	
 ?+	
 ?second	
 ?と同じ	
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?	
 ?if	
 ?(?rst	
 ?!=	
 ?0	
 ?&&	
 ?second	
 ?!=	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?+	
 ?second	
 ?end	
 ?
	
 ?	
 ?	
 ?if	
 ?(second	
 ?	
 ?==	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?end	
 ?
	
 ?	
 ?	
 ?second	
 ?
end	
 ?
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ?	
 ?if	
 ?(?rst	
 ?!=	
 ?0	
 ?&&	
 ?second	
 ?!=	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?+	
 ?second	
 ?end	
 ?
	
 ?	
 ?	
 ?if	
 ?(second	
 ?	
 ?==	
 ?0)	
 ?then	
 ?return	
 ??rst	
 ?+	
 ?second	
 ?end	
 ?
	
 ?	
 ?	
 ?second	
 ?
end	
 ?
def	
 ?add(?rst,second)	
 ?
	
 ?	
 ?	
 ??rst	
 ?+	
 ?second	
 ?
end	
 ?
?? 交通費精算	
実例例	
 ?
シナリオ	
 ?
ToDoリスト	
 ?
出発駅オブジェクトの?生成	
 ?
到着駅	
 ?
テストの実?行行	
 ?
?? 現在のコードをリファクタリングしてください。	
 ?
?? ヒント:重複したコードを取り除く	
演習1	
 ?
料料?金金表	
 ?
?? 料金表を導入して、料金を検索できるようにしてください。	
 ?
?? ヒント:テストコードは以下のようになります。	
演習2	
 ?
def	
 ?test_fare	
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?dept	
 ?=	
 ?DepartureStaIon.new("Shinagawa")	
dest	
 ?=	
 ?DesInaIonStaIon.new("Shinjuku")	
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?fare	
 ?=	
 ?Fare.new(200,dept,dest)	
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?assert_equal(200,fare.fare)	
end	
	
 ?def	
 ?test_?nd_fare	
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?dept	
 ?=	
 ?DepartureStaIon.new("Shinagawa")	
dest	
 ?=	
 ?DesInaIonStaIon.new("Shinjuku")	
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?fare	
 ?=	
 ?Fare.new(200,dept,dest)	
fareTable	
 ?=	
 ?FareTable.new	
fareTable.add(fare)	
?	
	
 ?	
 ?	
 ?	
 ?	
 ?	
 ?assert_equal(200,fareTable.?nd_fare(dept,dest))	
	
 ?	
 ?	
 ?end

More Related Content

エクストリームエンシ?ニア4