MSTestを使用して、[TestInitialize]
メソッド内から現在のテストの名前を取得する必要がありました。これはTestContext.TestName
プロパティから取得できます。
[ClassInitialize]
メソッドに渡される静的TestContext
と、パブリックプロパティとして宣言されている(およびテストランナーによって設定される)間に、予期しない動作の違いが見つかりました。
次のコードを検討してください。
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace TestContext.Tests
{
[TestClass]
public class UnitTest1
{
public TestContext TestContext { get; set; }
private static TestContext _testContext;
[ClassInitialize]
public static void SetupTests(TestContext testContext)
{
_testContext = testContext;
}
[TestInitialize]
public void SetupTest()
{
Console.WriteLine(
"TestContext.TestName='{0}' static _testContext.TestName='{1}'",
TestContext.TestName,
_testContext.TestName);
}
[TestMethod] public void TestMethod1() { Assert.IsTrue(true); }
[TestMethod] public void TestMethod2() { Assert.IsTrue(true); }
[TestMethod] public void TestMethod3() { Assert.IsTrue(true); }
}
}
これにより、以下が出力されます(VS2013のResharperテストランナー出力からコピーアンドペースト):
TestContext.TestName='TestMethod1' static _testContext.TestName='TestMethod1'
TestContext.TestName='TestMethod2' static _testContext.TestName='TestMethod1'
TestContext.TestName='TestMethod3' static _testContext.TestName='TestMethod1'
以前、TestContext
の2つのインスタンスは同等であると想定していましたが、明らかにそうではありません。
public TestContext
プロパティは期待どおりに動作しますprivate static TestContext
メソッドに渡される[ClassInitialize]
値は渡しません。 TestContext
には現在実行中のテストに関連するプロパティがあるため、この実装は誤解を招き、壊れているように見えます[ClassInitialize]
メソッドに渡されたTestContext
を実際に使用することを好むシナリオはありますか、それは無視して使用しないのが最善ですか?
[ClassInitialize]
は先頭でのみ呼び出され、テスト名はTestMethod1
。これは、最初のテスト実行後は古くなっています。
TestContext
はすべてのメソッドに設定されているため、現在のテスト名になります。
はい、少しばかげています。
方法
[ClassInitialize]
public static void SetupTests(TestContext testContext) { }
プロパティセットTestContextが設定される前に呼び出されます。したがって、SetupTestsのコンテキストが必要な場合、パラメーターは便利です。それ以外の場合は、それぞれの前に設定されるTestContextプロパティを使用します
[TestInitialize]
public void SetupTest() { }
メソッド[ClassInitialize](または[AssemblyInitialize])で作成されたオブジェクトをクリーンアップメソッドとテストに渡す場合は、通常のTestContextとは別に、その初期化コンテキストを別の静的変数に保持する必要があります。この方法でのみ、後でコードで取得できます。
public TestContext TestContext { get; set; } // regular test context
private static TestContext ClassTestContext { get; set; } // global class test context
[ClassInitialize]
public static void ClassInit(TestContext context)
{
ClassTestContext = context;
context.Properties["myobj"] = <Some Class Level Object>;
}
[ClassCleanup]
public static void ClassCleanup()
{
object myobj = (object)ClassTestContext.Properties["myobj"];
}
[TestMethod]
public void Test()
{
string testname = (string)TestContext.Properties["TestName"] // object from regular context
object myobj = (object)ClassTestContext.Properties["myobj"]; // object from global class context
}
MSTestフレームワークは、[ClassInitialize]/[AssemblyInitialize]メソッドに渡されたコンテキストオブジェクトを保持しないため、返された後、明示的に保存しない限り永久に失われます。
シナリオ:各テストのコンテキスト。
次のライブラリを備えたVisual Studio 2017に適用されます。
サンプルコード:
[TestClass]
public class MyTestClass
{
public TestContext TestContext { get; set; }
/// <summary>
/// Run before each UnitTest to provide additional contextual information.
/// TestContext reinitialized before each test, no need to clean up after each test.
/// </summary>
[TestInitialize]
public void SetupTest()
{
TestContext.Properties.Add("MyKey", "My value ...");
switch (TestContext.TestName)
{
case "MyTestMethod2":
TestContext.Properties["MyKey2"] = "My value 2 ...";
break;
}
}
[TestMethod]
public void MyTestMethod()
{
// Usage:
// TestContext.Properties["MyKey"].ToString()
}
[TestMethod]
public void MyTestMethod2()
{
// Usage:
// TestContext.Properties["MyKey"].ToString()
// also has:
// TestContext.Properties["MyKey2"].ToString()
}
}