テスト駆動開発(tdd) in .net #ngtnet

50
テスト駆動開発(TDD) in .NET 2016/5/7 - # ngtnet TAKANO Sho (高野 将)/ @ masaru_b_cl

Upload: -

Post on 22-Jan-2018

5.713 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: テスト駆動開発(TDD) in .NET #ngtnet

テスト駆動開発(TDD)in .NET

2016/5/7 - #ngtnet

TAKANO Sho(高野 将)/ @masaru_b_cl

Page 2: テスト駆動開発(TDD) in .NET #ngtnet

自己紹介

某SIerで働くDeveloper

そのかたわら執筆業も

#ngtnet 2

Page 3: テスト駆動開発(TDD) in .NET #ngtnet

今日お話すること

テスト駆動開発(TDD)とは?

.NET開発におけるTDD

TDDの実例

TDDの指針

#ngtnet 3

Page 4: テスト駆動開発(TDD) in .NET #ngtnet

テスト駆動開発(TDD)とは?

#ngtnet 4

Page 5: テスト駆動開発(TDD) in .NET #ngtnet

テスト駆動開発(TDD)とは?

ケント・ベックが提唱した開発手法

#ngtnet 5

テスト駆動開発入門(ケント・ベック著、ピアソンエデュケーション刊)

http://www.amazon.co.jp/dp/4894717115

“「動作するきれいなコード」、

ロン・ジェフリーズの

この簡潔な言葉は、

TDD(テスト駆動開発)の目標である。

動作するきれいなコードは、

あらゆる理由で価値がある。 絶版

Page 6: テスト駆動開発(TDD) in .NET #ngtnet

TDDの進み方

#ngtnet 6

TDD のこころ @ OSH2014

http://www.slideshare.net/t_wada/osh2014-sprit-of-tdd

Page 7: テスト駆動開発(TDD) in .NET #ngtnet

TDDの進み方

#ngtnet 7

着実な道をいく

Page 8: テスト駆動開発(TDD) in .NET #ngtnet

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

Page 9: テスト駆動開発(TDD) in .NET #ngtnet

TDDのサイクル

小さく素早く回す

フィードバックを早く得る

#ngtnet 9

Page 10: テスト駆動開発(TDD) in .NET #ngtnet

TDDの黄金の回転

#ngtnet 10

TDD のこころ @ OSH2014

http://www.slideshare.net/t_wada/osh2014-sprit-of-tdd

Page 11: テスト駆動開発(TDD) in .NET #ngtnet

動作するきれいなコード

Clean code that works

#ngtnet 11

Beautiful

Page 12: テスト駆動開発(TDD) in .NET #ngtnet

動作するきれいなコード

#ngtnet 12

新装版リファクタリング(マーチン・ファウラー著、オーム社刊)https://estore.ohmsha.co.jp/titles/978427405019P

リーダブルコード(ダスティン・ボズウェル、トレバー・フォシェ著、O’REILLY刊)

https://www.oreilly.co.jp/books/9784873115658/

Page 13: テスト駆動開発(TDD) in .NET #ngtnet

動作するきれいなコード

#ngtnet 13

C# 実践開発手法(ゲイリー・マクリーン・ホール著、日経BP社刊)

http://ec.nikkeibp.co.jp/item/books/P98470.html

Head First デザインパターン(エリック&エリザベス・フリーマン、キャシー・シエラ、バートベイツ著、O’REILLY刊)

https://www.oreilly.co.jp/books/4873112494/

Page 14: テスト駆動開発(TDD) in .NET #ngtnet

動作するきれいなコード

#ngtnet 14

.NETのクラスライブラリ設計(Krzysztof Cwalina、Brad Abrams著、日経BP社刊)http://ec.nikkeibp.co.jp/item/books/P98470.html

Page 15: テスト駆動開発(TDD) in .NET #ngtnet

TDDの目的

#ngtnet 15

Page 16: テスト駆動開発(TDD) in .NET #ngtnet

TDDの目的

テストは手段であり目的ではない

動作するきれいなコードは

変化に対応しやすい

変化に対応しやすいということは

不安が少ない

不安の少ない状態≒健康

