MSTest&アプリのドメイン
-
05-07-2019 - |
質問
一部のプロジェクトでは、VSTS2008で単体テストを実行すると、VSTestHostのメモリ消費量が増加することに気付きました。ソリューションには非常に多くのテストがあるため、最終的にOutOfMemroyExceptionにつながります。 MSTestが各ユニットテストに対して新しいAppDomainを作成することを確信していたので、それは非常に奇妙に見えます。それ以外の場合、静的フィールドはどのようにリセットされますか? ただし、テストごとにAppDomainが作成されている場合は、メモリがリークすることはありません。しかし、そうです。
では、質問は次のとおりです。VSは各テストクラスに対してAppDomainを作成する必要がありますか。はいの場合、どうすればそれができるかを確認できます。 ProcessExpolorerとパフォーマンススナップインを使用してトレースを試みました。 " Total appdomain unloaded"の値テスト実行中は常に0です。
解決
ユニットテストエンジンが各テストに対して新しいAppDomainを作成するとは思わない。 AppDomainの作成は比較的高価な操作であるため、各テストでこれを行うと、単体テストの実行がかなり遅くなります!
Visual Studio 2008は、vstesthost.exeという別の実行可能ファイルを使用して単体テストを実行します。 VSはvstesthost.exeと通信して(どうやってこれを行うのかわかりません)、実行するテストを通知します。 vstesthost.exeは実行結果をVSに返し、VSはそれらの結果を表示します。
ユニットテストの実行中にOutOfMemoryExceptionsが発生する場合、テスト対象のコードが実際にクリーンアップしていないことを示す強力な指標です。アンマネージオブジェクト/メモリへのハンドルを保持していないことを確認しますか?単体テストをパフォーマンス分析の下で実行することをお勧めします(「テストビュー」の下で単体テストを見つけて右クリックし、「パフォーマンスセッションの作成」を選択することで実行できます)。これにより、少なくともオブジェクトの割り当てにいくらかの光が当てられる可能性があります。
他のヒント
MsTestは、テストアセンブリごとに1つのアプリドメインを作成します。ただし、noisolationを使用している場合を除きます。この場合、AppDomain Isolationはありません。
リークが発生している場合は、おそらくテストコードまたは製品コードのいずれかにあります。辞書に物を詰め込んでそこに残していないことを確認してください。
ユニットテストごとに個別のAppDomainを設定するのは間違っていました。
証拠は次のとおりです。 シングルトン
public class Singleton
{
public static Singleton Instance = new Singleton();
private Guid _token;
private Singleton()
{
_token = Guid.NewGuid();
}
public Guid Token
{
get { return _token; }
}
}
および2つのテスト:
[TestClass]
public class UnitTest2
{
[TestMethod]
public void TestMethod1()
{
Console.WriteLine(Singleton.Instance.Token);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Console.WriteLine(Singleton.Instance.Token);
}
}
両方のテストを実行すると、同じGUIDが出力されます。
大規模なテスト実行でも同じ問題が発生しました。私の理論は次のとおりです。この場合のメモリ不足は、MSTestテスト結果ファイルがXMLであるという事実によるものです。したがって、ディスクにシリアル化する前に、テスト実行が終了するまで、すべてのログ結果をメモリに保持する必要があります。 XMLの万歳:-)
この問題を接続の問題として投稿しましたしばらく前に、MSTest 10(64ビットに移行)で修正されるはずでしたが、VS2010および.NET 4.0に移行している他のすべての問題のため、これをまだ確認できませんでした。
シングルトンを破棄する唯一の方法は、appDomainを破棄することです。シングルトンはそれ自体を保持する静的であるため、基本的には循環参照です。真のシングルトンは、appdomainがなくなるまで破棄されません。
これはMSTest 2010では解決されていないようです。このような多くの同様の問題が発生しています。単体テストでガベージコレクションが機能しないのはなぜですか?
私の理解では、UTフレームワークは実行されたすべてのテストを処理しますが、これはコードにあるシングルトンパターンの場合には当てはまらないようです。