C# 在MSTest中,如何指定某些测试方法不能彼此并行运行?
我有一套大型的集成测试来测试网站服务器。大多数测试可以并行运行。但是,我有一些更改设置的方法,它们在并行运行时可能会导致彼此失败 作为一个简化的例子,假设我进行了以下测试:C# 在MSTest中,如何指定某些测试方法不能彼此并行运行?,c#,.net,mstest,C#,.net,Mstest,我有一套大型的集成测试来测试网站服务器。大多数测试可以并行运行。但是,我有一些更改设置的方法,它们在并行运行时可能会导致彼此失败 作为一个简化的例子,假设我进行了以下测试: TestPrice_5PercentTax TestPrice_10PercentTax TestPrice_NoTax TestInventory_Add10Items TestInventory_Remove10Items 库存测试不会相互妨碍,也不会受到价格测试的影响。但是价格测试将改变Tax设置,因此如果5和10同
TestPrice_5PercentTax
TestPrice_10PercentTax
TestPrice_NoTax
TestInventory_Add10Items
TestInventory_Remove10Items
库存测试不会相互妨碍,也不会受到价格测试的影响。但是价格测试将改变Tax
设置,因此如果5
和10
同时运行,10
可能在5
完成之前改变设置,5
将失败,因为它看到的是10%的税,而不是预期的5%
我想为这三个价格测试定义一个类别,并说它们可能不会同时运行。它们可以与任何其他测试同时运行,但不能与其他价格测试同时运行。在MSTest中是否有这样做的方法?MSTest v2的功能如下
[assembly: Parallelize(Workers = 0, Scope = ExecutionScope.MethodLevel)]
// Notice the assembly bracket, this can be compatible or incompatible with how your code is built
namespace UnitTestProject1
{
[TestClass]
public class TestClass1
{
[TestMethod]
[DoNotParallelize] // This test will not be run in parallel
public void TestPrice_5PercentTax() => //YourTestHere?;
[TestMethod]
[DoNotParallelize] // This test will not be run in parallel
public void TestPrice_10PercentTax() => //YourTestHere?;
[TestMethod]
[DoNotParallelize] // This test will not be run in parallel
public void TestPrice_NoTax() => //YourTestHere?;
[TestMethod]
public void TestInventory_Add10Items() => //YourTestHere?;
[TestMethod]
public void TestInventory_Remove10Items() => //YourTestHere?;
}
}
更详细的信息可以在这里找到
我强烈建议您至少快速阅读链接,因为这可能会帮助您解决和理解并行或顺序运行测试的问题。我想提供一个我开始但没有追求的潜在解决方案 首先,我创建了一个类,可以将其用作测试方法的属性
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple =true)]
public class NoParallel : Attribute
{
public NoParallel(string nonParallelGroupName)
{
SetName = nonParallelGroupName;
}
public string SetName { get; }
}
然后,我把它添加到我的测试方法中,这将产生冲突
[NoParallel("Tax")]
public void TestPrice_5PercentTax();
[NoParallel("Tax")]
public void TestPrice_10PercentTax();
[NoParallel("Tax")]
public void TestPrice_NoTax();
// This test doesn't care
public void TestInventory_Add10Items();
// This test doesn't care
public void TestInventory_Remove10Items();
我给了我的测试类一个静态的互斥体字典,它由互斥体的名字组成
private static Dictionary<string, Mutex> exclusiveCategories = new Dictionary<string, Mutex>();
我们决定不继续这样做,因为这真的不值得付出努力。最终,我们决定将无法一起运行的测试拉到它们自己的测试类中,并按照H.N的建议用
[DoNotParallelize]
标记它们。创建一个测试方法,并在其中调用冲突测试,而不是从MSTest调用。这对我来说不是一个理想的解决方案,因为如果TestPrice5percenttax
失败,其余的测试将不会运行。我不想在其中一个中断时丢失关于其余部分的信息。根据您启动MSTest的方式,最简单的解决方案可能是添加一个类似@DourHighArch的子句。或者通过使用您正在使用的测试框架中可能找到的工具,将特定测试拆分为单独运行。或者使用方法调用与并行性冲突的指定测试。根据初始化的执行方式,使用单独的任务/方法运行指定的测试。我只在buildserver环境中遇到过与VsTest相同的问题,因此我的评论对于这个特定的解决方案可能不准确。这是否回答了您的问题?这并不像我希望的那样可定制,但我想我正在寻找MSTest无法提供的东西。我最终使用了这个解决方案。谢谢很乐意帮助:)大多数事情都可以实现,但正如您在解决方案回复中所述。更高级的方法通常需要更多的时间来进行测试。
public static List<string> NonparallelSets(this TestContext context, ContextHandler testInstance)
{
var result = new List<string>();
var testName = context.TestName;
var testClassType = testInstance.GetType();
var testMethod = testClassType.GetMethod(testName);
if (testMethod != null)
{
var nonParallelGroup = testMethod.GetCustomAttribute<NoParallel>(true);
if (nonParallelGroup != null)
{
result = nonParallelGroups.Select(x => x.SetName).ToList();
}
}
result.Sort();
return result;
}
[TestInitialize]
public void PerformSetup()
{
// Get all "NoParallel" strings on the test method currently being run
var nonParallelSets = testContext.NonparallelSets(this);
// A test can have multiple "NoParallel" attributes so do this for all of them
foreach (var setName in nonParallelSets)
{
// If this NoParallel set doesn't have a mutex yet, make one
Mutex mutex;
if (exclusiveCategories.ContainsKey(setName))
{
mutex = exclusiveCategories[setName];
}
else
{
mutex = new System.Threading.Mutex();
exclusiveCategories[setName] = mutex;
}
// Wait for the mutex before you can run the test
mutex.WaitOne();
}
}
[TestCleanup]
public void PerformTeardown()
{
// Get the "NoParallel" strings on the test method again
var nonParallelSets = testContext.NonparallelSets(this);
// Release the mutex held for each one
foreach (var setName in nonParallelSets)
{
var mutex = exclusiveCategories[setName];
mutex.ReleaseMutex();
}
}