Unit testing 如何在Poly重试策略中捕获最后一次尝试结果?
我正在扩展.NETCore中的Unit testing 如何在Poly重试策略中捕获最后一次尝试结果?,unit-testing,.net-core,polly,Unit Testing,.net Core,Polly,我正在扩展.NETCore中的TestMethod属性。我使用Polly库进行重试逻辑以及外部超时策略 我想要一个助手方法,它可以重试调用ITestMethod,直到它通过。我不介意重试的次数。但我会设定一个必须完成的超时时间。如果委托在超时时间内成功执行,则可以。但是,如果存在超时异常,我仍然需要失败的结果值(上次迭代的结果),而不是TimeOutRejectedException或返回类型的默认值 下面是我的扩展测试方法属性类: 公共密封类GuarantedPassTestMethodAtt
TestMethod
属性。我使用Polly库进行重试逻辑以及外部超时策略
我想要一个助手方法,它可以重试调用ITestMethod
,直到它通过。我不介意重试的次数。但我会设定一个必须完成的超时时间。如果委托在超时时间内成功执行,则可以。但是,如果存在超时异常,我仍然需要失败的结果值(上次迭代的结果),而不是TimeOutRejectedException
或返回类型的默认值
下面是我的扩展测试方法属性类:
公共密封类GuarantedPassTestMethodAttribute:TestMethodAttribute
{
///
公共重写TestResult[]执行(ITestMethod testMethod)
{
返回ExecuteTestTillSuccess(testMethod);
}
私有测试结果[]ExecuteTestTillSuccess(ITestMethod testMethod)
{
var gracefulTestRun=
TestExecutionHelper.ExecuteTestTillPassAsync(
()=>TestInvokeDelegate(testMethod));
返回gracefulTestRun.Result;
}
私有任务TestInvokeDelegate(ITestMethod testMethod)
{
TestResult[]结果=null;
var线程=新线程(()=>result=Invoke(testMethod));
thread.Start();
thread.Join();
返回Task.FromResult(结果);
}
}
下面是我使用Polly的TestExecutionHelper
:
内部静态类TestExecutionHelper
{
私有静态只读函数TestFailurePredicate=
结果=>results!=null&&
结果。长度==1&&
results.First().output!=UnitTestOutput.Passed;
内部静态异步任务ExecuteTestTillPassAsync(
Func testInvokeDelegate,
int DELAYBETWEENEXECUTIONNMS=3000,
整数时间(秒=60*10)
{
var timeoutPolicy=Policy.TimeoutAsync(timeoutingseconds);
var retryPolicy=Policy.HandleResult(TestFailurePredicate)
.WaitAndRetryAsync(int.MaxValue,x=>TimeSpan.Fromms(DelayBetweenExecutionNMs));
var testRunPolicy=timeoutPolicy.WrapAsync(retryPolicy);
返回wait wait testRunPolicy.ExecuteAsync(testInvokeDelegate);
}
}
通过此设置,我可以获得通过的测试方法执行,或者获得失败测试的TimeOutRejectedException
。我想捕获失败测试的TestResult
,即使在重试之后也是如此。测试用例
假设我们有以下测试:
[TestClass]
公共类UnitTest1
{
专用静态整数计数器;
[GuaranteedPassTestMethod]
公共异步任务TestMethod1()
{
等待任务。延迟(1000);
Assert.Fail($“第{++counter}次失败”);
}
}
我使用了一个静态
变量(称为计数器
)来更改每个测试运行的输出
属性
我通过使用任务简化了属性的代码。运行:
公共密封类GuarantedPassTestMethodAttribute:TestMethodAttribute
{
公共重写TestResult[]执行(ITestMethod testMethod)
=>TestExecutionHelper
.ExecuteTestTillPassAsync(
async()=>等待任务。运行(
()=>testMethod.Invoke(null)))
.GetAwaiter().GetResult();
}
为了更好地处理异常,我还将.Result
更改为GetAwaiter().GetResult()
- 如果您不熟悉此模式,请阅读
策略
我引入了一个名为Results
的累加器变量,在这里我捕获了所有测试运行的结果
内部静态类TestExecutionHelper
{
私有静态只读列表结果=新列表();
私有静态只读函数TestFailurePredicate=result=>
{
结果。添加(结果);
返回结果!=null&&result.output!=UnitTestOutput.Passed;
};
内部静态异步任务ExecuteTestTillPassAsync(
Func testInvokeDelegate,
int DELAYBETWEENEXECUTIONNMS=3000,
int TIMEOUTINES=1*10)
{
var timeoutPolicy=Policy.TimeoutAsync(timeoutingseconds);
var retryPolicy=Policy.HandleResult(TestFailurePredicate)
.WaitAndRetryForeverAsync(=>TimeSpan.fromMillimes(delaybetweenExecutionNMs));
var testRunPolicy=timeoutPolicy.WrapAsync(retryPolicy);
请尝试{等待testRunPolicy.ExecuteAsync(testInvokeDelegate);}
catch(TimeoutRejectedException){}//Suppress
返回结果。ToArray();
}
}
- 我在这里使用了
WaitAndRetryForeverAsync
而不是WaitAndRetryAsync(int.MaxValue,
)
- 我还更改了
testInvokeDelegate
的签名以与界面对齐
输出
在我的测试中,我已经将默认值timeoutingseconds
减少到10秒
TestMethod1
Source: UnitTest1.cs line 17
Test has multiple result outcomes
3 Failed
Results
1) TestMethod1
Duration: 1 sec
Message:
Assert.Fail failed. Failed for 1th time
Stack Trace:
UnitTest1.TestMethod1() line 20
ThreadOperations.ExecuteWithAbortSafety(Action action)
2) TestMethod1
Duration: 1 sec
Message:
Assert.Fail failed. Failed for 2th time
Stack Trace:
UnitTest1.TestMethod1() line 20
ThreadOperations.ExecuteWithAbortSafety(Action action)
3) TestMethod1
Duration: 1 sec
Message:
Assert.Fail failed. Failed for 3th time
Stack Trace:
UnitTest1.TestMethod1() line 20
ThreadOperations.ExecuteWithAbortSafety(Action action)
让我们看看此测试运行的时间表:
- 0>>1:
TestMethod1
的Delay
- 1:
Assert.Fail
- 1>>4:重试的惩罚
- 4>>5:
TestMethod1
的Delay
- 5:
Assert.Fail
- 5>>8:重试的惩罚
- 8>>9:
TestMethod1
的Delay
- 9:
Assert.Fail
- 9>>12::重试的惩罚
- 10:超时开始了
这里有一点需要注意:测试持续时间不包含重试的惩罚延迟:
能否请您详细说明此代码Invoke(testMethod)
?正如我所能testMethod.Invoke
确实存在,但它返回一个TestResult
@Mani这个版本对您有用吗?