如何在 Visual Studio 2010 中并行化数据驱动的单元测试?
Posted
技术标签:
【中文标题】如何在 Visual Studio 2010 中并行化数据驱动的单元测试?【英文标题】:How to parallelize a Data-Driven unit test in Visual Studio 2010? 【发布时间】:2011-05-02 01:47:34 【问题描述】:我知道通过在测试解决方案的.testresults
文件中指定parallelTestCount
属性,可以在多核机器上并行化常规的MS-Test 单元测试(当然需要注意事项)。像这样,
<Execution parallelTestCount="1">
<TestTypeSpecific />
<AgentRule name="Execution Agents"></AgentRule>
</Execution>
MSDN 上的更多信息:Executing Unit Tests in parallel on a multi-CPU/core machine
但是,我有一个数据驱动的测试,类似这样,这只是一个测试,但输入来自 csv 并运行 1000 条记录通过同样的测试。
[DeploymentItem("InputDataRows.csv"), Timeout(37800000), DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\InputDataRow.csv", "InputDataRow#csv", DataAccessMethod.Sequential)]
[TestMethod]
public void RunProcessing()
int userId = Convert.ToInt32(TestContext.DataRow[0].ToString());
int connId = Convert.ToInt32(TestContext.DataRow[1].ToString());
string xml = TestHelper.GetDataFromDb(userId, connId);
a = doStuffA(xml);
b = doStuffB(xml);
Assert.IsTrue(a == b);
因为这是一个缓慢的过程,我正在考虑并行化这个单元测试。
属性上的Sequential enum只是它访问数据的方式,另一个选项是Random,仍然是串行而不是并行。
【问题讨论】:
您使用什么语言? C#? 您使用的是什么版本的 .Net?另外,您能否提供一些有关如何设置 TestContext 的详细信息? 【参考方案1】:为了并行化此单元测试,您需要 doStuffA()
和 doStuffB()
才能对数据的子集(例如,一次处理一个块或什至 csv 的一行)进行操作。如果您可以重构您的方法以这种方式运行,您可以利用任务或并行 foreach 循环,以便此测试并行执行。假设您的方法被重构以处理您的 csv 行,您可以执行以下操作:
int userId = Convert.ToInt32(TestContext.DataRow[0].ToString());
int connId = Convert.ToInt32(TestContext.DataRow[1].ToString());
string xml = TestHelper.GetDataFromDb(userId, connId);
var rows = xml.Split('\n');
Parallel.ForEach(rows, (row) =>
var a = doStuffOnRowA(row);
var b = doStuffOnRowB(row);
Assert.AreEqual(a, b);
);
【讨论】:
【参考方案2】:这可能看起来有点复杂,但请听我说完。 MSTest 有一个限制,即您实际上不能并行运行数据驱动的测试。 我过去为解决这个问题所做的是在 Visual Studio 中创建一个“自定义工具”。
https://msdn.microsoft.com/en-us/library/bb166508.aspx
或
https://msdn.microsoft.com/en-us/library/bb166817.aspx
我们创建的自定义工具执行以下操作:
-
将 csv 拆分为多个 csv 文件,每个文件只有一行。
为每个新生成的 csv 生成单独的测试。
生成这些测试时,我们将特定的测试属性放在它们上面,因此我们可以指定只运行具有该属性的测试。
这听起来有点过头了,但如果您在构建自定义工具方面做得很好,这实际上是一个非常顺利的过程。
【讨论】:
【参考方案3】:如果 xml 中没有数据被更改(或者方法没有修改 xml 的相同部分),那么你可以这样做..
var numCompleted = 0;
var a = Task.Run(() => doStuffOnRowA(xml); );
var b = Task.Run(() => doStuffOnRowB(xml); );
Task.WaitAll(new Task[2] a, b );
如果您复制和粘贴这种伪代码,这可能不会运行。 不完全是 Parallel,但至少会同时运行!
【讨论】:
在等待多任务时最好使用框架的这个功能 Task.WaitAll msdn.microsoft.com/en-us/library/windows/apps/… 谢谢,我刚改了!【参考方案4】:不支持并行执行数据驱动测试。请看这里:RFC 004 - In-assembly Parallel Execution
【讨论】:
对于寻找这个的人,请参阅文档中的最后一行:“4. 数据驱动测试的执行将不会被并行化 - 即不支持对 DataRow 属性进行并行化。”【参考方案5】:据我所知:测试中的各个数据行不是并行运行的。但如果您有多个单元测试,它们确实会并行运行。
【讨论】:
以上是关于如何在 Visual Studio 2010 中并行化数据驱动的单元测试?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual Studio 2010 中使用 Visual Studio 2008 创建的 DLL?
关于在Visual Studio2010中如何卸载Visual Asixist这个插件?为啥将它卸载后Visual Studio启动后仍然有