如何实现C#单元/集成/功能测试按指定顺序运行?
C#测试按指定顺序执行配置方法
网上流传的「C#测试默认按字母顺序执行」是错误认知,MSTest、xUnit、NUnit这三个主流C#测试框架,默认都不会保证测试按方法名字母序、代码文件书写顺序执行:测试发现阶段的程序集枚举逻辑、默认开启的测试并行执行机制,都会打乱预期的排列顺序。
如果确实需要让测试按指定顺序执行(仅推荐用于有流程链路依赖的集成测试、端到端功能测试,单元测试本身要求用例完全独立、无顺序依赖),可以根据使用的测试框架对应配置:
MSTest 框架配置
- 给测试类添加
[DoNotParallelize]特性,关闭该类下所有测试的并行执行能力 - 给每个测试方法添加
[Priority(数值)]特性,数值越小执行优先级越高,按需要的执行顺序给数值从小到大赋值即可
示例代码:
[TestClass] [DoNotParallelize] public class FlowIntegrationTests { [TestMethod] [Priority(1)] public void A1_PostFirsttoRegisterClaimsAdmin() { // 注册管理员测试逻辑 } [TestMethod] [Priority(2)] public void B2_CreateMasterWalletTest() { // 创建主钱包测试逻辑 } [TestMethod] [Priority(3)] public void C3_SendCoinsToProfile() { // 转币到用户账户测试逻辑 } [TestMethod] [Priority(4)] public void D4_LoginTest() { // 登录测试逻辑 } }
NUnit 框架配置
- 给测试类添加
[NonParallelizable]特性,关闭类内测试并行执行 - 给每个测试方法添加
[Order(数值)]特性,数值越小执行顺序越靠前
示例代码:
[TestFixture] [NonParallelizable] public class FlowIntegrationTests { [Test] [Order(1)] public void A1_PostFirsttoRegisterClaimsAdmin() { // 测试逻辑 } [Test] [Order(2)] public void B2_CreateMasterWalletTest() { // 测试逻辑 } [Test] [Order(3)] public void C3_SendCoinsToProfile() { // 测试逻辑 } [Test] [Order(4)] public void D4_LoginTest() { // 测试逻辑 } }
xUnit 框架配置
xUnit 原生设计强推测试独立原则,没有内置顺序执行特性,需要自定义测试顺序器实现指定顺序执行:
- 先自定义顺序标记特性
[AttributeUsage(AttributeTargets.Method)] public class TestOrderAttribute : Attribute { public int SortNum { get; } public TestOrderAttribute(int sortNum) => SortNum = sortNum; }
- 实现xUnit的
ITestCaseOrderer接口,编写按自定义特性排序的逻辑
public class CustomPriorityOrderer : ITestCaseOrderer { public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> testCases) where TTestCase : ITestCase { var sortedCaseDict = new SortedDictionary<int, List<TTestCase>>(); foreach (var testCase in testCases) { var sortNum = 0; var orderAttr = testCase.TestMethod.Method .GetCustomAttributes(typeof(TestOrderAttribute)) .FirstOrDefault(); if (orderAttr != null) { sortNum = orderAttr.GetNamedArgument<int>(nameof(TestOrderAttribute.SortNum)); } if (!sortedCaseDict.ContainsKey(sortNum)) sortedCaseDict[sortNum] = new List<TTestCase>(); sortedCaseDict[sortNum].Add(testCase); } foreach (var caseList in sortedCaseDict.Values) { foreach (var testCase in caseList) yield return testCase; } } }
- 给测试类标记顺序器、绑定串行测试集合,禁止并行
[TestCaseOrderer("你的项目命名空间.CustomPriorityOrderer", "你的测试项目程序集名称")] [Collection("SequentialFlowTests")] public class FlowIntegrationTests { [Fact] [TestOrder(1)] public void A1_PostFirsttoRegisterClaimsAdmin() { } [Fact] [TestOrder(2)] public void B2_CreateMasterWalletTest() { } [Fact] [TestOrder(3)] public void C3_SendCoinsToProfile() { } [Fact] [TestOrder(4)] public void D4_LoginTest() { } }
注意:不要在单元测试中依赖执行顺序,单元测试必须满足可独立运行、重复运行结果一致的要求,顺序执行配置仅适用于有强流程依赖的集成测试、功能测试场景。
内容的提问来源于stack exchange,提问作者NextNightFlyer
相关产品推荐
相关产品推荐

