web-dev-qa-db-ja.com

単体テストを整理する最良の方法は何ですか

長年にわたり、メインプログラムの多数のユニットテストを構築してきました。数千。問題は、非常に多くのテストがあるため、どのようなテストを行っているのかが明確にわからないことです。テストのどこが苦手なのか(またはどこに重複があるのか​​)わからないため、これは問題です。

私たちのアプリは報告エンジンです。したがって、解析(すべてのテーブルプロパティを読み取ったかどうか)、データのマージ(マージで正しいテーブルプロパティを維持したかどうか)、最終ページのフォーマット(テーブルがページに正しく配置されているか)のテストに使用するテンプレートを使用できます。 )、および/または出力形式(作成されたDOCXファイルは正しいですか)。

テストに必要なものをこれに追加します。テーブルセルの周囲のパディングを取得します(レポートのデザインにはWord、Excel、およびPowerPointを使用します)。セル内のテーブル、垂直方向に結合されたセル、水平方向に結合されたセル、内部テーブルに垂直方向と水平方向に結合されたセルを持つテーブルを含む垂直方向と水平方向に結合されたセルについて、改ページ間のパディングをテストする必要があります。ページを分割します。

では、そのテストはどのカテゴリーに入るのでしょうか。表のパディング、改ページ、ネストされたセル、垂直方向に結合されたセル、水平方向に結合されたセル、または他の何か?

また、これらのカテゴリを文書化したり、単体テストに名前を付けたりするにはどうすればよいですか?

pdate:多くの人々が、カバレッジツールを使用して、完全なカバレッジがあることを確認することを提案しています。残念ながら、バグは特定の組み合わせが原因である傾向があり、コードはすべてテスト済みですが、その組み合わせではありません。

たとえば、昨日、テンプレート(Word文書)のforEachループの終わりにWordブックマークを開始し、次のforEachループの初めにそれを終了した顧客がいました。これはすべて、ユニットテストを含むコードを使用しましたが、ブックマークの展開を開始するテンプレートと25回開始して10回終了するテンプレートの組み合わせを考えていませんでした(2つのforEachループの行数は異なります)。

19
David Thielen

一般的に、私は単体テストのソースツリーをミラーリングする傾向があります。したがって、src/lib/fubarがある場合、fubarの単体テストが含まれるtest/lib/fubarがあります。

ただし、説明しているように見えるのは、より機能的なテストです。その場合、考えられるすべての条件を列挙した多次元テーブルができます。次に、テストがないものは無意味であるか、新しいテストが必要です。もちろん、それらをテストスイートのセットに配置することもできます。

最も一般的な構造は、srcおよびtestディレクトリミラーのようです。

src/module/class
test/module/class_test

しかし、私が今見た別の構造があります。

src/module/class
src/module/class_test

単体テストは、テストしているクラスをミラーリングする傾向があるため、同じディレクトリに配置すると、ファイルへのアクセスがはるかに簡単になり、両方を並べて作業できます。

7
ming_codes

.NETでは、「Tests.Unit」または「Tests.Integration」マスター名前空間の下にある、テストプロジェクトのソースコードの名前空間構造をミラーリングするか、少なくとも近似する傾向があります。すべての単体テストは1つのプロジェクトで行われ、ソースコードの基本構造はプロジェクト内のフォルダーとして複製されます。統合テストについても同様です。したがって、プロジェクトの簡単なソリューションは次のようになります。

Solution
   MyProduct.Project1 (Project)
      Folder1 (Folder)
         ClassAA (Class def)
         ...
      Folder2
         ClassAB
         ...
      ClassAC
      ...
   MyProduct.Project2
      Folder1
         ClassBA
         ...
      ClassBB
      ...
   ...
   MyProduct.Tests.Unit
      Project1
         Folder1
            ClassAATests
            ClassAATests2 (possibly a different fixture setup)
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests
      ...
   MyProduct.Tests.Integration
      Project1 (a folder named similarly to the project)
         Folder1 (replicate the folders/namespaces for that project beneath)
            ClassAATests
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests

ユニットテストフレームワークでコーディングされたAATまたはAEETの場合、これは少し変更されます。通常、これらのテストは一連のステップを反映しており、新しいユースケースまたはストーリーの機能をテストします。私は通常、これらのテストをMyProduct.Tests.Acceptanceプロジェクト自体。各ストーリーのテストを含み、開発中のストーリーが属するマイルストーンまたは「エピック」ストーリーによってグループ化される可能性があります。ただし、これらは実際には単なる統合テストなので、ストーリー指向ではなくオブジェクト指向でテストを構成する場合は、MyProduct.Tests.Acceptanceまたは同様のプロジェクト。 MyProduct.Tests.Integrationテスト中の最上位オブジェクトのスコープの下。

5
KeithS

単体テストが1つのカテゴリのみである理由はありません。すべての主要な単体テストツールキットは、特定のカテゴリのテストをバンドルするtest suitesの作成をサポートしています。コードの特定の領域が変更された場合、開発者はまずそのスイートを実行して、何が壊れているかを確認する必要があります。テストがパディングに関係する場合andが壊れるandネスティングは、必ず3つすべてのスイートに配置します。

とはいえ、ユニットテストのポイントは、常に実行することです。つまり、コードをコミットする前に、実行するのに十分なほど小さくて高速でなければなりませんall。言い換えれば、テストがどのカテゴリであるかは重要ではありません。とにかくコミットする前に実行する必要があります。スイートは実際には、何らかの理由で必要な速度でテストを記述できない場合に使用する松葉杖です。

カバレッジに関しては、テストを実行することによって実際に実行された行のパーセンテージを示す非常に優れたカバレッジツールがあります。これは、どのような種類のテストがまだ欠けているかを明らかに示しています。

ネーミングに関しては、ユニットテストのnamesに労力を費やすことに特別な価値はありません。テストから聞きたいのは「合格した5235テストのうち5235」だけです。テストが失敗した場合、読み取るのはその名前ではなく、messageです。成功基準を実装するassert()の文字列。メッセージは、テストの本文を読まなくても、何が問題なのかがわかるように、十分な情報を含んでいる必要があります。名前はそれと比較して重要ではありません。

3
Kilian Foth

テストに弱いかどうかを知る1つの方法は、トレーサビリティです。通常、テストの場合、これはカバレッジの形式を取ります。

目的は、テストで実行されているコードの部分を測定し、テストでカバーされていないコードを確認できるようにすることです。 「コードの一部」が何であるかを定義するのはあなた(およびカバレッジツール)です。最少はブランチカバレッジです。

1
mouviciel