web-dev-qa-db-ja.com

MSTest TestContextを理解する

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を実際に使用することを好むシナリオはありますか、それは無視して使用しないのが最善ですか?

20
Richard Everett

[ClassInitialize]は先頭でのみ呼び出され、テスト名はTestMethod1。これは、最初のテスト実行後は古くなっています。

TestContextはすべてのメソッドに設定されているため、現在のテスト名になります。

はい、少しばかげています。

15
BanksySan

方法

[ClassInitialize]
public static void SetupTests(TestContext testContext) { }

プロパティセットTestContextが設定される前に呼び出されます。したがって、SetupTestsのコンテキストが必要な場合、パラメーターは便利です。それ以外の場合は、それぞれの前に設定されるTestContextプロパティを使用します

[TestInitialize]
public void SetupTest() { }
4
Peter

メソッド[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]メソッドに渡されたコンテキストオブジェクトを保持しないため、返された後、明示的に保存しない限り永久に失われます。

1
Alex

シナリオ:各テストのコンテキスト。

次のライブラリを備えたVisual Studio 2017に適用されます。

  • Microsoft.VisualStudio.TestPlatform.TestFramework
  • Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions

サンプルコード:

    [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()
        }

    }
0