38

我正在寻找并行运行测试套件的方法。如何并行运行单元测试(MSTest)?

我知道.testrunconfig设置。这可以让你多路复用的CPU数量。

我想并行运行1000个测试。这是有道理的,因为我正在测试一个Web服务,所以在测试中花费的时间有90%等待服务响应。

关于如何解决这个问题的任何想法?测试是为VS编写的,但我愿意在VS之外运行它们。

稍后编辑:Visual Studio测试团队在VS 2015 Update 1中添加了此项。请参阅Mark Sowul的答案。

+0

您在这里谈论1000个主题。 – 2010-10-12 16:53:46

+0

对,我想知道是否有一个预生成框架来管理这个。或者如果有人构建自己的框架。 – 2010-10-12 17:13:10

+2

你需要一个负载模拟器。 MSTest并不意味着用作负载测试。 1000线程疯狂的方式,你需要做的是看看不同的测试技术,这是超出单元测试的界限。 – Aren 2010-10-12 17:47:49

回答

20

Visual Studio 2015 Update 1增加了这一点。 https://www.visualstudio.com/en-us/news/releasenotes/vs2015-update1-vs#a-idmisc-a-miscellaneous

对于更新2,在测试资源管理器窗格顶部的工具栏中(在“分组”和“搜索”框之间)有一个UI切换按钮。

对于更新1,设置在.runsettings

<?xml version="1.0" encoding="utf-8"?> 
<RunSettings> 
    <RunConfiguration> 
    <MaxCpuCount>0</MaxCpuCount> 
    </RunConfiguration> 
</RunSettings> 

为MaxCpuCount的值具有以下语义如下:

• 'n' 个(其中1 < = N < =数):将启动up to'n'进程。

•任何其他值的“n”:启动的进程数将与机器上的可用内核数一样多。

+2

我们有数百个测试的测试DLL,有些可以并行运行,有些则不能。有没有一种方法来归因安全和不安全的测试类/方法?我通常希望选择一个或多个这些巨大的DLL并让它翻转。 – GilesDMiddleton 2016-04-05 14:23:50

+2

要记住的一件事是,并行性是在课堂上而不是在测试水平上。我没有看到内置的方式去做你想做的事,但你可以自己做,例如并在'ClassInitialize' /'ClassCleanup'中命名为Mutexes。不幸的是,最终可能会有那些暂时阻止并行的测试(例如,所有四个'并行测试'都是使用互斥锁的测试),但是我认为你可以得到这个结果。 – 2016-04-05 14:58:52

+4

测试在容器级别进行并行化(在C#的情况下,这是Assembly),所以它将并行运行来自不同程序集的测试。新模型中依次执行相同装配中的测试。 – jessehouwing 2016-05-09 11:59:07

27

你可以得到高达5使用方法from the Visual Studio Team Test Blog

请记住,有可能是使用这种并发问题,如MSTest的不完全隔离每个测试(静结转,例如,使事情代码有意运行一次)。

(不知道为什么限制为5,但如果parallelTestCount设置为5个以上。按照下面的评论MSTest的不平行运行它们,这条规则显然与Visual Studio 2013的变化)

+0

是的,刚刚发现,困难的方式:) - 我跑我的套件在8核心和所有测试被中止... – 2010-11-04 15:23:01

+0

