[英]Repeat mstest test run multiple times
Some of my mstest unit tests help detect multi-threading race conditions, and as such they are most useful when run many times in a row, but I only want to do this for specific test runs -- not all the time. 我的一些mstest单元测试有助于检测多线程竞争条件,因此它们在连续多次运行时最有用,但我只想在特定的测试运行中执行此操作 - 而不是所有时间。
Is there a way to configure mstest (in the Test List Editor preferably) to run a test multiple times? 有没有办法配置mstest(最好在测试列表编辑器中)多次运行测试?
I needed to do something similar, so I came up with a solution to this. 我需要做类似的事情,所以我想出了一个解决方案。
It's not simple, but once everything is setup you can reuse it across projects. 这并不简单,但一旦设置完毕,您就可以在项目中重复使用它。 I also have a download of this code on GitHub ( https://github.com/johnkoerner/MSTestLooper ), but in case that goes away at some point, here is how I did it. 我也在GitHub上下载了这段代码( https://github.com/johnkoerner/MSTestLooper ),但是如果在某些时候消失了,我就是这样做的。
First we create an attribute that we will apply to our class to tell it run all the tests multiple times. 首先,我们创建一个属性,我们将应用于我们的类,告诉它多次运行所有测试。 Do all of this in a separate assembly, because the DLL needs to live in a special location. 在单独的程序集中完成所有这些操作,因为DLL需要位于特殊位置。
[Serializable]
public class TestLooperAttribute : TestClassExtensionAttribute
{
private static readonly Uri thisGuy = new Uri("urn:TestLooperAttribute");
private string _PropertyName;
public string PropertyName
{
get
{ return _PropertyName; }
set
{
_PropertyName = value;
}
}
public override Uri ExtensionId
{
get {
return thisGuy; }
}
public override TestExtensionExecution GetExecution()
{
return new TestLooperExecution(PropertyName);
}
}
Next we have to create a custom test class execution class: 接下来,我们必须创建一个自定义测试类执行类:
class TestLooperExecution : TestExtensionExecution
{
private string PropertyName;
public TestLooperExecution(string PropertyName)
{
this.PropertyName = PropertyName;
}
public override ITestMethodInvoker CreateTestMethodInvoker(TestMethodInvokerContext InvokerContext)
{
return new TestLooperInvoker(InvokerContext, PropertyName);
}
public override void Dispose()
{
//TODO: Free, release or reset native resources
}
public override void Initialize(TestExecution Execution)
{
//TODO: Wire up event handlers for test events if needed
}
}
Finally we add a custom invoker, which is where we perform the looping: 最后我们添加一个自定义调用程序,这是我们执行循环的地方:
class TestLooperInvoker : ITestMethodInvoker
{
private TestMethodInvokerContext m_invokerContext;
private string PropertyName;
public TestLooperInvoker(TestMethodInvokerContext InvokerContext, string PropertyName)
{
m_invokerContext = InvokerContext;
this.PropertyName = PropertyName;
}
public TestMethodInvokerResult Invoke(params object[] args)
{
// Our helper results class to aggregate our test results
HelperTestResults results = new HelperTestResults();
IEnumerable<object> objects = m_invokerContext.TestContext.Properties[PropertyName] as IEnumerable<object>;
foreach (var d in objects)
results.AddTestResult(m_invokerContext.InnerInvoker.Invoke(d), new object[1] { d.GetType().ToString()});
var output = results.GetAllResults();
m_invokerContext.TestContext.WriteLine(output.ExtensionResult.ToString());
return output;
}
}
The HelperTestResults class just builds up strings for output, you can handle this how you want and I don't want to include that code because it will just make this post that much longer. HelperTestResults类只是为输出构建字符串,你可以按照你想要的方式处理它,我不想包含那些代码,因为它只会使这篇文章更长。
Compile this into a DLL and then you need to copy it to 将其编译为DLL,然后您需要将其复制到
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies
You also have to create a registry entry for the class: 您还必须为该类创建一个注册表项:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\TestTypeExtensions\TestLooperAttribute]
"AttributeProvider"="TestLooper.TestLooperAttribute, TestLooper"
Now that you have all of that done, you can finally use the class: 既然你完成了所有这些,你终于可以使用这个类了:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestLooper;
using System.Collections.Generic;
namespace UnitTestSamples
{
[TestLooper(PropertyName="strings")]
public class UnitTest1
{
public static List<String> strings = new List<String>();
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
[ClassInitialize()]
public static void Init(TestContext x)
{
strings.Add("A");
strings.Add("B");
strings.Add("C");
strings.Add("D");
}
[TestInitialize()]
public void TestInit()
{
if (!TestContext.Properties.Contains("strings"))
testContextInstance.Properties.Add("strings", strings);
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "DataDriven1.csv", "DataDriven1#csv", DataAccessMethod.Sequential)]
[DeploymentItem("DataDriven1.csv")]
public void TestMethodStrings(string s)
{
int value1 = Convert.ToInt32(TestContext.DataRow["Col1"]); ;
TestContext.WriteLine(String.Format("{0}:{1}", s, value1));
}
}
}
Notice that our test method accepts a parameter, which comes from the test looper. 请注意,我们的测试方法接受来自测试循环器的参数。 I also show this using a data driven test, to show you can combine the two together to generate large permutations across your data sets. 我还使用数据驱动测试来展示这一点,以显示您可以将两者结合在一起,以在您的数据集中生成大的排列。
[TestMethod()]
public void RepetableTest(){
for(int i = 0; i < repeatNumber; i++){
//test code goes here
}
}
我猜答案是否定的。
Consider creating a test to spin off a couple of threads. 考虑创建一个测试来分离几个线程。 The Test List won't allow you to have multiple entries for the same test. 测试列表不允许您为同一测试提供多个条目。 You could assign, however, the multi-threaded test to its own list and call it only when you want to run that particular test. 但是,您可以将多线程测试分配给自己的列表,并仅在您要运行该特定测试时调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.