SlideShare une entreprise Scribd logo
1  sur  38
2008/7/26

タダで始めるテストファースト入門
C# Express + NUnit

biac
http://bluewatersoft.cocolog-nifty.com/

わんくま同盟 名古屋勉強会 #3
自己紹介
• 山本 康彦 ( biac )

– いまだにプログラムを書きたがる 51 歳
– http://bluewatersoft.cocolog-nifty.com/blog/cat8051143/

• 名古屋のとある ISV 勤務

– 現在、 WPF を使った業務アプリケーションの
開発プロジェクトで品質保証を担当
– MFS Agile を部分的に実施中

• もとは機械の設計屋さん

– ものごとの見方・考え方が、きっとズレてる

わんくま同盟 名古屋勉強会 #3
用意するもの
• 開発環境とテストフレームワーク
– C# 2008 Express
http://www.microsoft.com/japan/msdn/vstudio/Express/

– NUnit 2.4.7
http://www.nunit.org/index.php

• あるといいなぁ
– 静的コード分析ツール FxCop 1.35
– テストカバレッジ計測ツール PartCover

わんくま同盟 名古屋勉強会 #3
テスト駆動開発 と テストファースト
• この図の全体がテスト駆動開発 ( TDD ) で、
テストファースト技法はその一部。 ( 点線内 )
テスト失敗
( RED )

テストコード
追加・修正

製品コード
リファクタリン
グ

製品コード
追加・修正

テスト成功
( GREEN )

わんくま同盟 名古屋勉強会 #3
最初のテスト
• ソリューションとテストプロジェクトを
作る。
• テストプロジェクトに参照設定を追加
nunit.framework
• テスト : NUnit Framework をちゃんと呼
び出すことができるか ?

わんくま同盟 名古屋勉強会 #3
最初のテスト ( コード )

using NUnit.Framework;

namespace Wankuma.SorterSampleTest {
[TestFixture]
public class WankumaSorterTest {

}

•

}

[Test]
[Description(" 初めての NUnit テスト ")]
public void FirstTest() {
Assert.Fail(" ちゃんと Assert できました ! (^^;");
}
-------- src00.sln --------

このテストは失敗します ( レッド )
失敗させようとして、 失敗した → ちゃんと動いている !

わんくま同盟 名古屋勉強会 #3
わんくま同盟 名古屋勉強会 #3
ソートしてくれるクラスを作ろう
• 仕様
– 入出力は int の配列
– とりあえず、 昇順にソート

• 最初に考えること – どんなふうに使う ?
– クラス名、 メソッドシグネチャを決める
int[] input = ・・・
WankumaSorter sorter = new WankumaSorter();
int[] result = sorter.Sort(input);

わんくま同盟 名古屋勉強会 #3
テストケース : n = 1
• 最初は、 仕様の一番簡単なところから。
n = 1 のとき
入力 : int[] input = { 7 } // 数字 1 つ
結果 : int[] result = { 7 }
※ 簡単なところから、 テストをちょこっと、
製品をちょこっと…
考えなきゃいけないことのスコープを小さくし
て、 シンプルに進めていく。

わんくま同盟 名古屋勉強会 #3
テストケース : n = 1 ( テストコード )
[Test]
[Description("n=1 のとき ( 何もしない )")]
public void SortTestWith1Item() {
// テストの準備
int[] input = { 7 };
// テスト実行
WankumaSorter sorter = new WankumaSorter();
int[] result = sorter.Sort(input);
// テスト結果の検証
Assert.AreEqual(1, result.Length);
Assert.AreEqual(7, result[0]);
}

// 使ったリソースの後始末 … 今回は無し

※ 検証用比較データ ( 上では 1 とか 7 ) は、 テスト対象とは独立して生成したものであること
。

わんくま同盟 名古屋勉強会 #3
テストケース : n = 1 ( 製品コード )
•
1.

テストを通るギリギリのコードで製品を実装
していく。
まず、 コンパイルが通るように。 製品のプロ
ジェクトと WankumaSorter クラスを作る。

namespace Wankuma.SorterSample {
public class WankumaSorter {
public int[] Sort(int[] input) {
return null; // ← とりあえず何か返す
}
}
}

わんくま同盟 名古屋勉強会 #3
• 2. テスト実行 --- 失敗します ( RED )
– まだ実装のまともな中身が無いんですから、
失敗しなきゃいけないですね。 ちゃんと失敗
することを確認します。
– 失敗するはずだと思っていて、 万一成功して
しまったら… なにか見落としていることがあ
るはずですね。

わんくま同盟 名古屋勉強会 #3
• 3. 製品の実装 --- テストに通る最小限度
– このテストを通すには、 { 7 } を返してやれ
ばいいんです。 ( シンプルに ! )

• 4. テスト実行 --- 成功します ( GREEN !
)
namespace Wankuma.SorterSample {
public class WankumaSorter {
public int[] Sort(int[] input) {
return new int[]{7};
}
}
}

-------- src01.sln --------

わんくま同盟 名古屋勉強会 #3
宿題 – その 1
• 最初に決めておくべきことは、これで
OK?
※ 帰ってくるのは同じオブジェクト ? それとも
?
→ Assert.AreSame() または
Assert.AreNotSame() を使ってテスト

わんくま同盟 名古屋勉強会 #3
テストケース : n = 2
• n = 2 のとき
入力 : int[] input = { 3, 5 } // 数字 2 つ
結果 : int[] result = { 3, 5 }
… これは、 何もせずそのまま返せば OK にな
っちゃうと思いますよね ?
簡単すぎなので、 パス。
入力 : int[] input = { 5, 3 } // 数字 2 つ
結果 : int[] result = { 3, 5 }
… これなら、 ちょっと製品の実装が進みそう。
わんくま同盟 名古屋勉強会 #3
テストケース : n = 2 ( テストコード )
[Test]
[Description("n=2 のとき。 逆順なら入れ替え。 ")]
public void SortTestWith2Items() {
int[] input = { 5, 3 };
WankumaSorter sorter = new WankumaSorter();
int[] result = sorter.Sort(input);

}

