はじめに
前回の記事『C#で始めるテスト駆動開発』では、TDD Boot Camp(TDDBC)横浜の課題を使って、NUnitを使ったTDDの手順を紹介しました。おかげさまで好評をいただけたようで、多くのかたに読んでいただけました。ありがとうございます。
Twitterで呟かれた読者の感想に、Visual Studio標準の単体テスト機能(MSTest)よりもNUnitの方が人気なんだろうか、というものがありました。人気のほどは分かりませんが、開発現場ではMSTestを使っているところもあります。そこで今回は、前の記事で書き漏らしたことをいくつか補足させていただいた後、MSTestを使ったTDDについて説明します。
対象読者
TDDに興味をお持ちの.NET Frameworkの開発者。
必要な環境
サンプルコードはC#で、Visual Studio 2010 Ultimateエディションを使って書いてあります。試してみるには、Visual Studio 2010 Professionalエディション以上が必要です。お持ちでない方は、Microsoftのサイトから評価版を入手して利用することができます。なお、ご自分でコードを入力して試すのであれば、Visual Studio 2008(Professionalエディション以上)や、Visual Studio 11 Developer Preview(このDeveloper PreviewはUltimateエディション相当/リンクは記事執筆時点)など、MSTestを搭載しているVisual Studioであれば構いません。
次のページから評価版をダウンロードできます(記事執筆時点)。本稿のサンプルを試してみるには、Ultimate・Premium・Professionalのいずれかのエディションを選んでください。
前回の補足
TDD(テスト駆動開発)のオリジナル
前回の記事では「TDD = テストファースト + リファクタリング」であると説明しました。TDDの定義はいろいろと言われているので迷うこともあるかもしれません。そこで、TDDの提唱者であるKent Beckの著書からオリジナルの説明を引用しておきます。『Test Driven Development: By Example』(2002/11/8発行)の前書きからです。
we drive development with automated tests, a style of development called Test-Driven Development (TDD). In Test-Driven Development, we
- Write new code only if an automated test has failed- Eliminate duplication
These are two simple rules
我々は、 自動テストによって開発を駆動する。 それはテスト駆動開発 (TDD) と呼ばれる開発のスタイル。 テスト駆動開発において我々は、 - 自動テストが失敗した場合に限り、 新しいコードを書く。 - 重複を取り除く。 これらは2つのシンプルな規則だ。
1つ目の規則は、明らかにテストファーストです。2つ目の規則は、同書の中でKent Beckは「重複を取り除くため」と称してデザインパターンを取り込むリファクタリングまでをも説明していることからすると、単なる重複の排除に留まらずリファクタリングのことを指していると解されます。また、1つ目の規則は、自動テストがなかったり、あるいは、コードを書いた後に自動テストを書いたりするのは、TDDではない、ということでもあります。
いつでも、どこでも、TDD!?
ある技法を開発プロジェクトの中でどう扱うか? それは当然のこととしてあまり述べてこなかったのですが、あらためて明確に書いておこうと思います。
「実際の開発では、常にTDDしているのか?」
筆者も、TDDを推進する立場から喋っていると、いつでもTDDしているように思われてしまうようですが、そんなことはありません。実際の開発では、TDDしたり、しなかったりします!
定式化するならば、
TDDで増加する工数 < TDDによって削減される、後のテスト工数とコード改修工数
という場面ではTDDする、というのが開発プロジェクトとして正しいありかたでしょう。実際には上の式の値を計測することは困難ですが、目安としては次のようなことが挙げられます。
テストが(ほとんど)不要ならばTDDしない
- 単純なプロパティ
- 定数や列挙型の定義
- ごく単純で変更も予想されないラッパー関数など
- 使い捨てのお試しコードなど
自動化テストを書くコストが手動テストよりも明らかに高そうならばTDDしない
- UI(画面)
- ハードウェアに密着していて、ハードウェアの操作が必要な部分
ある日のコーディング作業中に、TDDしたりしなかったりする。当然ながら、一連の製品コード中にも、TDDで作った部分とそうでない部分が混在する。それが実態ということになります。開発プロジェクトの目的はTDDすることではありませんから。
品質管理の立場からTDDを利用できないかと考える場合、上の不等式をしっかり念頭に置いておいてください。やみくもに「100%、TDDすべし!」などとやってしまうと、コストが上がったうえに納期を守れないという事態を招きます。
また、単純なプロパティ定義やプライベートな定数定義など、他のコードと分離できない部分のTDDを省略することも多いですから、「TDDする/しないでファイルを分けろ!」というのも非現実的だと、覚えておいてください(カバレッジ100%は非現実的だということ)。
日本語変数名について
Twitterで呟かれた読者の感想の中に、日本語の変数名・メソッド名についてお叱りをいただいたものもありました。しかしながら、サンプルコード中の日本語名は、パッと目に入るというメリットがありますので、これからも使っていきたくご寛恕ねがいます。
ちなみに、.NET Frameworkとその開発言語では、内部的には文字列はすべてUNICODEで扱われますから、.NET Framework内部に留まる限りは変数名やメソッド名などに日本語を使っても何の問題もありません。ただし、.NET Frameworkの外に一歩でも出れば、文字コード変換は避けて通れませんから、例えばデータベースのテーブル名などに、日本語名を付けるのは問題があります。
筆者自身の経験では、製品コードで日本語名を使った記憶はほとんどありません。テストコードでは、実際の開発でも日本語名をよく使います。中でもテストメソッドの名前は、日本語ならばどういうテストであるかがすぐ分かるように書けるので、日本語名を積極的に使用すべきでしょう。