回答:
私の意見では、単体テストは本番コードとは別のアセンブリに配置する必要があります。単体テストを製品コードと同じアセンブリに配置することのいくつかの短所を次に示します。
私はどんなプロも知りません。追加のプロジェクト(または10)を持つことは、不利なことではありません。
編集:ビルドと配送に関する詳細情報
さらに、自動ビルドプロセスでは、本番環境と単体テストを別の場所に配置することをお勧めします。理想的には、ユニットテストビルドプロセスは、製品コードがビルドされ、製品ファイルをユニットテストディレクトリにコピーする場合にのみ実行されます。この方法でこれを行うと、実際のビットが配送などのために分離されます。さらに、この時点で特定のディレクトリのすべてのテストに対して自動ユニットテストを実行することは、かなり簡単です。
要約すると、ビットとその他のファイルの毎日のビルドとテストおよび出荷の一般的なアイデアは次のとおりです。
#if
ください。このカスタムシンボルは、CIソフトウェアスクリプトのコンパイラコマンドラインパラメータを使用して切り替えることができます。msdn.microsoft.com/en-us/library/4y6tbswk.aspxを参照してください。
別のプロジェクトですが、同じソリューションです。(私はテストコードと製品コードの別々のソリューションを持つ製品に取り組んできました-それは恐ろしいことです。あなたは常に2つを切り替えています。)
別のプロジェクトの理由は、他の人が述べたとおりです。データ駆動型テストを使用している場合、テストを本番アセンブリに含めると、かなりの量の膨張が生じる可能性があることに注意してください。
製品コードの内部メンバーにアクセスする必要がある場合は、InternalsVisibleToを使用します。
[assembly:InternalsVisibleTo("UnitTestProjectName")]
プロジェクトAssemblyInfo.cs
ファイルに追加することを意味します。
本番用コードでテストをデプロイすることに対する頻繁な反対は理解していません。私は小さなマイクロキャップでチームを率いていました(14から130人に成長しました)。半ダースほどのJavaアプリがあり、特定の環境でテストを実行するためにフィールドにテストを展開することは非常に価値があることがわかりました異常な動作を示していたマシン。ランダムな問題が現場で発生し、コストなしで数千のユニットテストをミステリーに投入できることは非常に貴重で、多くの場合、インストールの問題、不安定なRAMの問題、マシン固有の問題、不安定なネットワークの問題、などなど。フィールドでテストを行うことは非常に貴重だと思います。また、ランダムな問題がランダムなタイミングでポップアップし、ユニットテストをすぐに実行するのを待って、そこにユニットテストを配置しておくと便利です。ハードドライブのスペースは安いです。データと関数を一緒に維持しようとするように(OO設計)、コードとテストを一緒に維持することには根本的に価値があると思います(関数+関数を検証するテスト)。
テストをC#/。NET / Visual Studio 2008の同じプロジェクトに入れたいのですが、それを達成するための十分な調査はまだしていません。
FooTest.csと同じプロジェクトにFoo.csを保持することの大きな利点の1つは、クラスに兄弟テストが欠落しているときに開発者に常に通知されることです。これにより、テスト駆動型のコーディング手法の改善が促進されます...穴がより明白になります。
ユニットテストをコードと同じプロジェクトに配置して、より良いカプセル化を実現します。
内部メソッドを簡単にテストできます。つまり、内部メソッドであるはずのメソッドをパブリックにしないでください。
また、ユニットテストを作成しているコードの近くに配置することも非常に便利です。メソッドを作成すると、同じプロジェクト内にあるため、対応する単体テストを簡単に見つけることができます。unitTestsを含むアセンブリをビルドすると、unitTestにエラーがあるとコンパイラエラーが発生するため、ビルドするためだけにユニットテストを最新の状態に保つ必要があります。別のプロジェクトでunittestを使用すると、一部の開発者がunittest-projectのビルドを忘れ、壊れたテストがしばらく欠落する可能性があります。
また、コンパイルタグ(IF #Debug)を使用して、本番コードからユニットテストを削除できます。
自動統合テスト(made i NUnit)は単一のプロジェクトに属していないため、別のプロジェクトに含める必要があります。
Release
ビルドでテストを実行することができず、抜け落ちる「ヘイゼンバグ」がほとんどないことを意味します。
InternalsVisibleTo
すると、
Debug
、Approval
そしてRelease
; そして、すべてのリリース最適化で承認をコンパイルします。また、通常、単体テストは最初の段階でのヘイゼンバグの検出には適していません(私の経験では)。あなたはそれらのために特定の統合回帰テストを必要とする傾向があります-そしてそれらを並べて配置することもできます。
TypeScriptプロジェクトでいくつかの時間を費やした後、テストは、テストするコードと一緒にファイルに配置されることが多いため、個別に保つよりもこのアプローチを好むようになりました。
そのため、最近新しい.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コードでアイコンをカスタマイズすることも役立ちます。
これを行うには、Material Icon Theme拡張機能を使用して、VS Code設定JSONに次のようなものを追加します。
"material-icon-theme.files.associations": {
"*.Tests.cs": "test-jsx",
"*.Mocks.cs": "merlin",
"*.Interface.cs": "yaml",
}
私の単体テストは常に別のプロジェクトで行われます。実際、ソリューションに含まれるすべてのプロジェクトについて、それに対応する個別のテストプロジェクトがあります。テストコードはアプリケーションコードではなく、コードと混在させないでください。少なくともTestDriven.Netを使用して、それらを別々のプロジェクトに保持することの1つの利点は、テストプロジェクトを右クリックしてそのプロジェクトのすべてのテストを実行し、アプリケーションコードのライブラリ全体をワンクリックでテストできることです。
NUnitフレームワークが使用されている場合、同じプロジェクトにテストを配置する別の理由があります。単体テストを組み合わせた次の本番コードの例を考えてみます。
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);
}
}
ここでの単体テストは、テストされるコードのドキュメントおよび仕様として機能します。テストを別のプロジェクトに配置して、自己文書化のこの効果を達成する方法がわかりません。関数のユーザーは、テストを検索してそれらのテストケースを確認する必要がありますが、これはほとんどありません。
更新:このようなTestCase
属性の使用がNUnitの開発者が意図したものではなかったことは知っていますが、なぜそうではないのですか?
私はそれらを別々のプロジェクトに入れました。アセンブリの名前は、名前空間の名前を反映しています。これは、一般的な規則です。したがって、Company.Product.Feature.slnというプロジェクトがある場合、そのプロジェクトの出力(アセンブリ名)はCompany.Product.Feature.dllになります。テストプロジェクトはCompany.Product.Feature.Tests.slnで、Company.Product.Feature.Tests.dllを生成します。
それらを単一のソリューションに保持し、構成マネージャーを介して出力を制御するのが最善です。デフォルトのデバッグとリリースを使用する代わりに、メインブランチ(開発、統合、本番)ごとに名前付きの構成があります。構成を設定したら、構成マネージャーの[ビルド]チェックボックスをクリックして、構成を含めたり除外したりできます。(構成マネージャーを取得するには、ソリューションを右クリックし、構成マネージャーに移動します。)Visual StudioのCMにはバグがあることがあることに注意してください。数回、プロジェクトやソリューションファイルにアクセスして、作成したターゲットをクリーンアップする必要がありました。
さらに、チームビルドを使用している場合(他の.NETビルドツールも同じであると確信しています)、ビルドを名前付き構成に関連付けることができます。これは、たとえば「プロダクション」ビルドのユニットテストをビルドしない場合、ビルドプロジェクトはこの設定も認識し、そのようにマークされているためビルドしないことを意味します。
また、以前はビルドマシンからXCopyドロップオフを実行していました。スクリプトは、*。Tests.Dllという名前のすべてのコピーがデプロイされないようにするだけです。シンプルですがうまくいきました。
それらは別々にしておくといいでしょう。
言及されている他の理由に加えて、コードとテストを一緒にすると、テストカバレッジ数が歪んでしまいます。単体テストカバレッジについてレポートする場合-単体テストを実行するとテストがカバーされるため、レポートされるカバレッジは高くなります。統合テストのカバレッジについてレポートする場合、統合テストは単体テストを実行しないため、レポートされるカバレッジは低くなります。
Robert LopezによるFlood NNライブラリのユニットテストフレームワークに本当に触発されました。単体テスト済みのクラスごとに異なるプロジェクトを使用し、これらすべてのプロジェクトを保持する1つのソリューションと、すべてのテストをコンパイルして実行するメインプロジェクトがあります。
きちんとしたことは、プロジェクトのレイアウトでもあります。ソースファイルはフォルダーにありますが、VSプロジェクトのフォルダーは下にあります。これにより、コンパイラごとに異なるサブフォルダを作成できます。すべてのVSプロジェクトにはコードが付属しているため、ユニットテストの一部またはすべてを実行するのは非常に簡単です。
私はこれが非常に古い質問であることを知っていますが、ここで私の経験を追加したいと思います。最近、単体テストの習慣を個別のプロジェクトから同じプロジェクトに変更します。
どうして?
まず、メインプロジェクトのフォルダー構造をテストプロジェクトと同じにする傾向があります。だから、私が下にファイルがある場合、私はProviders > DataProvider > SqlDataProvider.cs
私のようなユニットテストプロジェクトで同じ構造を作成していますProviders > DataProvider > SqlDataProvider.Tests.cs
しかし、プロジェクトがますます大きくなると、ファイルをあるフォルダーから別のフォルダーに、またはあるプロジェクトから別のプロジェクトに移動すると、それらを単体テストプロジェクトと同期するのが非常に面倒になります。
第2に、テストするクラスからユニットテストクラスに移動するのが必ずしも簡単ではありません。これはJavaScriptとPythonではさらに困難です。
最近、私はそれを練習し始めました、私が作成したすべてのファイル(たとえばSqlDataProvider.cs
)は、次のようなTestサフィックスを持つ別のファイルを作成していますSqlDataProvider.Tests.cs
最初はファイルとライブラリ参照が膨らむように見えますが、長期的には一目でムービングファイルシンドロームを排除し、テスト対象の候補であるすべてのファイルにペアファイルがあることを確認します.Tests
接尾辞。個別のプロジェクトを調べる代わりに、テストファイルを(サイドバイサイドであるため)簡単にジャンプできます。
ビジネスルールを記述して、プロジェクト全体をスキャンし、.Testsファイルがないクラスを特定して、所有者に報告することもできます。また、テストランナーにターゲット.Tests
クラスを簡単に伝えることもできます。
特にJsとPythonでは、異なるパスから参照をインポートする必要はありません。テストするターゲットファイルの同じパスを使用するだけで済みます。
私はしばらくこの方法を使用していますが、プロジェクトの新規参入者にとって、プロジェクトの規模と保守性と学習曲線の間のトレードオフは非常に合理的だと思います。
他の人が答えたように- 別のプロジェクトでテストを行う
言及されていないことの1つは、ファイルnunit3-console.exe
以外に対しては実際に実行できないという事実.dll
です。
TeamCity経由でテストを実行することを計画している場合、これは問題を引き起こします。
コンソールアプリケーションプロジェクトがあるとします。コンパイルすると、実行可能ファイル.exe
がbin
フォルダーに返されます。
nunit3-console.exe
あなたはそのコンソールアプリケーションで定義されたすべてのテストを実行することはできません。
つまり、コンソールアプリケーションはexe
ファイルを返し、クラスライブラリはdll
ファイルを返します。
私は今日これに少し気がついて、それは:(
個別のプロジェクト。ただし、同じsvnを共有する必要があるかどうかについては、私自身で議論しています。現在、私はそれらに別々のsvnリポジトリを提供しています。
「MyProject」-プロジェクト自体
と呼ばれる
"MyProjectTests"-MyProjectに関連付けられたテスト用。
これはかなりクリーンで、プロジェクトへのコミットとテストへのコミットがまったく別であるという利点があります。また、テストをリリースしなくても、必要に応じてプロジェクトのsvnを引き渡すことができます。また、テストおよびプロジェクト用にブランチ/トランク/タグディレクトリを作成できることも意味します。
しかし、私は次のようなものを1つのsvnリポジトリーに、プロジェクトごとに持つ傾向にあります。
私のプロジェクト | \トランク | | \コード | \テスト | \タグ | | \ 0.1 | | | \コード | | \テスト | \ 0.2 | | \コード | \テスト \ブランチ \ MyFork | \コード \テスト
他の人がこの解決策についてどう思うか知りたいです。