ユニットテストを整理する最良の方法は何ですか


18

私たちは、長年にわたってメインプログラムのためにかなりの数の単体テストを構築してきました。数千。問題は、非常に多くのテストがあるため、どのテストがあるのか​​明確に把握していないことです。そして、それは問題です。なぜなら、どこでテストが苦手なのか(または重複箇所があるのか​​)わからないからです。

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

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

それでは、そのテストはどのカテゴリに属しますか?テーブルのパディング、改ページ、ネストされたセル、垂直に結合されたセル、水平に結合されたセル、または他の何か?

そして、これらのカテゴリをどのように文書化し、単体テストに名前を付けるなどしますか?

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

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


1
あなたの質問は本当にあるようです、特定のシナリオをテストしたことをどのように知っていますか?
アンディWiesendanger

はい!また、類似したシナリオのテストもあります。そして、そこから私たちは#2の必要性を得ます-カバーされているものを読むことは私たちが逃したものを見つけるのに役立ちます。
デヴィッド

回答:


13

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

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


現在、ソースツリーをミラーリングしています。しかし、2つの問題があります。まず、テーブルの書式設定には、100を超えるさまざまなテストがあります。正確にテストされているものを追跡することが問題になっています。第二に、パーサー、データ置換、フォーマット、出力ドキュメントの作成など、非常に異なる機能領域でテーブルをテストする必要があります。だから私はあなたが正しいと思う、ある意味でそれは与えられたプロパティの機能テストです。
デヴィッドティーレン

どちらがテストのテーブルをどこに保存するのかという質問につながりますか?ルートソースディレクトリにスプレッドシートを考えていますか?
デヴィッドティーレン

テストディレクトリのバージョン管理スプレッドシートに保存します。テストする必要があるものがたくさんある場合は、メタ構造に分解することが有益です。何をどのようにテストするのではなく、どの一般的なものをテストするのかを考えてみてください。
サルダスリオン

7

最も一般的な構造はsrctestディレクトリミラーと思われます。

src/module/class
test/module/class_test

しかし、私が見た代替構造があり、今ではより良いと信じています。

src/module/class
src/module/class_test

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


2
前者のアプローチの欠点の1つは、プロジェクトのファイル構造を変更するたびに、テスト構造に対して同じことを行う必要があることです。テストがコードのある場所にある場合、この問題は存在しません。
victor175

5

.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テスト中の最高レベルのオブジェクトのスコープの下でemを投げるだけです。


3

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

とは言っても、ユニットテストのポイントは、それらを常に実行することです。つまり、コードをコミットする前にすべてを実行できるように、小さくて高速でなければなりません。言い換えれば、テストがどのカテゴリであるかは実際には関係なく、とにかくコミットする前に実行する必要があります。スイートは、何らかの理由で必要な速度のテストを作成できない場合に使用する松葉杖にすぎません。

カバレッジに関しては、テストの実行によって実際に実行された行の割合を示す非常に優れたカバレッジツールがあります。これは、まだどのタイプのテストが欠落しているかを示す明らかなポインタです。

命名に関しては、単体テストの名前に労力を費やすことに特別な価値はありません。テストから聞きたいことは、「5235テストのうち5235テストに合格した」ことだけです。テストが失敗した場合、読むのはその名前ではなく、メッセージassert()成功基準を実装するのString など)です。このメッセージは、テストの本文を読まずに何が問題なのかを理解できるように十分な情報を提供するものでなければなりません。名前はそれと比較して重要ではありません。


あなたが言うことすべてに100%同意します(ビルドマシンはチェックイン時にすべてのテストを実行します)。私たちの大きな問題は、テスト対象を追跡することです。また、コードカバレッジはあまり役に立ちません(上記の更新を参照)。
デヴィッドティーレン

1

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

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

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