私たちはCIサーバーとしてTeamCityを使用しており、"TestFixtureSetUp Failed"
テスト失敗ウィンドウ。
この問題をデバッグする方法はありますか?テストは私のワークステーション(VS2008のR#テストランナー)で正常に実行されます。
TestFixtureSetUp(およびTestFixtureTearDown)の実装に少し欠陥があるため、例外が十分に報告されません。私はそれらの最初の実装を作成しましたが、想定どおりに動作することはありませんでした。当時、NUnitコードの概念は、アクションが単一のテストに直接関連しているという考えと密接に結びついていました。したがって、すべての報告はテスト結果に関連していました。大きな書き直しなしでスイートレベルで発生した何かを報告するためのスペースは実際にはありませんでした(羊をエスカレーターに変更するときのリファクタリングではありません)。
そのちょっとした歴史のために、TestFixtureSetUpで実際に何が起こったかを見つけるのは困難です。エラーを添付するのに適した場所はありません。 TestFixtureSetUp呼び出しは、テストに直接関連するのではなく、テストを実行することの副作用です。
@TrueWillは正しい考えを持っています。ログを確認し、必要に応じてログを追加するようにテストを変更します。 TestFixtureSetup内のtry/catchに配置して、catchブロックに多くのログを記録することができます。背景を追加できると思っただけです(つまり、私のせいです)。
最初にビルドログを確認します。
それから明らかでない場合は、テストにConsole.WriteLinesを含めてみることをお勧めします-私は肯定的ではありませんが、それらはビルドログに書き込まれたと思います。あるいは、ファイルにログを記録することもできます(凝ったものにしたい場合は、log4netを使用します)。
Visual StudioがCIサーバーにインストールされている場合は、そこからビルド/テストを実行してみてください。接続の問題であれば、それで解決する可能性があります。
しかし、ファイルへの相対パスが正しくなくなったり、絶対パスが使用されたりする、パスの問題を見てきました。これらはデバッグが難しく、パスをログに記録して、ビルドサーバーに存在するかどうかを確認する必要がある場合があります。
今日は、複製したくない、実行時間の長いセットアップの統合テストを作成しているときに、この問題に遭遇しました。すべてのテストフィクスチャセットアップロジックをtry/catchでラップすることになりました。次に、SetUpメソッドを追加します。このメソッドの唯一の目的は、フィクスチャのセットアップ中に障害が発生したかどうかを確認し、より適切なログを提供することです。
Exception testFixtureSetupException = null;
[TestFixtureSetUp]
public void FixtureSetup()
{
try
{
// DoTestFixtureSetup
}
catch (Exception ex)
{
testFixtureSetupException = ex;
}
}
[SetUp]
// NUnit doesn't support very useful logging of failures from a TestFixtureSetUp method. We'll do the logging here.
public void CheckForTestFixturefailure()
{
if (testFixtureSetupException != null)
{
string msg = string.Format("There was a failure during test fixture setup, resulting in a {1} exception. You should check the state of the storage accounts in Azure before re-running the RenewStorageAccountE2ETests. {0}Exception Message: {3}{0}Stack Trace:{4}",
Environment.NewLine, testFixtureSetupException.GetType(), accountNamePrefix, testFixtureSetupException.Message, testFixtureSetupException.StackTrace);
Assert.Fail(msg);
}
}
Visual StudioでSpecFlowとC#を使用している場合は、テストが失敗した後に自動生成された<whatever>.feature.cs
ファイルを確認します。 public partial class <whatever>Feature
行に、ホバーするとNUnitフィクスチャのセットアップが失敗した理由を示す記号が表示されます。私の場合、私のBeforeFeature
クラスのTestHooks
メソッドの一部が静的ではありませんでした。すべてのBeforeTestRun
、AfterTestRun
、BeforeFeature
、およびAfterFeature
メソッドは静的である必要があります。
単体テストをデバッグモードで実行します。セットアップでランタイムエラーが発生する場合があります。
Visual NUnitを使用してSpecFlowでテストを実行すると、同じエラーが発生しました。ユニットテストエクスプローラー(Resharper提供)から同じことを実行しようとすると、もう少し役立つメッセージが表示されました。10を超えるパラメーターを持つバインディングメソッドはサポートされていません。 10個を超えるパラメーターを持つSpecFlowメソッドを使用することはできず、テストを削除する必要があることに気付きました。
VS単体テストにすばやく切り替えて、テストデータベースを正しく作成していないことがわかりました。私の場合、失敗した理由に対してより良い応答を返すことができました。私は通常NUnitを使用します。 「クラスXのインスタンスを作成できません。エラー:System.Data.SqlClient.SqlException:ファイルのアクティブ化エラーが発生しました。物理ファイル名 '\ DbTest.mdf'が正しくない可能性があります。追加のエラーを診断して修正し、操作を再試行してください。 CREATE DATABASEが失敗しました。リストされている一部のファイル名を作成できませんでした。関連するエラーを確認してください。 "
今日はこれで悩みました。実際のエラーを取得するために次のことを行いました。
(1)別のフィクスチャに別のテストを記述して、問題のあるテストフィクスチャのインスタンスを初期化し、TestFixtureSetUpやSetUpなどのセットアップメソッドを明示的に呼び出し、ターゲットテストメソッドを実行します。
(2)上記の新しいコードの例外処理コードを追加し、実際の例外をどこかに記録/出力します。
それが誰かを助けることができる場合:あなたは例外をキャッチしてTearDownのコンソールに書くことができます
何かのようなもの :
[SetUpFixture]
public class BaseTest
{
private Exception caughtException = null;
[SetUp]
public void RunBeforeAnyTests()
{
try
{
throw new Exception("On purpose");
}
catch (Exception ex)
{
caughtException = ex;
}
}
[TearDown]
public void RunAfterAnyTests()
{
if (caughtException != null)
{
Console.WriteLine(string.Format("TestFixtureSetUp failed in {0} - {1}", this.GetType(), caughtException.Message));
}
}
}
そして結果は:
IntegratedTests.Services.BaseTestでTestFixtureSetUpが失敗する-意図的
フィールドの初期化中のエラーが原因でこの症状が発生しました。 [SetUp]
メソッドでフィールドを初期化すると、より適切なエラーメッセージが表示されます。
[TestFixture]
internal class CommandParserTest
{
// obscure error message
private CommandParser parser = new CommandParser(...);
...
}
[TestFixture]
internal class CommandParserTest
{
private CommandParser parser;
[SetUp]
public void BeforeTest()
{
// better error message
parser = new CommandParser(...);
}
...
}
この問題が発生しました。これは、クラスにプライベートの読み取り専用Dictionary
を追加したことが原因でした。これは、private const string
を追加したのと同じです。
Dictionary
を定数にしようとしましたが、コンパイル時にそれを行うことはできません。これを返すメソッドにDictionary
を入れることでこれを解決しました。