C # - Selenium - Retry Attribute not working with Selenium timeout
I have the following custom RetryAttribute
taken from this post: NUnit retry dynamic attribute . It works great, but when I get a timeout error in Selenium, it doesn't work.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
wait.Until(ExpectedConditions.ElementToBeClickable(element));
Repeat given attribute:
/// <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) {
}
}
And then apply the custom attribute.
[Test]
[RetryDynamic]
public void Test() {
//....
}
How can this be solved?
source to share
According to the documentation here
NUnit Docs Repetition Attribute
If the test has an unexpected exception, an error result is returned and not replayed. Only assertion errors can trigger a retry . to convert an unexpected exception to assertion failure, see ThrowsConstraint .
my attention.
The associated ThrowsNothingConstraint simply states that the delegate does not throw an exception.
You need to catch the exception and throw a failed assertion if the exception was not expected.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
Assert.That(() => {
wait.Until(ExpectedConditions.ElementToBeClickable(element));
}, Throws.Nothing);
So the above code is just talking about performing an action and shouldn't expect an exception. If an exception is thrown, then this is a failed statement. Try again if attribute applies to test.
source to share
Another solution would be to implement your own RetryAttribute
to catch the WebDriver exception. This way you don't have to modify the test:
[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.Status != ResultState.Failure.Status)
break;
if (count > 0)
context.CurrentResult = context.CurrentTest.MakeTestResult();
}
return context.CurrentResult;
}
}
}
source to share