CollectionAssert.AreEqual(
new int[] { 3, 5 }, result
);

※ ちゃんとテストは失敗しますね ?
これから実装することに意味がある、 というものです

わんくま同盟 名古屋勉強会 #3
テストケース : n = 2 ( 製品コード )
•

こんな実装でどうでしょう ?
public int[] Sort(int[] input) {
//return new int[]{7};
if (input[0] > input[1]) {
int work = input[0];
input[0] = input[1];
input[1] = work;
}
return input;
}

•

さっき作ったテスト SortTestWith2Items() を
流すと …グリーン !
これで OK?
わんくま同盟 名古屋勉強会 #3
• テストを全部流してみましょう …レッド !? orz
なぜですか ?
n = 1 のときも、 2 つあると思って比較しちゃうからで
すね。
Sort() の最初に、 こんなのを付け加えて
if (input.Length == 1)
return input;

テストは… ? はい、オールグリーン !
※ いいかげんな実装だと思うでしょう。
しかし、 入力される配列要素数が 1 または 2 である、 という前提が正しいなら、 これで製
品として OK なんですよ。
public メソッドですから、 ガード句
if (input.Length > 2)
throw ArgumentOutOfRangeException();
なんてのをメソッドの先頭に加えれば完璧。

わんくま同盟 名古屋勉強会 #3
ちょっとリファクタリング
•

製品コードの

int work = input[0];
input[0] = input[1];
input[1] = work;
の部分は、 きっとこれからも使うでしょう。
この 3 行で、 値を入れ替えるという操作をやっています。
リファクタリングして、 値を入れ替えるというメソッドにしてお
きましょう。
※ Express でも、メソッドの抽出リファクタリングをサポートする機能は付いています。

if (input[0] > input[1]) {
Swap(ref input[0], ref input[1]);
}
private static void Swap(ref int n, ref int m) {
int work = n;
n = m;
m = work;
}

わんくま同盟 名古屋勉強会 #3
• リファクタリングしたら、 また全部のテストを
流して、 なにも壊していないことを確認してお
きましょう。
※ テストもリファクタリングしましょうか。
テストの実行と結果の検証を区別するため、
int[] result = sorter.Sort(input);
CollectionAssert.AreEqual(new int[] { 3, 5 }, result);

などと書いてきましたけど。
まぎらわしくなければ、

CollectionAssert.AreEqual(new int[] { 3, 5 }, sorter.Sort(input));

と 1 行にまとめて書いちゃっても同じですよね。

-------- src02.sln --------

わんくま同盟 名古屋勉強会 #3
テストケース : n = 3
• n = 3 のとき
入力 : int[] input = { 3, 7, 5 } // 数字 3 つ
結果 : int[] result = { 3, 5, 7 }
… これは失敗するでしょう。
※ どんなテストをどんな順序で作っていくと、効率よく
製品コードが育っていくか…
これは、 テストファーストで作っていくときの醍醐味
であり、 最も難しいところでもあります。
わんくま同盟 名古屋勉強会 #3
テストケース : n = 3 ( テストコード )
[Test]
[Description("n=3 のとき。 ")]
public void SortTestWith3Items() {
int[] input = { 3, 7, 5 };

}

WankumaSorter sorter = new WankumaSorter();
CollectionAssert.AreEqual(
new int[] { 3, 5, 7 }, sorter.Sort(input)
);

※ レッドを確認したら、 製品コードを変えます。
こんどは、配列の 2 つめと 3 つめも比較して、 逆順だったら入れ
替えるロジックを追加しましょうか ?
いや、 もう先が見えてますよね ?
4 つになったら、 また同じことが…

わんくま同盟 名古屋勉強会 #3
テストケース : n = 3 ( 製品コード )
そこで、 for 文で書き直すことにします。
public int[] Sort(int[] input) {
if (input.Length == 1)
return input;

}

for (int i = 0; i < (input.Length - 1); i++) {
if (input[i] > input[i+1]) {
Swap(ref input[i], ref input[i+1]);
}
}
return input;

わんくま同盟 名古屋勉強会 #3
テストケース : n = 3 ( テストコード )
・・・はい、 オールグリーン !
これで OK?
ちょっとテストがヌルイような気がしませんか ?
n = 3 のとき
入力 : int[] input = { 7, 5, 3 } // 数字 3 つ
結果 : int[] result = { 3, 5, 7 }
これはどうでしょう ?
テストを追加して、 走らせてみると… レッド !?
わんくま同盟 名古屋勉強会 #3
Wankuma.SorterSampleTest.WankumaSorterTest.SortTestWith3Items
:
Expected and actual are both <System.Int32[3]>
Values differ at index [0]
Expected: 3
But was: 5
•

配列の先頭が 3 になっていて欲しいのに、 帰ってきたのは 5 で
す。 なぜでしょう ?
隣同士の交換を、 先頭から見て行って一回ずつしかやってないか
らですね。
7, 5, 3
↓
0 番と 1 番を比較・交換
5, 7, 3
↓
1 番と 2 番を比較・交換
5, 3, 7 ← いまココ

わんくま同盟 名古屋勉強会 #3
テストケース : n = 3 ( 製品コード )
• for ループ 1 回で、一番大きな数字が一
番後ろに来ました。 そこは確定でしょう
。
• けれど、 そこより前はまだ大小関係が入
り乱れています。
• 外側に for ループを追加して、 内側の
for ループの終了位置を一つずつ減らしな
がら、ループを繰り返してあげる必要が
あるみたいです。
わんくま同盟 名古屋勉強会 #3
for (int j = input.Length - 1; j > 0; j--) {
for (int i = 0; i < j; i++) {
if (input[i] > input[i + 1]) {
Swap(ref input[i], ref input[i + 1]);
}
}
}

• さぁ、これで… オールグリーン !

-------- src03.sln --------

