2017-06-08 47 views
3

我有以下自定義RetryAttribute採取從這篇文章:NUnit retry dynamic attribute。它工作正常,但是當我在Selenium中遇到超時錯誤時,它不起作用。C# - 硒 - 重試屬性不工作與硒超時

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5)); 
      wait.Until(ExpectedConditions.ElementToBeClickable(element)); 

重試自定義屬性:

/// <summary> 
/// RetryDynamicAttribute may be applied to test case in order 
/// to run it multiple times based on app setting. 
/// </summary> 
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 
public class RetryDynamicAttribute : RetryAttribute { 
    private const int DEFAULT_TRIES = 1; 
    static Lazy<int> numberOfRetries = new Lazy<int>(() => { 
     int count = 0; 
     return int.TryParse(ConfigurationManager.AppSettings["retryTest"], out count) ? count : DEFAULT_TRIES; 
    }); 

    public RetryDynamicAttribute() : 
     base(numberOfRetries.Value) { 
    } 
} 

,然後應用自定義屬性。

[Test] 
[RetryDynamic] 
public void Test() { 
    //.... 
} 

這怎麼解決?

回答

3

根據文檔在這裏

NUnit的文檔Retry Attribute

如果測試有一個意外的異常,一個錯誤的結果返回並 它不是重試。 只有斷言失敗纔會觸發重試。要將 轉換爲斷言失敗的意外異常,請參閱 ThrowsConstraint

強調我的。

相關ThrowsNothingConstraint簡單地說,這些代表 不拋出異常。

您需要捕獲異常,並導致失敗的斷言,如果沒有預期的異常了。

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5)); 
Assert.That(() => { 
     wait.Until(ExpectedConditions.ElementToBeClickable(element)); 
    }, Throws.Nothing); 

所以上面的代碼只是說執行的操作,它不應該期待一個例外。如果拋出異常,那麼它是一個失敗的斷言。如果將屬性應用於測試,則重試將執行。

3

另一種解決方案是實現自己的RetryAttribute來捕獲WebDriver異常。這樣你就不必改變測試:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 
public class RetryAttributeEx : PropertyAttribute, IWrapSetUpTearDown 
{ 
    private int _count; 

    public RetryAttributeEx(int count) : base(count) { 
     _count = count; 
    } 

    public TestCommand Wrap(TestCommand command) { 
     return new RetryCommand(command, _count); 
    } 

    public class RetryCommand : DelegatingTestCommand { 

     private int _retryCount; 

     public RetryCommand(TestCommand innerCommand, int retryCount) 
      : base(innerCommand) { 
      _retryCount = retryCount; 
     } 

     public override TestResult Execute(TestExecutionContext context) { 

      for (int count = _retryCount; count-- > 0;) { 

       try { 
        context.CurrentResult = innerCommand.Execute(context); 
       } 
       catch (WebDriverTimeoutException ex) { 
        if (count == 0) 
         throw; 

        continue; 
       } 

       if (context.CurrentResult.ResultState != ResultState.Failure) 
        break; 

       if (count > 0) 
        context.CurrentResult = context.CurrentTest.MakeTestResult(); 
      } 

      return context.CurrentResult; 
     } 
    } 

}