単体テストのコーディング標準


22

通常、コーディング標準について話すとき、プログラム自体のコードを参照しますが、単体テストについてはどうですか?単体テストに固有の特定のコーディング標準ガイドラインはありますか?彼らは何ですか?

回答:


12

私の頭の中で、テストコードのコーディングスタイルには3つの違いが考えられます。

テストメソッドの命名では、のパターンに従いますshouldDoSomethingWhenSomeConditionHolds

テスト内では、次の間隔パターンに従うのが一般的です。

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

テストごとに1つのアサーションのみを要求する人もいますが、これは普遍的とはほど遠いものです。

DRY(Do n't Repeat Yourself)は、実稼働コードよりもテストコードでの考慮事項が少なくなっています。いくつかの繰り返しコードをsetUpメソッドまたはtestUtilsクラスに配置する必要がありますが、テストコードの繰り返しをゼロにしようとすると、密結合で柔軟性のないテストが発生し、リファクタリングが妨げられます。


もちろん、さまざまなパターンがあります。そのため、回答も提供する必要があります。
エリックウィルソン

10
それがArrange、Act、Assertパターンです。
StuperUser

乾燥はまだ重要です。複数のテストで同じアサートを行う必要がある場合は、共通の関数を作成し、すべてのテストで呼び出します。
MiFreidgeim SO停止する悪

@MichaelFreidgeim程度について話しているだけかもしれませんが、テストコードの繰り返しに対する許容度は非常に高くなっています。テストスイートを何度も繰り返し作成した経験がありますが、要件が変更されたときにテストを修正および理解することが難しくなっていることがわかりました。それから私はテストでDRYについて心配することをやめ、テストスイートは使いやすくなりました。<肩をすくめる>
エリックウィルソン

16

Roy Osheroveは、テストの命名に次のパターンを推奨しています。

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspxを参照してください


私はロイに同意します。ReSharperは私にそれらを削除すべきだと言い続けますがNameOfMethodUnderTestStateUnderTestExpectedBehavior();)
オスカーメデロス

メソッドがオーバーロードされているときにこれを機能させるには、同じ名前のメソッドが複数存在する可能性がありますか?
ナレンドラパタイ14年

6

主なことは、単体テストは基本的にミニ仕様であることを覚えておくことです。これは、読みやすさを常に重視する必要があることを意味します。

第一に、これは、名前がテスト対象および主張されているものを明確に伝えなければならないことを意味します。

第二に、それは時々忘れられますが、仕様として、彼らはまさにそれを行うべきであるということです-動作を指定します。つまり、単体テストにロジックを含めるべきではありません-または、テストするのではなく、プログラムの機能を繰り返すというtrapに陥る可能性があります。

テストにはセットアップが複雑なオブジェクトが含まれることがあるため、オブジェクトマザーテストデータビルダーなどを使用して、このセットアップロジックをテストとは別にするように努める必要があります。

本のいくつかの推奨事項で締めくくります。

xUnitテストパターン:リファクタリングテストコード:すばらしい本です。少し乾燥していると言う人もいますが、そうは思いません。テストを編成するさまざまな方法と、それらを保守可能にする方法について詳しく説明します。NUnitなどのようなものを使用している場合に関連します。

ユニットテストの技術:.Netの例を使用:テストの記述と保守の要点に関する最高の本。本当に新しいにもかかわらず、AAA構文が単なる別の方法ではなくかなり標準になったため、モックセクションはすでに少し古くなっています。

テストに導かれたオブジェクト指向ソフトウェアの成長:この本は素晴らしいです!群を抜いて最高の単体テストの本であり、ユニットテストを設計プロセスの第一級市民として位置づける唯一の先進的な本です。パブリックベータ版のときにこれを読んでいて、それ以来推奨されていました。本書全体で使用されている実物のような優れた実例。ロイの本を最初に読むことをお勧めします。


私見では、単体テストにロジックを含めることができます:正しい動作を決定するために同じことをする単純なアルゴリズムを使用して、高度に最適化された効率的なバージョンのアルゴリズムをテストすることは完全に合理的です。たとえば、線形検索ベースの連想配列を作成してハッシュテーブルをテストすることを想像してください。
dsimcha

2
はい。ただし、テストデータビルダーのテスト外に属します(内部のロジックが自明でない場合は、それ自体をユニットテストする必要があります)。これの例外は、一般に正しいと「信頼され」、テストなしで使用できるサードパーティのライブラリです。
FinnNk

3

単体テストにロジックを入れないでください。たとえば、addメソッドをテストしているとしましょう。次のようなものがあります。

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

この特定のケースでは、テストと同じロジックを繰り返している可能性が高いため、本質的には「1 + 1 == 2」ではなく「1 + 1 == 1 + 1」をテストしています。 「実際の」テスト。したがって、テストコードの実際の外観は次のようになります。

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}

2
小さな修正:「string expected = string.Format( "Hello、Bob")」は「string expected = "Hello、Bob"」であるべきだと思います。
マイクローゼンブラム

@MikeRosenblumあなたは明らかに正しいです、そして誰かがそれを修正しようとしましたが、2人のレビュアーはこの編集を拒否しました
Konrad Morawski 14年

@コンラッド:それは奇妙です。これはプログラミングフォーラムですよね?
マイクローゼンブラム14

Mike Rosenblumの提案に従って、回答をもう一度編集しました。
bdsl

0

長い説明的なメソッド名。 テストメソッドはコードから呼び出されることはありません(リフレクションを介してそれらを検出して呼び出す単体テストランナーによって呼び出されるため)、気が狂ってメソッド名が50〜80文字の長さであってもかまいません。特定の命名規則(キャメルケース、アンダースコア、「should」、「must」、「when」、「given」など)は、名前が3つの質問に答える限り、それほど重要ではありません。

  • テスト対象は何ですか?
  • 条件は何ですか?
  • 期待される結果は何ですか?

テスト方法は短くする必要があります

テストメソッドは、単純な線形構造を持つ必要があります。ifまたはloopコンストラクトはありません。

テストメソッドは、「arrange-act-assert」パターンに従う必要があります。

各テストは1つのことをテストする必要があります。これは通常、テストごとに1つのアサートを意味します。次のようなテスト{ Do A; Assert B; Assert C; }は2つにリファクタリングする必要が{ Do A; Assert B; }あります。{ Do A; Assert C; }

ランダムなデータや「DateTime.Now」などを避けます

すべてのテストフィクスチャメンバーがテストの終了時に元の状態に戻されるようにします(たとえば、分解を使用)

本番コードで無慈悲に重複を削除しても、テストフィクスチャでのコードの重複ははるかに小さな問題です。


-1

Farmboyが既に言及しているものとほぼ同じ、私のメソッド名の形式

 <MethodName>Should<actionPerformed>When<Condition>

例えば

 GetBalanceShouldReturnAccountBalance() {
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.