MSTest扩展(获取测试类实例)

时间:2018-08-20 22:42:00

标签: c# .net unit-testing testing mstest

我有一些测试,这些测试使用套接字连接来测试对服务器的调用。套接字对象是测试类本身中的全局变量,我在每次测试前都使用标记为[TestInitialize]的方法对其进行了设置。我们将其称为TestInit()。

我想扩展MSTest来使每个测试运行两次,将套接字换出第二次运行,从而使我能够针对两个后端/服务器有效地运行测试。我通过扩展TestMethodAttribute的Execute()函数并两次调用Invoke()来做到这一点。

从TestMethodAttribute的Execute()中,没有实例变量。我无法获得测试类来换出套接字。我的解决方案是使用静态变量来发出信号,告知我们是否在第二次执行,如果这样,TestInit()将使用第二个套接字而不是第一个。

问题::我可以在扩展的TestMethodAttribute上使用锁,以确保标记辅助执行的静态变量不容易与其他并行运行的测试发生竞争。问题是,普通的测试方法属性将没有线程锁定代码,因此将原始TestMethodAttribute与扩展的属性混合会导致竞争情况。通过在线程上锁定TestInit()并在TestCleanup()上解锁来依次锁定测试也不起作用,因为在设置了“二次执行”测试之后,其他测试可以进入第一和第二测试之间。 (种族条件)。

有什么方法可以在TestMethodAttribute的Execute()中获取测试类实例吗?除了在各处强制使用自定义TestMethodAttributes / TestClassAttributes之外,我还能做些什么?请帮忙。

(不要建议我手动将交换写入测试中,我的问题的全部目的是让测试框架使您摆脱这一困扰。也不要建议禁用并行化,因为我仍然需要它)。

谢谢。

2 个答案:

答案 0 :(得分:0)

您可以尝试使用TestRunParameters配置。这使您可以在运行时将数据传递给测试。

<TestRunParameters>
  <Parmeter name="server1" value="https://s1.com"/>
  <Parmeter name="server2" value="https://s2.com"/>
</TestRunParameters>

您将需要重构测试代码。

private testSomething(serverInfo)
{
  var socketConnection = getConnectionFromServerInfo(serverInfo);
  //use the socketConnection to perform tests
} 

现在的实际测试方法

[TestMethod]
public void TestSomethingOnS1
{
  testSomething(TestContext.Properties["server1"].ToString());
}

[TestMethod]
public void TestSomethingOnS2
{
  testSomething(TestContext.Properties["server2"].ToString());
}

more info

答案 1 :(得分:0)

您可以使用[ThreadStatic]属性标记用于指示运行的静态变量。

[TestClass]
public class MyTest
{
    [ThreadStatic]
    public static int Run = 1;

    [TestInitialize]
    public void TestInit()
    {
        if (Run == 1) 
        {
            //...
        }
        else if (Run == 2) 
        { 
            //...
        }
    }

    [MyTestMethod]
    public void MyTestMethod() 
    {
        //...
    }
}

public class MyTestMethodAttribute : TestMethodAttribute
{
    public override TestResult[] Execute(ITestMethod testMethod)
    {
        MyTest.Run = 1;
        var result1 = testMethod.Invoke(null);
        MyTest.Run = 2;
        var result2 = testMethod.Invoke(null);

        return new TestResult[] { result1, result2 };
    }
}