unit-testing
ユニットテスト:ベストプラクティス
サーチ…
前書き
単体テストは、関数、クラス、プロシージャ、インタフェースのようなアプリケーションのテスト可能な最小部分です。ユニットテストは、ソースコードの個々の単位をテストして、使用に適しているかどうかを判断する方法です。単体テストは基本的にソフトウェア開発者が作成し実行して、コードがその設計と要件を満たし、期待どおりに動作することを確認します。
良い命名
良い命名の重要性は、いくつかの悪い例で最もよく説明することができます:
[Test]
Test1() {...} //Cryptic name - absolutely no information
[Test]
TestFoo() {...} //Name of the function - and where can I find the expected behaviour?
[Test]
TestTFSid567843() {...} //Huh? You want me to lookup the context in the database?
良いテストには良い名前が必要です。良いテストは、メソッド、テストシナリオや要件をテストしないでください。
適切なネーミングは、コンテキストと予想される動作に関する情報も提供します。理想的には、ビルドマシンでテストが失敗したときに、テストコードを見ずに、何が間違っているのかを判断することができます。
コードを読み込んでデバッグするのに時間がかかりません:
[Test]
public void GetOption_WithUnkownOption_ReturnsEmptyString() {...}
[Test]
public void GetOption_WithUnknownEmptyOption_ReturnsEmptyString() {...}
初心者の方は、 EnsureThat_またはそれに似た接頭辞を使用してテスト名を開始すると便利です。 "EnsureThat_"で始めると、テストが必要なシナリオや要件について考え始めることができます。
[Test]
public void EnsureThat_GetOption_WithUnkownOption_ReturnsEmptyString() {...}
[Test]
public void EnsureThat_GetOption_WithUnknownEmptyOption_ReturnsEmptyString() {...}
テストフィクスチャーの命名も重要です。テストされるクラスの後にテストフィクスチャに名前を付けます:
[TestFixture]
public class OptionsTests //tests for class Options
{
...
}
最後の結論は:
適切なネーミングは、優れたテストにつながり、プロダクションコードの設計につながります。
簡単なものから複雑なものまで
クラスを書くことと同じ - 単純なケースから始め、必要に応じてテスト(別名テスト)と実装(別名プロダクションコード)を追加する:
[Test]
public void EnsureThat_IsLeapYearIfDecimalMultipleOf4() {...}
[Test]
public void EnsureThat_IsNOTLeapYearIfDecimalMultipleOf100 {...}
[Test]
public void EnsureThat_IsLeapYearIfDecimalMultipleOf400 {...}
要件の完了時にリファクタリングステップを忘れないでください。最初にリファクタリングしてから、テストをリファクタリングしてください
作業が終わったら、あなたのクラスに関する完全な最新のREADABLE文書が必要です。
MakeSutコンセプト
テストコードは、生産コードと同じ品質要求があります。 MakeSut()
- 読みやすくする
- 簡単にリファクタリングすることができます
- 依存性注入を完全にサポートします。
ここにそのコンセプトがあります:
[Test]
public void TestSomething()
{
var sut = MakeSut();
string result = sut.Do();
Assert.AreEqual("expected result", result);
}
最も単純なMakeSut()はテスト済みのクラスを返すだけです:
private ClassUnderTest MakeSUT()
{
return new ClassUnderTest();
}
依存関係が必要な場合は、ここに注入することができます:
private ScriptHandler MakeSut(ICompiler compiler = null, ILogger logger = null, string scriptName="", string[] args = null)
{
//default dependencies can be created here
logger = logger ?? MockRepository.GenerateStub<ILogger>();
...
}
MakeSutは、Testrunnerフレームワークによって提供されるセットアップとティアダウンの方法の単純な代替品であり、これらの方法をテスト固有のセットアップとティアダウンのためのより良い場所と考えるかもしれません。
誰もが自分の使い方を決めることができます。私にとって、MakeSut()は読みやすさとはるかに柔軟性を提供します。最後に、テストランナーフレームワークとは独立した概念です。