web-dev-qa-db-ja.com

同じプロジェクトまたは別のプロジェクトに単体テストを配置しますか?

便宜上、同じプロジェクトに単体テストを配置しますか、それとも個別のアセンブリに配置しますか?

私たちのように別のアセンブリに配置すると、ソリューションにいくつかの余分なプロジェクトが作成されます。コーディング中の単体テストには最適ですが、これらの余分なアセンブリをすべて使わずにアプリケーションをリリースするにはどうすればよいですか?

132
leora

私の意見では、単体テストは製品コードとは別のアセンブリに配置する必要があります。生産コードと同じアセンブリに単体テストを配置する場合のいくつかの短所を次に示します。

  1. 単体テストには製品コードが同梱されています。製品コードに同梱されているものは、製品コードのみです。
  2. アセンブリは、単体テストによって不必要に肥大化します。
  3. 単体テストは、自動ビルドや連続ビルドなどのビルドプロセスに影響を与える可能性があります。

私はプロを本当に知りません。余分なプロジェクト(または10)を持っていることは、欠点ではありません。

編集:ビルドと出荷に関する詳細情報

さらに、自動化されたビルドプロセスでは、生産テストと単体テストを異なる場所に配置することをお勧めします。理想的には、単体テストのビルドプロセスは、製品コードがビルドされ、製品ファイルを単体テストディレクトリにコピーする場合にのみ実行されます。この方法で実行すると、実際のビットが出荷などのために分離されます。さらに、特定のディレクトリ内のすべてのテストでこの時点で自動ユニットテストを実行することは非常に簡単です。

要約すると、ビットおよびその他のファイルの毎日のビルドとテスト、および出荷の一般的なアイデアは次のとおりです。

  1. プロダクションビルドが実行され、プロダクションファイルが特定の「プロダクション」ディレクトリに配置されます。
    1. 実動プロジェクトのみをビルドします。
    2. コンパイルされたビットおよびその他のファイルを「本番」ディレクトリにコピーします。
    3. ビットやその他のファイルをリリース候補ディレクトリにコピーします。別名、クリスマスリリースディレクトリは「Release20081225」になります。
  2. 本番ビルドが成功すると、単体テストビルドが実行されます。
    1. 製品コードを「tests」ディレクトリにコピーします。
    2. ユニットテストを「tests」ディレクトリにビルドします。
    3. 単体テストを実行します。
  3. ビルド通知と単体テストの結果を開発者に送信します。
  4. リリース候補(Release20081225など)が受け入れられたら、これらのビットを出荷します。
93
Jason Jackson

別のプロジェクトですが、同じソリューション内にあります。 (テストコードと製品コード用に別々のソリューションを備えた製品に取り組んできました-それは恐ろしいことです。あなたは常にこの2つを切り替えています。)

別のプロジェクトの理由は、他の人が述べたとおりです。データ駆動型テストを使用している場合、テストを実稼働アセンブリに含めると、かなりの量の膨張が発生する可能性があることに注意してください。

本番コードの内部メンバーにアクセスする必要がある場合は、 InternalsVisibleTo を使用します。

106
Jon Skeet

実稼働コードでテストを展開することに頻繁に反対することを理解していません。私は小さなマイクロキャップでチームを率いました(14人から130人に成長しました)。半ダースほどのJavaアプリがあり、フィールドにテストを展開して、異常な動作を示しているspecificマシンで実行することは非常に価値があることがわかりました。フィールドでランダムな問題が発生し、ミステリーで数千のユニットテストをゼロのコストで実行できることは非常に貴重であり、インストールの問題、フレークRAMの問題、マシン固有の問題、不安定なネットワークの問題など。テストを現場に投入することは非常に貴重だと思います。また、ランダムな問題がランダムに発生するため、ユニットテストをすぐに実行するのを待ってそこに座っておくのは良いことです。ハードドライブのスペースは安価です。データと関数を一緒にしようとするのと同じように(OO設計)、コードとテスト(関数+関数を検証するテスト)を一緒に保つために根本的に価値があるものがあると思います。

C#/。NET/Visual Studio 2008の同じプロジェクトにテストを配置したいのですが、それを達成するための十分な調査はまだ行っていません。

Foo.csをFooTest.csと同じプロジェクトに保持することの大きな利点の1つは、クラスが兄弟テストを欠いているときに開発者に絶えず思い出させることです!これにより、より良いテスト駆動型コーディングプラクティスが促進されます。

65
Dave

ユニットテストをコードと同じプロジェクトに配置して、カプセル化を改善します。

内部メソッドを簡単にテストできます。つまり、内部メソッドであるべきメソッドを公開する必要はありません。