它不应该总共被限制为5次,而是5次挂起测试。 Bruce Taimana的评论是:“如果清理”挂起“或者花太长时间,我们会让它继续清理,但我们会同时开始下一个测试,如果达到5次”挂起“测试,我们会中止。阅读整个评论[这里](http://blogs.msdn.com/b/vstsqualitytools/archive/2009/12/01/executing-unit-tests-in-parallel-on-a-multi-cpu-core- machine.aspx#10091555)。 – Anttu 2013-03-20 05:59:03

+0

@Anttu我希望看到一个解决方案设置为一次运行5个以上,并让它实际运行它们而不是失败。每次尝试超过5个设置时,它都会失败。也许吊死的时间被认为太小?我不知道。 – Rangoric 2013-03-20 13:24:39

8

什么我发现C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ Common7 \ IDE \ CommonExtensions \ Microsoft \ TestWindow \ vstest.console.exe 将与.testsettings文件运行并行测试,如下所示:

<?xml version="1.0" encoding="UTF-8"?> 
<TestSettings name="TestSettings1" id="21859d0f-7bdc-4165-b9ad-05fc803c9ee9" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"> 
    <Description>These are default test settings for a local test run.</Description> 
    <Deployment enabled="false" /> 
    <Execution parallelTestCount="8"> 
    <TestTypeSpecific> 
     <UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b"> 
     <AssemblyResolution> 
      <TestDirectory useLoadContext="true" /> 
     </AssemblyResolution> 
     </UnitTestRunConfig> 
    </TestTypeSpecific> 
    <AgentRule name="Execution Agents"> 
    </AgentRule> 
    </Execution> 
</TestSettings> 

参考可以在这里找到http://msdn.microsoft.com/en-us/library/vstudio/jj155796.aspx

+1

如果在Visual Studio中使用'Test Explorer',它也可以。你只需要选择''testsettings''配置'parallelTestCount'。更多细节在这里:http://ardalis.com/run-your-unit-tests-in-parallel-to-maximize-performance顺便说一下:选择'.testsettings',点击VS 2013中的'TEST'菜单然后“测试设置=>选择测试设置文件”。 – 2014-07-17 22:47:39

+0

我从来没有见过这样的野兽。 2013年,我必须创建自己的测试设置文件(在解决方案级别添加项目),然后按照Igor的说明对其进行修改以获得并行支持。 – 2014-08-04 18:43:03

4

上面的答案肯定有助于为我澄清事情,但是,这一点来自John Koerner的博客:https://johnkoerner.com/vs2015/parallel-test-execution-in-visual-studio-2015-update-1-might-not-be-what-you-expect/就是我们错过的一点。

“并行测试执行利用了机器上可用的内核,并且通过在每个可用内核上启动测试执行引擎作为一个独立的进程并将其交给容器(包含测试的程序集,DLL或相关工件执行),值得执行的测试。“

- >”单独的容器位是我失踪的一块。为了让我的测试并行运行,我需要将我的测试分解为单独的测试程序集。 “

所以是的,我们通过使用他们方便的'平行运行'标志使得VSTS在VSTS中并行运行,但它不是够了,我们不得不分割我们的测试成单独的测试项目。逻辑分组,当然,不是一个项目,每测试这将是可笑的

0
  1. 确保在您的DataTable中的第一列是一个唯一的ID。
  2. 创建一个接受DataRow的AsyncExecutionTask委托并返回任何内容
  3. 创建一个静态类(ParallelTestin g)使用接受DataRow和AsyncExecutionTask委托的AsyncExecutionContext方法。
  4. 在静态类中添加一个静态BatchStarted属性。
  5. 在静态类中添加一个静态的AsyncExecutionTests Dictionary属性。
  6. 在AsyncExecutionContext方法添加以下内容:

    public static void AsyncExecutionContext(DataRow currentRow, AsyncExecutionTask test) 
    { 
        if(!BatchStarted) 
        { 
         foreach(DataRow row in currentRow.Table) 
         { 
          Task testTask = new Task(()=> { test.Invoke(row); }); 
          AsyncExecutionTests.Add(row[0].ToString(), testTask); 
          testTask.Start(); 
         } 
         BatchStarted = true; 
        } 
        Task currentTestTask = AsyncExecutionTests[row[0].ToString()]; 
        currentTestTask.Wait(); 
        if(currentTestTask.Exception != null) throw currentTestTask.Exception; 
    } 
    
  7. 现在使用的类,像这样:

    [TestMethod] 
    public void TestMethod1() 
    { 
        ParallelTesting.AsyncExecutionContext(TestContext.DataRow, (row)=> 
         { 
          //Test Logic goes here. 
         } 
        ); 
    } 
    

注:你将不得不做例外一些修修补补让他们正确地冒泡(你可能在这里有一个聚合异常,你需要第一个例外)。显示每个测试执行所花费的时间将不再准确。最后一行完成后,您还需要清理ParallelTesting类。

工作原理:测试逻辑包装在一个lambda中,并传递给一个静态类,它将在第一次调用时为每一行测试数据执行一次逻辑。连续调用静态类只需等待预启动的测试任务完成。

这样每次调用测试框架对TestMethod所做的简单收集已经运行的相应测试的测试结果。

可能的改进:

  • 制作AsyncExecutionContext采取maxSynchronousTasks参数。
  • 研究框架如何移动跨非托管代码的完整堆栈跟踪,以查看是否可以将Task.Exception传递给Visual Studio测试框架,而不会重新抛出和销毁堆栈跟踪。