我有一个带有
NUnit3Adaptor 4.5.0
的 Azure DevOps 构建管道,跨 3 个虚拟机并行运行集成测试。我们的许多测试都在单个文件、单个设置中,并且许多测试按顺序运行,每个测试都依赖于前一个测试。
重点是保存单个昂贵的设置,并按顺序在多个测试中使用它,逐步推进流程并进行测试:
[TestFixture]
public class LotsaSequentialTests
{
[OneTimeSetUp]
public void SetupForThisClass()
{
// Expensive data import and process setup; one-time here
// ...
}
[Test, Order(1)]
public void CheckO1()
{
// I change something in the data and make a check
// ...
}
[Test, Order(2)]
public void CheckO2()
{
// I change something else in the data and make a check
// ...
}
[Test, Order(3)]
public void CheckO3()
{
// I change something else in the data and make another check
// ...
}
}
我的想法是,我可以使用一个昂贵的设置来进行 10 到 30 个按顺序运行的测试,每个测试都会对数据进行调整,重新运行流程,对流程中的这个阶段进行检查,下一个测试会添加另一个更改数据集,重新运行进程并进行检查。
如果其中一个失败,所有后续测试都会失败,这对于我们的场景非常有用。
理由是我不想为 10 到 30 个测试中的每一个测试运行昂贵的数据导入和设置,然后必须在检查之前将每个测试推进到某个状态。这与
NUnit3TestAdapter 4.5.0
一起在本地构建得很好,直到最近在 Azure DevOps 上也是如此。
我们最近将并行度从
distributionBatchType: basedOnTestCases
更改为 distributionBatchType: basedOnExecutionTime
希望缩短总体时间。我们遇到了一些奇怪的行为。 ADO 将测试类拆分到多个 VM 上,但现在以不同的方式拆分它们:它现在将它们拆分到多个 VM 上,而不是在单个 VM 上运行类中的所有测试。
因此,不仅每个虚拟机现在都在进行昂贵的设置(这是我想避免的),而且更糟糕的是,它在每个虚拟机上运行随机的测试集,这些测试当然没有它们的前身,所以整个计划失败了。
请注意,我们在这里没有使用
NUnit
并行化。
通过此设置,指示 Azure DevOps 在单个 VM 上运行此类。我们有 1500 个测试,只有 5 或 10 个类使用此方案,并且这些类随机失败,具体取决于 ADO 如何分解它们。
这是配置片段:
stages:
- stage: Build
jobs:
- job: Build
# perform the build and save the test artifacts 4to storage
- stage: Test
dependsOn: Build
jobs:
- job: Test
strategy:
parallel: 3
steps:
- task: DownloadPipelineArtifact@2
# restore the compiled NUnit tests from storage
- task: VSTest@2
displayName: 'Run Tests'
inputs:
testAssemblyVer2: |
**\MyApp.DTO.UnitTests.dll
**\MyApp.Migrations.IntegrationTests.dll
**\MyApp.Services.UnitTests.dll
**\MyApp.Services.IntegrationTests.dll
**\MyApp.Web.IntegrationTests.dll
**\MyApp.Services.Import.IntegrationTests.dll
**\MyApp.Services.ApiTests.dll
**\MyApp.Services.Thingy.IntegrationTests.dll
runInParallel: true
distributionBatchType: 'basedOnExecutionTime'
一个解决方案是进行单个测试,从每个测试中删除
[Test, Order(x)]
,如下所示:
[TestFixture]
public class LotsaSequentialTests
{
[OneTimeSetUp]
public void SetupForThisClass()
{
// Expensive data import and process setup; one-time here
// ...
}
[Test]
public void CheckAllOfThem()
{
CheckO1();
CheckO2();
CheckO3();
CheckO4();
CheckO5();
CheckO6();
// ...
}
}
但是我们失去了显示的粒度。没什么大不了的,但我真的想更多地了解 Azure DevOps 并按照我的意愿驯服野兽。
谢谢你。
根据您的需求,您需要对测试类进行分类,并分别在3台虚拟机上运行相应的测试类。
我建议你可以考虑使用matrix jobs来定义VStest任务中的
testFiltercriteria
来设置分组规则。
例如:
stages:
- stage: Test
jobs:
- job: Test
strategy:
matrix:
classgroup1:
testfilter: 'FullyQualifiedName~Namespace.ClassName1|FullyQualifiedName~Namespace.ClassName2'
classgroup2:
testfilter: 'FullyQualifiedName~Namespace.ClassName3|FullyQualifiedName~Namespace.ClassName4'
classgroup3:
testfilter: 'FullyQualifiedName~Namespace.ClassName5|FullyQualifiedName~Namespace.ClassName6'
steps:
- task: DownloadPipelineArtifact@2
# restore the compiled NUnit tests from storage
- task: VSTest@2
displayName: 'Run Tests'
inputs:
testAssemblyVer2: |
**\MyApp.DTO.UnitTests.dll
**\MyApp.Migrations.IntegrationTests.dll
**\MyApp.Services.UnitTests.dll
**\MyApp.Services.IntegrationTests.dll
**\MyApp.Web.IntegrationTests.dll
**\MyApp.Services.Import.IntegrationTests.dll
**\MyApp.Services.ApiTests.dll
**\MyApp.Services.Thingy.IntegrationTests.dll
runInParallel: true
distributionBatchType: 'basedOnExecutionTime'
testFiltercriteria: $(testfilter)
当您运行Pipeline时,它将创建3个作业并输入相关的测试过滤器信息以对目标VM上的测试类进行分组。
有关更多详细信息,您可以参考此文档:VSTest.Console.exe命令行选项和VSTest@2 - Visual Studio Test v2任务