また、書いているコードにユニットテストを近づけることは本当に素晴らしいことです。メソッドを記述すると、同じプロジェクト内にあるため、対応する単体テストを簡単に見つけることができます。 unitTestsを含むアセンブリをビルドすると、unitTestのエラーによりコンパイラエラーが発生するため、ビルドするためにunittestを最新の状態に保つ必要があります。別のプロジェクトでunittestを使用すると、一部の開発者はunittest-projectのビルドを忘れ、しばらくの間壊れたテストを逃す可能性があります。

また、コンパイルタグを使用して、運用コードから単体テストを削除できます(IF #Debug)。

自動統合テスト(i NUnit製)は、単一のプロジェクトに属さないため、別のプロジェクトに含める必要があります。

16
jenspo

私の単体テストは常に別のプロジェクトで行われます。実際、ソリューションに含まれるすべてのプロジェクトには、それに沿った個別のテストプロジェクトがあります。テストコードはアプリケーションコードではないため、コードと混同しないでください。少なくともTestDriven.Netを使用して、それらを別々のプロジェクトに保持することの1つの利点は、テストプロジェクトを右クリックして、そのプロジェクトのすべてのテストを実行し、ワンクリックでアプリケーションコードのライブラリ全体をテストできることです。

10
tvanfosson

NUnit frameworkが使用されている場合、同じプロジェクトにテストを配置する追加の理由があります。単体テストと組み合わせた製品コードの次の例を考えてみましょう。

public static class Ext
{
     [TestCase(1.1, Result = 1)]
     [TestCase(0.9, Result = 1)]
     public static int ToRoundedInt(this double d)
     {
         return (int) Math.Round(d);
     }
}

ここでの単体テストは、テスト対象のコードのドキュメントおよび仕様として機能します。テストを別のプロジェクトに配置して、この自己文書化の効果を実現する方法がわかりません。関数のユーザーは、これらのテストケースを表示するためにテストを検索する必要がありますが、これはほとんどありません。

UpdateTestCase属性のそのような使用は、NUnitの開発者が意図したものではないことを知っていますが、なぜそうではないのですか?

8
Andrej Adamenko

同じプロジェクトと異なるプロジェクトとの間で変動します。

ライブラリをリリースする場合、本番コードを含むテストコードをリリースすることが問題になります。そうでない場合、通常はそうではありません(ただし、試みる前に強い心理的障壁があります)。

同じプロジェクトにテストを入れると、テストとテストするコードを簡単に切り替えることができ、テストをリファクタリング/移動しやすくなります。

3
orip

それらを別々のプロジェクトに入れました。アセンブリの名前は、一般的な規則として、名前空間の名前を反映しています。したがって、Company.Product.Feature.slnというプロジェクトがある場合、Company.Product.Feature.dllの出力(アセンブリ名)があります。テストプロジェクトはCompany.Product.Feature.Tests.slnで、Company.Product.Feature.Tests.dllが生成されます。

それらを単一のソリューションに保持し、Configuration Managerを介して出力を制御するのが最善です。デフォルトのデバッグとリリースを使用する代わりに、メインブランチ(開発、統合、プロダクション)ごとに名前付きの構成があります。構成をセットアップしたら、構成マネージャーの[ビルド]チェックボックスをクリックして、構成を含めたり除外したりできます。 (Configuration Managerを取得するには、ソリューションを右クリックしてConfiguration Managerに移動します。)Visual StudioのCMは時々バグがあることに注意してください。何度か、プロジェクトやソリューションファイルにアクセスして、作成したターゲットをクリーンアップする必要がありました。

さらに、チームビルドを使用している場合(他の.NETビルドツールも同じであると確信しています)、ビルドを名前付き構成に関連付けることができます。これは、たとえば、「Production」ビルド用のユニットテストをビルドしない場合、ビルドプロジェクトもこの設定を認識し、そのようにマークされているためビルドしないことを意味します。

また、以前はビルドマシンからXCopyを削除していました。このスクリプトは、*。Tests.Dllという名前のものをデプロイすることを単に省略します。簡単でしたが、うまくいきました。

3
Joseph Ferris

テストがテスト対象のコードと一緒にファイルに配置されることが多いTypeScriptプロジェクトにしばらく時間を費やした後、私はそれらを別々に保つよりもこのアプローチを好むようになりました:

  • テストファイルにすばやく移動できます。
  • テストするクラスの名前を変更するときに、テストの名前を忘れないようにしてください。
  • テスト対象のクラスを移動するときに、テストを移動することを忘れないでください。
  • クラスにテストがない場合、すぐにわかります。
  • テスト用とコード用の2つの重複ファイル構造を管理する必要はありません。

したがって、最近、新しい.NET Coreプロジェクトを開始したときに、最終リリースでテストまたはテストアセンブリを出荷せずに、C#プロジェクトでこの構造を模倣できるかどうかを確認したかったのです。

プロジェクトファイルに次の行を追加すると、これまでのところうまく機能しているように見えます。

  <ItemGroup Condition="'$(Configuration)' == 'Release'">
    <Compile Remove="**\*.Tests.cs" />
  </ItemGroup>
  <ItemGroup Condition="'$(Configuration)' != 'Release'">
    <PackageReference Include="nunit" Version="3.11.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="3.12.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
  </ItemGroup>

上記により、Release構成で*.Tests.csという名前のすべてのファイルがコンパイルから除外され、必要な単体テストパッケージ参照が削除されます。

リリース構成でクラスを単体テストできるようにする場合は、ReleaseのようなReleaseContainingTestsから派生した新しい構成を作成するだけです。


更新:しばらくこのテクニックを使用した後、VS Codeのアイコンをカスタマイズしてテスト(およびその他のこと)を行うことが役立つこともわかりましたExplorerペインでもう少し目立ちます:

VS Code Screenshot

これを行うには、Material Icon Theme拡張機能を使用して、VS Code設定JSONに次のようなものを追加します。

"material-icon-theme.files.associations": {
  "*.Tests.cs": "test-jsx",
  "*.Mocks.cs": "merlin",
  "*.Interface.cs": "yaml",
}
2
James Thurley

私はそれらを別々に保つと言うでしょう。

前述の他の理由に加えて、コードとテストを一緒にすると、テストカバレッジの数値が歪められます。単体テストのカバレッジについてレポートする場合-単体テストの実行時にテストがカバーされるため、レポートされるカバレッジが高くなります。統合テストカバレッジについてレポートする場合、統合テストでは単体テストが実行されないため、レポートされるカバレッジは低くなります。

1
Sebastian K

これは非常に古い質問であることは知っていますが、ここで私の経験を追加したいと思います。最近、ユニットテストの習慣を別のプロジェクトから同じものに変更します。

どうして?

最初に、メインプロジェクトのフォルダー構造をテストプロジェクトと同じに保つ傾向があります。したがって、_Providers > DataProvider > SqlDataProvider.cs_の下にファイルがある場合、_Providers > DataProvider > SqlDataProvider.Tests.cs_のような単体テストプロジェクトで同じ構造を作成しています。

しかし、プロジェクトがどんどん大きくなった後、ファイルをあるフォルダーから別のフォルダーに、またはあるプロジェクトから別のプロジェクトに移動すると、それらをユニットテストプロジェクトと同期させるのは非常に面倒な作業になります。

第二に、テスト対象のクラスから単体テストクラスに移動することは必ずしも非常に簡単ではありません。これは、JavaScriptとPythonではさらに困難です。

最近、私はそれを練習し始めました、私が作成したすべてのファイル(例えば_SqlDataProvider.cs_)私は_SqlDataProvider.Tests.cs_のようなTestサフィックスを持つ別のファイルを作成しています

最初はファイルとライブラリ参照が肥大化するように見えますが、長期的には、一見しただけでムービングファイルシンドロームを排除し、テスト対象のすべてのファイルにペアファイルがあることを確認します_.Tests_サフィックス付き。個別のプロジェクトを調べるのではなく、テストファイルに簡単にジャンプできます(隣り合っているため)。

プロジェクトをスキャンして.Testsファイルを持たないクラスを特定し、所有者に報告するビジネスルールを作成することもできます。また、_.Tests_クラスをターゲットにするようにテストランナーに簡単に伝えることができます。

特にJsおよびPythonの場合、異なるパスから参照をインポートする必要はありません。テストするターゲットファイルの同じパスを使用できます。

私はしばらくこのプラクティスを使用していますが、プロジェクトの規模と保守性、およびプロジェクトへの新規参入者の学習曲線との間の非常に合理的なトレードオフだと思います。

0
Teoman shipahi

Robert Lopezによる Flood NNライブラリ のユニットテストフレームワークに本当に触発されました。単体テストのクラスごとに異なるプロジェクトを使用し、これらすべてのプロジェクトを保持する1つのソリューションと、すべてのテストをコンパイルして実行するメインプロジェクトがあります。

すてきなことは、プロジェクトのレイアウトでもあります。ソースファイルはフォルダーにありますが、VSプロジェクトのフォルダーは下にあります。これにより、コンパイラごとに異なるサブフォルダを作成できます。すべてのVSプロジェクトにはコードが同梱されているため、誰でも単体テストの一部またはすべてを簡単に実行できます。

0
user1115652