如何实现Reqnroll自定义Retry Hook的ScenarioExecutionRetry方法?
Reqnroll(新版Specflow)自定义重试Hook:实现ScenarioExecutionRetry方法
我正在为Reqnroll(新版Specflow)构建自定义Retry Hook,想要实现失败测试最多重试n次的逻辑,但在重新执行失败测试时遇到困难。以下是目前编写的代码,请问如何编写ScenarioExecutionRetry方法?
namespace Hooks.SharedHooks { [Binding] public class RetryHook { private int _retryCount; private const int DefaultMaxRetries = 2; private static readonly Regex RetryTag = new Regex(@"^Retry"); private static readonly Regex RetryTagNumberRegex = new Regex(@"^Retry\(\d+\)$"); // 修正原正则语法错误 [BeforeScenario("Retry","Retry*")] public void BeforeScenario() { _retryCount = 0; } [AfterScenario("Retry", "Retry*", Order = 0)] public void AfterScenario(ScenarioContext scenarioContext, ITestRunnerManager testRunnerManager) { var maxRetries = GetMaxRetriesFromScenario(scenarioContext) ?? DefaultMaxRetries; while (_retryCount < maxRetries && scenarioContext.TestError != null) { _retryCount++; Console.WriteLine($"Attempting scenario '{scenarioContext.ScenarioInfo.Title}' try {_retryCount} of {maxRetries}"); ScenarioExecutionRetry(scenarioContext, testRunnerManager); // 修正原方法名笔误 } } private int? GetMaxRetriesFromScenario(ScenarioContext scenarioContext) { foreach (var tag in scenarioContext.ScenarioInfo.Tags) { var match = RetryTagNumberRegex.Match(tag); if (match.Success && int.TryParse(match.Groups[1].Value, out int retries)) { return retries; } } return null; } private void ScenarioExecutionRetry(ScenarioContext scenarioContext,ITestRunnerManager manager) { // Logic to re-run the failed scenario } } }
实现方案
1. 核心逻辑实现
要重新执行失败场景,需借助ITestRunnerManager获取测试运行器,重置场景上下文的错误状态后重新执行步骤。以下是ScenarioExecutionRetry的完整实现:
private void ScenarioExecutionRetry(ScenarioContext scenarioContext, ITestRunnerManager testRunnerManager) { // 获取当前场景对应的测试运行器 var testRunner = testRunnerManager.GetTestRunner(scenarioContext.ScenarioInfo); // 重置场景上下文的错误标记,确保循环判断逻辑正常 scenarioContext.SetTestError(null); try { // 重新执行当前场景的所有步骤 testRunner.RunScenario(scenarioContext.ScenarioInfo); } catch (Exception ex) { // 重试失败时,将错误重新绑定到场景上下文,供下一次循环判断 scenarioContext.SetTestError(ex); Console.WriteLine($"Retry {_retryCount} failed for scenario '{scenarioContext.ScenarioInfo.Title}': {ex.Message}"); } }
2. 异步优化(推荐)
Reqnroll框架更推荐异步执行模式,可将方法改为异步版本,避免阻塞测试进程:
// 修改AfterScenario为异步方法 [AfterScenario("Retry", "Retry*", Order = 0)] public async Task AfterScenarioAsync(ScenarioContext scenarioContext, ITestRunnerManager testRunnerManager) { var maxRetries = GetMaxRetriesFromScenario(scenarioContext) ?? DefaultMaxRetries; while (_retryCount < maxRetries && scenarioContext.TestError != null) { _retryCount++; Console.WriteLine($"Attempting scenario '{scenarioContext.ScenarioInfo.Title}' try {_retryCount} of {maxRetries}"); await ScenarioExecutionRetryAsync(scenarioContext, testRunnerManager); } } // 异步版本的重试执行方法 private async Task ScenarioExecutionRetryAsync(ScenarioContext scenarioContext, ITestRunnerManager testRunnerManager) { var testRunner = testRunnerManager.GetTestRunner(scenarioContext.ScenarioInfo); scenarioContext.SetTestError(null); try { await testRunner.RunScenarioAsync(scenarioContext.ScenarioInfo); } catch (Exception ex) { scenarioContext.SetTestError(ex); Console.WriteLine($"Retry {_retryCount} failed for scenario '{scenarioContext.ScenarioInfo.Title}': {ex.Message}"); } }
3. 使用说明
- 给需要重试的场景添加
@Retry标签:将使用默认的2次重试 - 添加
@Retry(3)标签:将使用指定的3次重试
内容的提问来源于stack exchange,提问作者rtgher
相关产品推荐
相关产品推荐