#ngtnet 16

Page 17: テスト駆動開発(TDD) in .NET #ngtnet

TDDの目的

健康なコード

健康な体

健康なチーム

#ngtnet 17

Page 18: テスト駆動開発(TDD) in .NET #ngtnet

.NET開発におけるTDD

#ngtnet 18

Page 19: テスト駆動開発(TDD) in .NET #ngtnet

.NET開発におけるTDD

テスティングフレームワーク

およびサポートツール

ソリューション構成

テストコード

テスト実行

#ngtnet 19

Page 20: テスト駆動開発(TDD) in .NET #ngtnet

テスティングフレームワーク

MSTest

VS標準搭載でお手軽さNo.1

NUnit

*Unit系正統派で手堅い

xUnit.net

新たに見直された次世代フレームワーク

#ngtnet 20

Page 21: テスト駆動開発(TDD) in .NET #ngtnet

テスティングフレームワーク

個人的オススメは2つのどちらか

MSTest

入門には最適

NUnit

情報が多い

#ngtnet 21

Page 22: テスト駆動開発(TDD) in .NET #ngtnet

サポートツール

テストアダプター

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

Page 23: テスト駆動開発(TDD) in .NET #ngtnet

サポートツール

Chaining Assertion

A.Is(B)でテストが書ける

#ngtnet 23

Chaining Assertion – CodePlex

http://chainingassertion.codeplex.com/

Page 24: テスト駆動開発(TDD) in .NET #ngtnet

ソリューション構成

複数プロジェクトで構成する

テスト対象プロジェクト

アプリケーション(*.exe)or クラスライブラリ(*.dll)

(テスト対象の型はpublic or internal(※)に)

テストプロジェクト

MSTest : 単体テストプロジェクト

他 : クラスライブラリ

+ テスティングフレームワークへの参照

#ngtnet 24

※アセンブリ属性InternalsVisibleToの設定が必要

Page 25: テスト駆動開発(TDD) in .NET #ngtnet

テストコード

#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のテストコード

Page 26: テスト駆動開発(TDD) in .NET #ngtnet

テスト実行

テスト エクスプローラーで結果表示

#ngtnet 26

Page 27: テスト駆動開発(TDD) in .NET #ngtnet

TDDの実例

#ngtnet 27

Page 28: テスト駆動開発(TDD) in .NET #ngtnet

TDDの実例

FizzBuzzをTDDで作成してみます

#ngtnet 28

• 1から100までの整数を順番に出力する

• ただし、

• 値が3の倍数の場合は”Fizz”を

• 値が5の倍数の場合は”Buzz”を

• 値が3と5の公倍数の場合は”FizzBuzz”を

• それぞれ表示すること

Page 29: テスト駆動開発(TDD) in .NET #ngtnet

設計

ざっと設計しToDoリストを作成する

正の整数の場合、その数値を文字列で返す

3の倍数の場合、”Fizz”を返す

5の倍数の場合、”Buzz”を返す

3と5の公倍数の場合、”FizzBuzz”を返す

0以下の場合、引数エラーにする

#ngtnet 29

Page 30: テスト駆動開発(TDD) in .NET #ngtnet

最初のテスト作成

ToDoリストから一つ選び、

最初の失敗するテストを作成する

例)引数が1の場合、”1”を返す

自分が最初のユーザーとなり、

使いやすいAPI設計を考える

型名、メソッド名、引数や戻り値の型、etc…

#ngtnet 30

Page 31: テスト駆動開発(TDD) in .NET #ngtnet

最初のテスト失敗

テストを実行して失敗することを確認する

正しく失敗することを担保するため

コンパイルエラーも失敗に含める

#ngtnet 31

Page 32: テスト駆動開発(TDD) in .NET #ngtnet

仮実装(Fake It)

テストが成功する最速の実装を行う

定数やリテラルを使っても良い

例)”1”を返す

テストの妥当性を担保する

#ngtnet 32

Page 33: テスト駆動開発(TDD) in .NET #ngtnet

最初のテスト成功

テストが成功することを確認する

#ngtnet 33

Page 34: テスト駆動開発(TDD) in .NET #ngtnet

リファクタリング

