テスト駆動開発(tdd) in .net #ngtnet
TRANSCRIPT
テスト駆動開発(TDD)in .NET
2016/5/7 - #ngtnet
TAKANO Sho(高野 将)/ @masaru_b_cl
自己紹介
某SIerで働くDeveloper
そのかたわら執筆業も
#ngtnet 2
今日お話すること
テスト駆動開発(TDD)とは?
.NET開発におけるTDD
TDDの実例
TDDの指針
#ngtnet 3
テスト駆動開発(TDD)とは?
#ngtnet 4
テスト駆動開発(TDD)とは?
ケント・ベックが提唱した開発手法
#ngtnet 5
テスト駆動開発入門(ケント・ベック著、ピアソンエデュケーション刊)
http://www.amazon.co.jp/dp/4894717115
“「動作するきれいなコード」、
ロン・ジェフリーズの
この簡潔な言葉は、
TDD(テスト駆動開発)の目標である。
動作するきれいなコードは、
あらゆる理由で価値がある。 絶版
TDDの進み方
#ngtnet 6
TDD のこころ @ OSH2014
http://www.slideshare.net/t_wada/osh2014-sprit-of-tdd
TDDの進み方
#ngtnet 7
着実な道をいく
TDDのサイクル
1. 次の目標を考える
2. その目標を示すテストを書く(テストファースト)
3. そのテストを実行して失敗させる(Red)
4. 目的のコードを書く
5. 2で書いたテストを成功させる(Green)
6. テストが通るままで
リファクタリングを行う(Refactoring)
7. 1~6を繰り返す
#ngtnet 8
TDD のこころ @ OSH2014
http://www.slideshare.net/t_wada/osh2014-sprit-of-tdd
TDDのサイクル
小さく素早く回す
≒
フィードバックを早く得る
#ngtnet 9
TDDの黄金の回転
#ngtnet 10
TDD のこころ @ OSH2014
http://www.slideshare.net/t_wada/osh2014-sprit-of-tdd
動作するきれいなコード
Clean code that works
#ngtnet 11
Beautiful
動作するきれいなコード
#ngtnet 12
新装版リファクタリング(マーチン・ファウラー著、オーム社刊)https://estore.ohmsha.co.jp/titles/978427405019P
リーダブルコード(ダスティン・ボズウェル、トレバー・フォシェ著、O’REILLY刊)
https://www.oreilly.co.jp/books/9784873115658/
動作するきれいなコード
#ngtnet 13
C# 実践開発手法(ゲイリー・マクリーン・ホール著、日経BP社刊)
http://ec.nikkeibp.co.jp/item/books/P98470.html
Head First デザインパターン(エリック&エリザベス・フリーマン、キャシー・シエラ、バートベイツ著、O’REILLY刊)
https://www.oreilly.co.jp/books/4873112494/
動作するきれいなコード
#ngtnet 14
.NETのクラスライブラリ設計(Krzysztof Cwalina、Brad Abrams著、日経BP社刊)http://ec.nikkeibp.co.jp/item/books/P98470.html
TDDの目的
#ngtnet 15
TDDの目的
テストは手段であり目的ではない
動作するきれいなコードは
変化に対応しやすい
変化に対応しやすいということは
不安が少ない
不安の少ない状態≒健康
#ngtnet 16
TDDの目的
健康なコード
健康な体
健康なチーム
#ngtnet 17
.NET開発におけるTDD
#ngtnet 18
.NET開発におけるTDD
テスティングフレームワーク
およびサポートツール
ソリューション構成
テストコード
テスト実行
#ngtnet 19
テスティングフレームワーク
MSTest
VS標準搭載でお手軽さNo.1
NUnit
*Unit系正統派で手堅い
xUnit.net
新たに見直された次世代フレームワーク
#ngtnet 20
テスティングフレームワーク
個人的オススメは2つのどちらか
MSTest
入門には最適
NUnit
情報が多い
#ngtnet 21
サポートツール
テストアダプター
VS上でMSTest以外も実行可能にする拡張
NUnit3 Test Adapterhttps://visualstudiogallery.msdn.microsoft.com/0da0f6bd-9bb6-4ae3-87a8-537788622f2d
xUnit.net runner for Visual Studiohttps://visualstudiogallery.msdn.microsoft.com/463c5987-f82b-46c8-a97e-b1cde42b9099
#ngtnet 22
サポートツール
Chaining Assertion
A.Is(B)でテストが書ける
#ngtnet 23
Chaining Assertion – CodePlex
http://chainingassertion.codeplex.com/
ソリューション構成
複数プロジェクトで構成する
テスト対象プロジェクト
アプリケーション(*.exe)or クラスライブラリ(*.dll)
(テスト対象の型はpublic or internal(※)に)
テストプロジェクト
MSTest : 単体テストプロジェクト
他 : クラスライブラリ
+ テスティングフレームワークへの参照
#ngtnet 24
※アセンブリ属性InternalsVisibleToの設定が必要
テストコード
#ngtnet 25
using Microsoft.VisualStudio.TestTools.UnitTesting;namespace Test.MSTest{
[TestClass]public class UnitTest1 // テストクラス
{[TestInitialize]public void SetUp() { /* テスト初期処理 */ }
[TestCleanup]public void TearDown() { /* テスト後処理 */ }
[TestMethod]public void TestSomething(){
// テスト主処理“実際の値”.Is(“期待する値");
}}
}
MSTest+Chaining Assertionのテストコード
テスト実行
テスト エクスプローラーで結果表示
#ngtnet 26
TDDの実例
#ngtnet 27
TDDの実例
FizzBuzzをTDDで作成してみます
#ngtnet 28
• 1から100までの整数を順番に出力する
• ただし、
• 値が3の倍数の場合は”Fizz”を
• 値が5の倍数の場合は”Buzz”を
• 値が3と5の公倍数の場合は”FizzBuzz”を
• それぞれ表示すること
設計
ざっと設計しToDoリストを作成する
正の整数の場合、その数値を文字列で返す
3の倍数の場合、”Fizz”を返す
5の倍数の場合、”Buzz”を返す
3と5の公倍数の場合、”FizzBuzz”を返す
0以下の場合、引数エラーにする
#ngtnet 29
最初のテスト作成
ToDoリストから一つ選び、
最初の失敗するテストを作成する
例)引数が1の場合、”1”を返す
自分が最初のユーザーとなり、
使いやすいAPI設計を考える
型名、メソッド名、引数や戻り値の型、etc…
#ngtnet 30
最初のテスト失敗
テストを実行して失敗することを確認する
正しく失敗することを担保するため
コンパイルエラーも失敗に含める
#ngtnet 31
仮実装(Fake It)
テストが成功する最速の実装を行う
定数やリテラルを使っても良い
例)”1”を返す
テストの妥当性を担保する
#ngtnet 32
最初のテスト成功
テストが成功することを確認する
#ngtnet 33
リファクタリング
テストが成功する状態を保ったまま、
コードを整理する
テストコードを整えることも含む
例)名前付き引数の名前を削除する
#ngtnet 34
次の失敗するテストを追加する
プログラミングを先にすすめるため、
小さな一歩となるテストを追加する
三角測量を行うこともある
1つの実装に対して2つのテストで三角
例)引数が2の場合、”2”を返す
#ngtnet 35
すべてのテストを実行
追加したテストのみ失敗することを確認する
他のテストも失敗する
=良くない設計の臭い
仕様でなく実装に対してテストしている
責務分割が不十分 など
#ngtnet 36
テストが成功するまで修正
仮実装の定数やリテラル等を
引数、変数に置き換える
例)引数を文字列にして返す
#ngtnet 37
リファクタリング
再びリファクタリング
fizzBuzzer変数をフィールドにし、
SetUpメソッドを導入する
冗長なテストを統合、削除する
#ngtnet 38
ToDoリストを更新する
完了したものを消す
1以上の場合、その数値を文字列で返す
3の倍数の場合、”Fizz”を返す
5の倍数の場合、”Buzz”を返す
3と5の公倍数の場合、”FizzBuzz”を返す
0以下の場合、引数エラーにする
#ngtnet 39
次のテストを追加する
例)3の倍数の場合、”Fizz”を返す
追加したテストのみ失敗することを確認
#ngtnet 40
明白な実装
実装が自明であれば
仮実装をスキップしてもよい
ギアを上げるイメージ
例)引数と3との剰余が0なら”Fizz”を返す
#ngtnet 41
以後同様に続ける
続きはデモで
#ngtnet 42
TDDの指針
#ngtnet 43
いつTDDを行うか
不安を感じたとき
ライブラリの使い方に自信がない
サードパーティの実装が信用出来ない など
使い捨てのコードでないとき
繰り返し実行しないテストはただのコスト
#ngtnet 44
いつTDDを行うか
GUIでないとき
GUIのテストコストは非常に高い
GUIの変更は頻繁にある
トライ&エラーであれこれしないとき
確定後のコードにテストを書いてもよい
≒テストファーストにこだわらない
#ngtnet 45
どんなテストが良いテスト?
F.I.R.S.T
Fast 高速
Independent 独立している
Repeatable 繰り返し実行可能
Self-Validating 手動での検証がない
Timely テストファースト
#ngtnet 46
どのようにテストを行うか
各種テスト技法を参考に
同値クラス
境界値分析
デシジョンテーブル
etc
#ngtnet 47
既存コードがある場合
テストのないコードはレガシーコードだ!
#ngtnet 48
レガシーコード改善ガイド
(マイケル・C・フェザーズ著、翔泳社刊)
http://www.shoeisha.co.jp/book/detail/9784798116839
最後に
#ngtnet 49
最後に
TDDはセンスではなくスキル
訓練次第で誰でも習得可能
自分1人でも始められる
安心を得て健康になろう
#ngtnet 50