わんくま同盟 名古屋勉強会 #3
わんくま同盟 名古屋勉強会 #3
ムダな子はいねぇが~ !?
• 結局、 ソートのロジックは二重ループになりま
した。
ちょっといじわるなテストを考えてみます。
• n = 5 のとき
入力配列 : 1, 2, 3, 5, 7 ( 数字 5 つ )
結果配列 : 1, 2, 3, 5, 7
• このとき、 Sort() の中で、 大小比較が何回行
われるでしょう ?
頭から比較していって最後まで 4 回比較してみ
れば、 すでに整列していることが分かります。
4 回より多く比較するのはムダってものです。
わんくま同盟 名古屋勉強会 #3
またちょびッとリファクタリング
• そこで、 比較回数を計測できるようにリ
ファクタリングしてから、プローブを突
っ込みます。
• リファクタリング - 比較部分をメソッド
に切り出す
if (IsNotInOrder(input[i], input[i + 1])) {
Swap(ref input[i], ref input[i + 1]);
}
private static bool IsNotInOrder(int lead, int trail ) {
return (lead > trail);
}

わんくま同盟 名古屋勉強会 #3
テストプローブの挿入 ( 製品コード )
• オールグリーンを確認したら、 プローブ
を仕込みます。
#if DEBUG
public static int TestCompareCount;
#endif
private static bool IsNotInOrder(int lead, int trail ) {
#if DEBUG
TestCompareCount++;
#endif
return (lead > trail);
}

わんくま同盟 名古屋勉強会 #3
テストケース : 最小の比較回数 ( テストコー
ド)

• すると、 比較は 4 回だけにしてほしい、
というテストが書けます。
[Test]
[Description("n=5 のとき。 最初から整列していると、比較は 4 回。 ")]
public void SortTestWith5Items() {
#if DEBUG // ← プローブは DEBUG 時のみ有効なので、 テストも。
int[] input = { 1, 2, 3, 5, 7 };
WankumaSorter sorter = new WankumaSorter();
sorter.TestCompareCount = 0;
CollectionAssert.AreEqual(new int[] { 1, 2, 3, 5, 7 },
sorter.Sort(input)); // ← 念のためソートできてることを確認
Assert.AreEqual(4, sorter.TestCompareCount);
#endif
}

わんくま同盟 名古屋勉強会 #3
• テストしてみましょう… レッドです。

Wankuma.SorterSampleTest.WankumaSorterTest.SortTestWith5Items:
Expected: 4
But was: 10

• なんと 10 回も比較しています。
これはどうしたものでしょう… ?
ひとつの手として、 Swap() した回数を数えて
おいて、 内側のループを抜けたときに 1 回も交
換していなかったら、もう比較する必要も無い
、と判定してやるのはどうでしょう ?
わんくま同盟 名古屋勉強会 #3
Swap カウンタの導入 ( 製品コード )
• Swap() メソッドを改修します。
• こんどのカウンタは、 さっきのプローブ用のとは違っ
て、 どんな呼ばれ方をするか分からない製品コードの
部分になりますから、 static ではダメです。 ちゃんと
メンバ変数にしておきましょう。
private int _swapCount;
private void Swap(ref int n, ref int m) {
this._swapCount++;

}

int work = n;
n = m;
m = work;

わんくま同盟 名古屋勉強会 #3
• そして、 内側のループに入る前に _swapCount をゼロ
クリアして、出てきたときにゼロのままだったら、 ソ
ート終了と判定します。
public int[] Sort(int[] input) {
if (input.Length == 1) return input;
for (int stop = input.Length - 1; stop > 0; stop--) {
this._swapCount = 0;
for (int i = 0; i < stop; i++) {
if (IsNotInOrder(input[i], input[i + 1])) {
Swap(ref input[i], ref input[i + 1]);
}
}
if ( this._swapCount == 0 ) break;
}
return input;
}
// -------- src04.sln --------

わんくま同盟 名古屋勉強会 #3
宿題 ( その 2)
• まだ不足しているテストケースがある。
• 降順にもソートせよ。
昇順 / 降順の切り替えをどうやるかも決定
せよ。 ( ただし、 既存のテストコードは
、 そのまま通ること。 )
• int 以外の型も使えるように拡張せよ。
( 数値だけでなく、 文字列はどうか ?)