テストが成功する状態を保ったまま、

コードを整理する

テストコードを整えることも含む

例)名前付き引数の名前を削除する

#ngtnet 34

Page 35: テスト駆動開発(TDD) in .NET #ngtnet

次の失敗するテストを追加する

プログラミングを先にすすめるため、

小さな一歩となるテストを追加する

三角測量を行うこともある

1つの実装に対して2つのテストで三角

例)引数が2の場合、”2”を返す

#ngtnet 35

Page 36: テスト駆動開発(TDD) in .NET #ngtnet

すべてのテストを実行

追加したテストのみ失敗することを確認する

他のテストも失敗する

=良くない設計の臭い

仕様でなく実装に対してテストしている

責務分割が不十分 など

#ngtnet 36

Page 37: テスト駆動開発(TDD) in .NET #ngtnet

テストが成功するまで修正

仮実装の定数やリテラル等を

引数、変数に置き換える

例)引数を文字列にして返す

#ngtnet 37

Page 38: テスト駆動開発(TDD) in .NET #ngtnet

リファクタリング

再びリファクタリング

fizzBuzzer変数をフィールドにし、

SetUpメソッドを導入する

冗長なテストを統合、削除する

#ngtnet 38

Page 39: テスト駆動開発(TDD) in .NET #ngtnet

ToDoリストを更新する

完了したものを消す

1以上の場合、その数値を文字列で返す

3の倍数の場合、”Fizz”を返す

5の倍数の場合、”Buzz”を返す

3と5の公倍数の場合、”FizzBuzz”を返す

0以下の場合、引数エラーにする

#ngtnet 39

Page 40: テスト駆動開発(TDD) in .NET #ngtnet

次のテストを追加する

例)3の倍数の場合、”Fizz”を返す

追加したテストのみ失敗することを確認

#ngtnet 40

Page 41: テスト駆動開発(TDD) in .NET #ngtnet

明白な実装

実装が自明であれば

仮実装をスキップしてもよい

ギアを上げるイメージ

例)引数と3との剰余が0なら”Fizz”を返す

#ngtnet 41

Page 42: テスト駆動開発(TDD) in .NET #ngtnet

以後同様に続ける

続きはデモで

#ngtnet 42

Page 43: テスト駆動開発(TDD) in .NET #ngtnet

TDDの指針

#ngtnet 43

Page 44: テスト駆動開発(TDD) in .NET #ngtnet

いつTDDを行うか

不安を感じたとき

ライブラリの使い方に自信がない

サードパーティの実装が信用出来ない など

使い捨てのコードでないとき

繰り返し実行しないテストはただのコスト

#ngtnet 44

Page 45: テスト駆動開発(TDD) in .NET #ngtnet

いつTDDを行うか

GUIでないとき

GUIのテストコストは非常に高い

GUIの変更は頻繁にある

トライ&エラーであれこれしないとき

確定後のコードにテストを書いてもよい

≒テストファーストにこだわらない

#ngtnet 45

Page 46: テスト駆動開発(TDD) in .NET #ngtnet

どんなテストが良いテスト?

F.I.R.S.T

Fast 高速

Independent 独立している

Repeatable 繰り返し実行可能

Self-Validating 手動での検証がない

Timely テストファースト

#ngtnet 46

Page 47: テスト駆動開発(TDD) in .NET #ngtnet

どのようにテストを行うか

各種テスト技法を参考に

同値クラス

境界値分析

デシジョンテーブル

etc

#ngtnet 47

Page 48: テスト駆動開発(TDD) in .NET #ngtnet

既存コードがある場合

テストのないコードはレガシーコードだ!

#ngtnet 48

レガシーコード改善ガイド

(マイケル・C・フェザーズ著、翔泳社刊)

http://www.shoeisha.co.jp/book/detail/9784798116839

Page 49: テスト駆動開発(TDD) in .NET #ngtnet

最後に

#ngtnet 49

Page 50: テスト駆動開発(TDD) in .NET #ngtnet

最後に

TDDはセンスではなくスキル

訓練次第で誰でも習得可能

自分1人でも始められる

安心を得て健康になろう

#ngtnet 50