わんくま同盟 名古屋勉強会 #3
補足 : 例外が出るところをテスト
• 製品コードから例外が出る ( そういう仕
様である ) ことを確認するためのテスト
• ExpectedException 属性を使うか、 ある
いは、 次のように try ~ catch する。
WankumaSorter sorter = new WankumaSorter();
try {
int[] result = sorter.Sort(null);
Assert.Fail(“ この行に来たらアウト !");
}
catch (ArgumentNullException) {
// OK! --- ここで例外メッセージの検査なども出来る
}

わんくま同盟 名古屋勉強会 #3
参考
• URL
– NUnit 入門 Test First のススメ ( 川俣 晶 )

http://www.atmarkit.co.jp/fdotnet/tools/nunit2/nunit2_01.html

– 「テスト駆動開発」はプログラマのストレスを軽減するか
? ( 川俣 晶 )
http://www.atmarkit.co.jp/fdotnet/special/tdd/tdd_01.html

– .NET 開発者のためのリファクタリング入門 ( 川俣 晶 )

http://www.atmarkit.co.jp/fdotnet/special/refactoring/refactoring_01.html

• 書籍

– テスト駆動開発入門 (ケント ベック)
– Microsoft.NET でのテスト駆動開発 ( ジェームス・ニューカ
ーク )
– リファクタリング ― プログラムの体質改善テクニック ( マ
ーチン ファウラー )

わんくま同盟 名古屋勉強会 #3

Contenu connexe

Tendances

Xp Terakoya 05
Xp Terakoya 05Xp Terakoya 05
Xp Terakoya 05
takepu
 

Tendances (20)

テストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3devテストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3dev
 
TypeScript 入門してみる
TypeScript 入門してみるTypeScript 入門してみる
TypeScript 入門してみる
 
Hey It's Not My TDD!
Hey It's Not My TDD!Hey It's Not My TDD!
Hey It's Not My TDD!
 
チラ見せ♡ナイト@20150410 LT公開用
チラ見せ♡ナイト@20150410 LT公開用チラ見せ♡ナイト@20150410 LT公開用
チラ見せ♡ナイト@20150410 LT公開用
 
プロト〜サービスアウトまでの開発支援ツールの作り方〜CrystalFantasia〜
プロト〜サービスアウトまでの開発支援ツールの作り方〜CrystalFantasia〜プロト〜サービスアウトまでの開発支援ツールの作り方〜CrystalFantasia〜
プロト〜サービスアウトまでの開発支援ツールの作り方〜CrystalFantasia〜
 
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
 
開発ビギナーだけじゃない!インフラエンジニア & マネージャー にも知ってほしいテスト自動化と品質管理
開発ビギナーだけじゃない!インフラエンジニア & マネージャー にも知ってほしいテスト自動化と品質管理開発ビギナーだけじゃない!インフラエンジニア & マネージャー にも知ってほしいテスト自動化と品質管理
開発ビギナーだけじゃない!インフラエンジニア & マネージャー にも知ってほしいテスト自動化と品質管理
 
アプリ開発を効率化する 方法あれこれ
アプリ開発を効率化する 方法あれこれアプリ開発を効率化する 方法あれこれ
アプリ開発を効率化する 方法あれこれ
 
Team Foundation Server / Visual Studio Online を利用したチーム開発の実践
Team Foundation Server / Visual Studio Online を利用したチーム開発の実践Team Foundation Server / Visual Studio Online を利用したチーム開発の実践
Team Foundation Server / Visual Studio Online を利用したチーム開発の実践
 
Tddのすゝめ
TddのすゝめTddのすゝめ
Tddのすゝめ
 
FriendlyによるWindowsアプリテスト自動化手法 基礎技術編
FriendlyによるWindowsアプリテスト自動化手法 基礎技術編FriendlyによるWindowsアプリテスト自動化手法 基礎技術編
FriendlyによるWindowsアプリテスト自動化手法 基礎技術編
 
TFSの導入提案
TFSの導入提案TFSの導入提案
TFSの導入提案
 
Android meets RxJava - 渋谷Java#6
Android meets RxJava - 渋谷Java#6Android meets RxJava - 渋谷Java#6
Android meets RxJava - 渋谷Java#6
 
Test Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるかTest Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるか
 
アジャイルサムライ壱の太刀 - 説得しないはじめないアジャイル開発のはじめ形 -
アジャイルサムライ壱の太刀 - 説得しないはじめないアジャイル開発のはじめ形 -アジャイルサムライ壱の太刀 - 説得しないはじめないアジャイル開発のはじめ形 -
アジャイルサムライ壱の太刀 - 説得しないはじめないアジャイル開発のはじめ形 -
 
TypeScript 独習会
TypeScript 独習会TypeScript 独習会
TypeScript 独習会
 
TypeScriptをオススメする理由
TypeScriptをオススメする理由TypeScriptをオススメする理由
TypeScriptをオススメする理由
 
Azureを使って手軽にブラウザテストの自動化をはじめよう
Azureを使って手軽にブラウザテストの自動化をはじめようAzureを使って手軽にブラウザテストの自動化をはじめよう
Azureを使って手軽にブラウザテストの自動化をはじめよう
 
Xp Terakoya 05
Xp Terakoya 05Xp Terakoya 05
Xp Terakoya 05
 
ポストJenkins時代のCI戦略
ポストJenkins時代のCI戦略ポストJenkins時代のCI戦略
ポストJenkins時代のCI戦略
 

Similaire à タダで始めるテストファースト入門 ~ C# Express + NUnit

関西Php勉強会のlimeの話
関西Php勉強会のlimeの話関西Php勉強会のlimeの話
関西Php勉強会のlimeの話
Hisateru Tanaka
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテスト
Yohei Sato
 
SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78
SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78
SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78
Katsuya Shimizu
 
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::UnitRuby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unit
higaki
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
Takuya Tsuchida
 
Unit testで定時帰宅!
Unit testで定時帰宅!Unit testで定時帰宅!
Unit testで定時帰宅!
Funato Takashi
 

Similaire à タダで始めるテストファースト入門 ~ C# Express + NUnit (20)

第3回 JavaScriptから始めるプログラミング2016
第3回 JavaScriptから始めるプログラミング2016第3回 JavaScriptから始めるプログラミング2016
第3回 JavaScriptから始めるプログラミング2016
 
関西Php勉強会のlimeの話
関西Php勉強会のlimeの話関西Php勉強会のlimeの話
関西Php勉強会のlimeの話
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
 
Ruby test double
Ruby test doubleRuby test double
Ruby test double
 
テストコードの定型化
テストコードの定型化テストコードの定型化
テストコードの定型化
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテスト
 
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
 
SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78
SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78
SQL Server 単体テストフレームワーク tSQLt の紹介 #clrh78
 
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::UnitRuby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unit
 
Nagoya.R #12 入門者講習
Nagoya.R #12 入門者講習Nagoya.R #12 入門者講習
Nagoya.R #12 入門者講習
 
最近の単体テスト
最近の単体テスト最近の単体テスト
最近の単体テスト
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テスト
 
Introduction to Spock
Introduction to SpockIntroduction to Spock
Introduction to Spock
 
モデル検査入門 #wacate
モデル検査入門 #wacateモデル検査入門 #wacate
モデル検査入門 #wacate
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
 
EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発
 
Unit testで定時帰宅!
Unit testで定時帰宅!Unit testで定時帰宅!
Unit testで定時帰宅!
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 

Plus de Yasuhiko Yamamoto

わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ
わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよわんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ
わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ
Yasuhiko Yamamoto
 

Plus de Yasuhiko Yamamoto (20)

わんくま名古屋 #40 (20161217) Xamarinで自動化テストしよう
わんくま名古屋 #40 (20161217) Xamarinで自動化テストしようわんくま名古屋 #40 (20161217) Xamarinで自動化テストしよう
わんくま名古屋 #40 (20161217) Xamarinで自動化テストしよう
 
わんくま名古屋 #38 (20160521) Xamarin入門
わんくま名古屋 #38 (20160521) Xamarin入門わんくま名古屋 #38 (20160521) Xamarin入門
わんくま名古屋 #38 (20160521) Xamarin入門
 
UWP アプリを JavaScript で作る 3つの方法
UWP アプリを JavaScript で作る 3つの方法UWP アプリを JavaScript で作る 3つの方法
UWP アプリを JavaScript で作る 3つの方法
 
無償のVisual studioで作るクライアント アプリ
無償のVisual studioで作るクライアント アプリ無償のVisual studioで作るクライアント アプリ
無償のVisual studioで作るクライアント アプリ
 
わんくま名古屋 #37 (20151114) Windows 10 UWP アプリ開発入門(実践編)
わんくま名古屋 #37 (20151114) Windows 10 UWP アプリ開発入門(実践編)わんくま名古屋 #37 (20151114) Windows 10 UWP アプリ開発入門(実践編)
わんくま名古屋 #37 (20151114) Windows 10 UWP アプリ開発入門(実践編)
 
わんくま名古屋 #37 (20151114) TDD道場 #25
わんくま名古屋 #37 (20151114) TDD道場 #25わんくま名古屋 #37 (20151114) TDD道場 #25
わんくま名古屋 #37 (20151114) TDD道場 #25
 
わんくま名古屋#36 (20150725) Windows 10 ユニバーサル Windows アプリ開発入門
わんくま名古屋#36 (20150725) Windows 10 ユニバーサル Windows アプリ開発入門わんくま名古屋#36 (20150725) Windows 10 ユニバーサル Windows アプリ開発入門
わんくま名古屋#36 (20150725) Windows 10 ユニバーサル Windows アプリ開発入門
 
第8回 業開中心会議 「Windows 10 ユニバーサルアプリの概要」
第8回業開中心会議 「Windows 10 ユニバーサルアプリの概要」第8回業開中心会議 「Windows 10 ユニバーサルアプリの概要」
第8回 業開中心会議 「Windows 10 ユニバーサルアプリの概要」
 
わんくま名古屋#34(20150214) TDD道場#22
わんくま名古屋#34(20150214) TDD道場#22わんくま名古屋#34(20150214) TDD道場#22
わんくま名古屋#34(20150214) TDD道場#22
 
わんくま名古屋#33(20141115) モノ作り半生
わんくま名古屋#33(20141115) モノ作り半生わんくま名古屋#33(20141115) モノ作り半生
わんくま名古屋#33(20141115) モノ作り半生
 
わんくま名古屋#33(20141115) TDD道場#21
わんくま名古屋#33(20141115) TDD道場#21わんくま名古屋#33(20141115) TDD道場#21
わんくま名古屋#33(20141115) TDD道場#21
 
開発ツールを買わずに作る♪ ユニバーサルWindowsアプリ!
開発ツールを買わずに作る♪ ユニバーサルWindowsアプリ!開発ツールを買わずに作る♪ ユニバーサルWindowsアプリ!
開発ツールを買わずに作る♪ ユニバーサルWindowsアプリ!
 
わんくま名古屋 #32 (20140823) TDD道場 #20
わんくま名古屋 #32 (20140823) TDD道場 #20わんくま名古屋 #32 (20140823) TDD道場 #20
わんくま名古屋 #32 (20140823) TDD道場 #20
 
わんくま名古屋#31(20140524) TDD道場 #19
わんくま名古屋#31(20140524) TDD道場 #19わんくま名古屋#31(20140524) TDD道場 #19
わんくま名古屋#31(20140524) TDD道場 #19
 
わんくま名古屋#31(20140524) ユニバーサルWindowsアプリ開発の勧め
わんくま名古屋#31(20140524) ユニバーサルWindowsアプリ開発の勧めわんくま名古屋#31(20140524) ユニバーサルWindowsアプリ開発の勧め
わんくま名古屋#31(20140524) ユニバーサルWindowsアプリ開発の勧め
 
Windows ストア アプリでスレッド間排他処理
Windows ストア アプリでスレッド間排他処理Windows ストア アプリでスレッド間排他処理
Windows ストア アプリでスレッド間排他処理
 
Windows 8.1 Update 1 の噂をまとめてみた
Windows 8.1 Update 1 の噂をまとめてみたWindows 8.1 Update 1 の噂をまとめてみた
Windows 8.1 Update 1 の噂をまとめてみた
 
わんくま名古屋 #29 (2013/11/23) TDD道場 #17
わんくま名古屋 #29 (2013/11/23) TDD道場 #17わんくま名古屋 #29 (2013/11/23) TDD道場 #17
わんくま名古屋 #29 (2013/11/23) TDD道場 #17
 
わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ
わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよわんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ
わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ
 
Windows 8.1 ストア アプリ first look for 8.0 developers! [ss]
Windows 8.1 ストア アプリ first look for 8.0 developers! [ss]Windows 8.1 ストア アプリ first look for 8.0 developers! [ss]
Windows 8.1 ストア アプリ first look for 8.0 developers! [ss]
 

タダで始めるテストファースト入門 ~ C# Express + NUnit

  • 1. 2008/7/26 タダで始めるテストファースト入門 C# Express + NUnit biac http://bluewatersoft.cocolog-nifty.com/ わんくま同盟 名古屋勉強会 #3
  • 2. 自己紹介 • 山本 康彦 ( biac ) – いまだにプログラムを書きたがる 51 歳 – http://bluewatersoft.cocolog-nifty.com/blog/cat8051143/ • 名古屋のとある ISV 勤務 – 現在、 WPF を使った業務アプリケーションの 開発プロジェクトで品質保証を担当 – MFS Agile を部分的に実施中 • もとは機械の設計屋さん – ものごとの見方・考え方が、きっとズレてる わんくま同盟 名古屋勉強会 #3
  • 3. 用意するもの • 開発環境とテストフレームワーク – C# 2008 Express http://www.microsoft.com/japan/msdn/vstudio/Express/ – NUnit 2.4.7 http://www.nunit.org/index.php • あるといいなぁ – 静的コード分析ツール FxCop 1.35 – テストカバレッジ計測ツール PartCover わんくま同盟 名古屋勉強会 #3
  • 4. テスト駆動開発 と テストファースト • この図の全体がテスト駆動開発 ( TDD ) で、 テストファースト技法はその一部。 ( 点線内 ) テスト失敗 ( RED ) テストコード 追加・修正 製品コード リファクタリン グ 製品コード 追加・修正 テスト成功 ( GREEN ) わんくま同盟 名古屋勉強会 #3
  • 5. 最初のテスト • ソリューションとテストプロジェクトを 作る。 • テストプロジェクトに参照設定を追加 nunit.framework • テスト : NUnit Framework をちゃんと呼 び出すことができるか ? わんくま同盟 名古屋勉強会 #3
  • 6. 最初のテスト ( コード ) using NUnit.Framework; namespace Wankuma.SorterSampleTest { [TestFixture] public class WankumaSorterTest { } • } [Test] [Description(" 初めての NUnit テスト ")] public void FirstTest() { Assert.Fail(" ちゃんと Assert できました ! (^^;"); } -------- src00.sln -------- このテストは失敗します ( レッド ) 失敗させようとして、 失敗した → ちゃんと動いている ! わんくま同盟 名古屋勉強会 #3
  • 8. ソートしてくれるクラスを作ろう • 仕様 – 入出力は int の配列 – とりあえず、 昇順にソート • 最初に考えること – どんなふうに使う ? – クラス名、 メソッドシグネチャを決める int[] input = ・・・ WankumaSorter sorter = new WankumaSorter(); int[] result = sorter.Sort(input); わんくま同盟 名古屋勉強会 #3
  • 9. テストケース : n = 1 • 最初は、 仕様の一番簡単なところから。 n = 1 のとき 入力 : int[] input = { 7 } // 数字 1 つ 結果 : int[] result = { 7 } ※ 簡単なところから、 テストをちょこっと、 製品をちょこっと… 考えなきゃいけないことのスコープを小さくし て、 シンプルに進めていく。 わんくま同盟 名古屋勉強会 #3
  • 10. テストケース : n = 1 ( テストコード ) [Test] [Description("n=1 のとき ( 何もしない )")] public void SortTestWith1Item() { // テストの準備 int[] input = { 7 }; // テスト実行 WankumaSorter sorter = new WankumaSorter(); int[] result = sorter.Sort(input); // テスト結果の検証 Assert.AreEqual(1, result.Length); Assert.AreEqual(7, result[0]); } // 使ったリソースの後始末 … 今回は無し ※ 検証用比較データ ( 上では 1 とか 7 ) は、 テスト対象とは独立して生成したものであること 。 わんくま同盟 名古屋勉強会 #3
  • 11. テストケース : n = 1 ( 製品コード ) • 1. テストを通るギリギリのコードで製品を実装 していく。 まず、 コンパイルが通るように。 製品のプロ ジェクトと WankumaSorter クラスを作る。 namespace Wankuma.SorterSample { public class WankumaSorter { public int[] Sort(int[] input) { return null; // ← とりあえず何か返す } } } わんくま同盟 名古屋勉強会 #3
  • 12. • 2. テスト実行 --- 失敗します ( RED ) – まだ実装のまともな中身が無いんですから、 失敗しなきゃいけないですね。 ちゃんと失敗 することを確認します。 – 失敗するはずだと思っていて、 万一成功して しまったら… なにか見落としていることがあ るはずですね。 わんくま同盟 名古屋勉強会 #3
  • 13. • 3. 製品の実装 --- テストに通る最小限度 – このテストを通すには、 { 7 } を返してやれ ばいいんです。 ( シンプルに ! ) • 4. テスト実行 --- 成功します ( GREEN ! ) namespace Wankuma.SorterSample { public class WankumaSorter { public int[] Sort(int[] input) { return new int[]{7}; } } } -------- src01.sln -------- わんくま同盟 名古屋勉強会 #3
  • 14. 宿題 – その 1 • 最初に決めておくべきことは、これで OK? ※ 帰ってくるのは同じオブジェクト ? それとも ? → Assert.AreSame() または Assert.AreNotSame() を使ってテスト わんくま同盟 名古屋勉強会 #3
  • 15. テストケース : n = 2 • n = 2 のとき 入力 : int[] input = { 3, 5 } // 数字 2 つ 結果 : int[] result = { 3, 5 } … これは、 何もせずそのまま返せば OK にな っちゃうと思いますよね ? 簡単すぎなので、 パス。 入力 : int[] input = { 5, 3 } // 数字 2 つ 結果 : int[] result = { 3, 5 } … これなら、 ちょっと製品の実装が進みそう。 わんくま同盟 名古屋勉強会 #3
  • 16. テストケース : n = 2 ( テストコード ) [Test] [Description("n=2 のとき。 逆順なら入れ替え。 ")] public void SortTestWith2Items() { int[] input = { 5, 3 }; WankumaSorter sorter = new WankumaSorter(); int[] result = sorter.Sort(input); } CollectionAssert.AreEqual( new int[] { 3, 5 }, result ); ※ ちゃんとテストは失敗しますね ? これから実装することに意味がある、 というものです わんくま同盟 名古屋勉強会 #3
  • 17. テストケース : n = 2 ( 製品コード ) • こんな実装でどうでしょう ? public int[] Sort(int[] input) { //return new int[]{7}; if (input[0] > input[1]) { int work = input[0]; input[0] = input[1]; input[1] = work; } return input; } • さっき作ったテスト SortTestWith2Items() を 流すと …グリーン ! これで OK? わんくま同盟 名古屋勉強会 #3
  • 18. • テストを全部流してみましょう …レッド !? orz なぜですか ? n = 1 のときも、 2 つあると思って比較しちゃうからで すね。 Sort() の最初に、 こんなのを付け加えて if (input.Length == 1) return input; テストは… ? はい、オールグリーン ! ※ いいかげんな実装だと思うでしょう。 しかし、 入力される配列要素数が 1 または 2 である、 という前提が正しいなら、 これで製 品として OK なんですよ。 public メソッドですから、 ガード句 if (input.Length > 2) throw ArgumentOutOfRangeException(); なんてのをメソッドの先頭に加えれば完璧。 わんくま同盟 名古屋勉強会 #3
  • 19. ちょっとリファクタリング • 製品コードの int work = input[0]; input[0] = input[1]; input[1] = work; の部分は、 きっとこれからも使うでしょう。 この 3 行で、 値を入れ替えるという操作をやっています。 リファクタリングして、 値を入れ替えるというメソッドにしてお きましょう。 ※ Express でも、メソッドの抽出リファクタリングをサポートする機能は付いています。 if (input[0] > input[1]) { Swap(ref input[0], ref input[1]); } private static void Swap(ref int n, ref int m) { int work = n; n = m; m = work; } わんくま同盟 名古屋勉強会 #3
  • 20. • リファクタリングしたら、 また全部のテストを 流して、 なにも壊していないことを確認してお きましょう。 ※ テストもリファクタリングしましょうか。 テストの実行と結果の検証を区別するため、 int[] result = sorter.Sort(input); CollectionAssert.AreEqual(new int[] { 3, 5 }, result); などと書いてきましたけど。 まぎらわしくなければ、 CollectionAssert.AreEqual(new int[] { 3, 5 }, sorter.Sort(input)); と 1 行にまとめて書いちゃっても同じですよね。 -------- src02.sln -------- わんくま同盟 名古屋勉強会 #3
  • 21. テストケース : n = 3 • n = 3 のとき 入力 : int[] input = { 3, 7, 5 } // 数字 3 つ 結果 : int[] result = { 3, 5, 7 } … これは失敗するでしょう。 ※ どんなテストをどんな順序で作っていくと、効率よく 製品コードが育っていくか… これは、 テストファーストで作っていくときの醍醐味 であり、 最も難しいところでもあります。 わんくま同盟 名古屋勉強会 #3
  • 22. テストケース : n = 3 ( テストコード ) [Test] [Description("n=3 のとき。 ")] public void SortTestWith3Items() { int[] input = { 3, 7, 5 }; } WankumaSorter sorter = new WankumaSorter(); CollectionAssert.AreEqual( new int[] { 3, 5, 7 }, sorter.Sort(input) ); ※ レッドを確認したら、 製品コードを変えます。 こんどは、配列の 2 つめと 3 つめも比較して、 逆順だったら入れ 替えるロジックを追加しましょうか ? いや、 もう先が見えてますよね ? 4 つになったら、 また同じことが… わんくま同盟 名古屋勉強会 #3
  • 23. テストケース : n = 3 ( 製品コード ) そこで、 for 文で書き直すことにします。 public int[] Sort(int[] input) { if (input.Length == 1) return input; } for (int i = 0; i < (input.Length - 1); i++) { if (input[i] > input[i+1]) { Swap(ref input[i], ref input[i+1]); } } return input; わんくま同盟 名古屋勉強会 #3
  • 24. テストケース : n = 3 ( テストコード ) ・・・はい、 オールグリーン ! これで OK? ちょっとテストがヌルイような気がしませんか ? n = 3 のとき 入力 : int[] input = { 7, 5, 3 } // 数字 3 つ 結果 : int[] result = { 3, 5, 7 } これはどうでしょう ? テストを追加して、 走らせてみると… レッド !? わんくま同盟 名古屋勉強会 #3
  • 25. Wankuma.SorterSampleTest.WankumaSorterTest.SortTestWith3Items : Expected and actual are both <System.Int32[3]> Values differ at index [0] Expected: 3 But was: 5 • 配列の先頭が 3 になっていて欲しいのに、 帰ってきたのは 5 で す。 なぜでしょう ? 隣同士の交換を、 先頭から見て行って一回ずつしかやってないか らですね。 7, 5, 3 ↓ 0 番と 1 番を比較・交換 5, 7, 3 ↓ 1 番と 2 番を比較・交換 5, 3, 7 ← いまココ わんくま同盟 名古屋勉強会 #3
  • 26. テストケース : n = 3 ( 製品コード ) • for ループ 1 回で、一番大きな数字が一 番後ろに来ました。 そこは確定でしょう 。 • けれど、 そこより前はまだ大小関係が入 り乱れています。 • 外側に for ループを追加して、 内側の for ループの終了位置を一つずつ減らしな がら、ループを繰り返してあげる必要が あるみたいです。 わんくま同盟 名古屋勉強会 #3
  • 27. for (int j = input.Length - 1; j > 0; j--) { for (int i = 0; i < j; i++) { if (input[i] > input[i + 1]) { Swap(ref input[i], ref input[i + 1]); } } } • さぁ、これで… オールグリーン ! -------- src03.sln -------- わんくま同盟 名古屋勉強会 #3
  • 29. ムダな子はいねぇが~ !? • 結局、 ソートのロジックは二重ループになりま した。 ちょっといじわるなテストを考えてみます。 • n = 5 のとき 入力配列 : 1, 2, 3, 5, 7 ( 数字 5 つ ) 結果配列 : 1, 2, 3, 5, 7 • このとき、 Sort() の中で、 大小比較が何回行 われるでしょう ? 頭から比較していって最後まで 4 回比較してみ れば、 すでに整列していることが分かります。 4 回より多く比較するのはムダってものです。 わんくま同盟 名古屋勉強会 #3
  • 30. またちょびッとリファクタリング • そこで、 比較回数を計測できるようにリ ファクタリングしてから、プローブを突 っ込みます。 • リファクタリング - 比較部分をメソッド に切り出す if (IsNotInOrder(input[i], input[i + 1])) { Swap(ref input[i], ref input[i + 1]); } private static bool IsNotInOrder(int lead, int trail ) { return (lead > trail); } わんくま同盟 名古屋勉強会 #3
  • 31. テストプローブの挿入 ( 製品コード ) • オールグリーンを確認したら、 プローブ を仕込みます。 #if DEBUG public static int TestCompareCount; #endif private static bool IsNotInOrder(int lead, int trail ) { #if DEBUG TestCompareCount++; #endif return (lead > trail); } わんくま同盟 名古屋勉強会 #3
  • 32. テストケース : 最小の比較回数 ( テストコー ド) • すると、 比較は 4 回だけにしてほしい、 というテストが書けます。 [Test] [Description("n=5 のとき。 最初から整列していると、比較は 4 回。 ")] public void SortTestWith5Items() { #if DEBUG // ← プローブは DEBUG 時のみ有効なので、 テストも。 int[] input = { 1, 2, 3, 5, 7 }; WankumaSorter sorter = new WankumaSorter(); sorter.TestCompareCount = 0; CollectionAssert.AreEqual(new int[] { 1, 2, 3, 5, 7 }, sorter.Sort(input)); // ← 念のためソートできてることを確認 Assert.AreEqual(4, sorter.TestCompareCount); #endif } わんくま同盟 名古屋勉強会 #3
  • 33. • テストしてみましょう… レッドです。 Wankuma.SorterSampleTest.WankumaSorterTest.SortTestWith5Items: Expected: 4 But was: 10 • なんと 10 回も比較しています。 これはどうしたものでしょう… ? ひとつの手として、 Swap() した回数を数えて おいて、 内側のループを抜けたときに 1 回も交 換していなかったら、もう比較する必要も無い 、と判定してやるのはどうでしょう ? わんくま同盟 名古屋勉強会 #3
  • 34. Swap カウンタの導入 ( 製品コード ) • Swap() メソッドを改修します。 • こんどのカウンタは、 さっきのプローブ用のとは違っ て、 どんな呼ばれ方をするか分からない製品コードの 部分になりますから、 static ではダメです。 ちゃんと メンバ変数にしておきましょう。 private int _swapCount; private void Swap(ref int n, ref int m) { this._swapCount++; } int work = n; n = m; m = work; わんくま同盟 名古屋勉強会 #3
  • 35. • そして、 内側のループに入る前に _swapCount をゼロ クリアして、出てきたときにゼロのままだったら、 ソ ート終了と判定します。 public int[] Sort(int[] input) { if (input.Length == 1) return input; for (int stop = input.Length - 1; stop > 0; stop--) { this._swapCount = 0; for (int i = 0; i < stop; i++) { if (IsNotInOrder(input[i], input[i + 1])) { Swap(ref input[i], ref input[i + 1]); } } if ( this._swapCount == 0 ) break; } return input; } // -------- src04.sln -------- わんくま同盟 名古屋勉強会 #3
  • 36. 宿題 ( その 2) • まだ不足しているテストケースがある。 • 降順にもソートせよ。 昇順 / 降順の切り替えをどうやるかも決定 せよ。 ( ただし、 既存のテストコードは 、 そのまま通ること。 ) • int 以外の型も使えるように拡張せよ。 ( 数値だけでなく、 文字列はどうか ?) わんくま同盟 名古屋勉強会 #3
  • 37. 補足 : 例外が出るところをテスト • 製品コードから例外が出る ( そういう仕 様である ) ことを確認するためのテスト • ExpectedException 属性を使うか、 ある いは、 次のように try ~ catch する。 WankumaSorter sorter = new WankumaSorter(); try { int[] result = sorter.Sort(null); Assert.Fail(“ この行に来たらアウト !"); } catch (ArgumentNullException) { // OK! --- ここで例外メッセージの検査なども出来る } わんくま同盟 名古屋勉強会 #3
  • 38. 参考 • URL – NUnit 入門 Test First のススメ ( 川俣 晶 ) http://www.atmarkit.co.jp/fdotnet/tools/nunit2/nunit2_01.html – 「テスト駆動開発」はプログラマのストレスを軽減するか ? ( 川俣 晶 ) http://www.atmarkit.co.jp/fdotnet/special/tdd/tdd_01.html – .NET 開発者のためのリファクタリング入門 ( 川俣 晶 ) http://www.atmarkit.co.jp/fdotnet/special/refactoring/refactoring_01.html • 書籍 – テスト駆動開発入門 (ケント ベック) – Microsoft.NET でのテスト駆動開発 ( ジェームス・ニューカ ーク ) – リファクタリング ― プログラムの体質改善テクニック ( マ ーチン ファウラー ) わんくま同盟 名古屋勉強会 #3

Notes de l'éditeur

  1. ※ NUnit Runner のプロパティで Description が見える。 また、 TestResult.xml に Description が出ている。
  2. 使う側のコードを、 できるだけ具体的に思い浮かべる。 テストの実行部は、 だいたいそれと同じカタチになるはず。
  3. テストを通すために必須ではない製品コード =&gt; テストされていないコード =&gt; バグが居るぞ~
  4. 次にどういうテストを作ると、 製品が上手くそだっていくか?
  5. テストを通すために必須ではない製品コード =&gt; テストされていないコード =&gt; バグが居るぞ~
  6. Swap() の ref 引数がカッコ悪い。 Input[] とインデックスを渡すべき? Input[] をメンバ変数にして、インデックスだけ渡す? …全部できあがってから、リファクタリングする。
  7. 次にどういうテストを作ると、 製品が上手くそだっていくか?
  8. プローブは、製品コードの動作に影響があってはいけません。 ( 速度・メモリ使用量への影響は別、 というか、 やむをえない。)
  9. このくらいなら、 製品コード改修後のテストをサボっても大丈夫でしょう。 ただし、 このまま放置しないこと。 導入した _swapCount メンバ変数は、 Swap() 内でインクリメントされてはいますが、 その値は使われていません。 ムダなコードを放置しておくと、 将来メンテするときにはトラップになってしまいます。
  10. ※ n=0 と null の時のテストケースは必須。 なにも言わずに input をそのまま返すか? 例外を投げるか? 仕様の不備を問い合わせる必要があるだろう。 ※ 降順ソートに変更するには、 IsNotInOrder() を変えるだけ。