I'm trying to implement test retries on failure, right now I've added IRetryListener which I managed to get working. The issue I am facing is, that when developing new tests locally the retry is kicking off each time the tests fail, and we really don't need the retry kicking off while we are developing new tests locally. Is there a way to set a parameter or flag that would allow us to only have retries when it is set to true?
Annotation Transformer
package IRetryAnalyzer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
public class AnnotationTransformer implements IAnnotationTransformer {
@Override
public void transform(ITestAnnotation annotation,
Class testClass,
Constructor testConstructor,
Method testMethod) {
annotation.setRetryAnalyzer(RetryAnalyzer.class);
}
}
Retry Interface
package IRetryAnalyzer;
import org.testng.ITestResult;
public interface IRetryAnalyzer {
/**
* Returns true if the test method has to be retried, false otherwise.
*
* @param result The result of the test method that just ran.
* @return true if the test method has to be retried, false otherwise.
*/
public boolean retry(ITestResult result);
}
RetryAnalyzer
package IRetryAnalyzer;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
import pages.BaseClass;
public class RetryAnalyzer extends BaseClass implements IRetryAnalyzer {
private int count = 0;
private static int maxTry = 3;
@Override
public boolean retry(ITestResult iTestResult) {
if (!iTestResult.isSuccess()) { //Check if test not succeed
if (count < maxTry) { //Check if maxtry count is reached
count ; //Increase the maxTry count by 1
logg.info("Test Failed: Retrying");
iTestResult.setStatus(ITestResult.FAILURE); //Mark test as failed
return true; //Tells TestNG to re-run the test
} else {
logg.info("Test Failed: Max retry count reached. Flagged as failed");
iTestResult.setStatus(ITestResult.FAILURE); //If maxCount reached,test marked as failed
}
} else {
iTestResult.setStatus(ITestResult.SUCCESS); //If test passes, TestNG marks it as passed
}
return false;
}
}
BaseClass
package pages;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
/**
*
*
*
*/
public class BaseClass {
public static Logger logg = Logger.getLogger(BaseClass.class.getName());
protected static WebDriver driver;
String ***** = "*****";
// *****
String ***** = "*****";
// *****
String ***** = "*****";
//*****
String ***** ="*****";
/**
* This function will execute before each Test tag in testng.xml
*
* @param browser
* @throws MalformedURLException
* @throws Exception
*/
@BeforeMethod
@Parameters({ "browser", "environmentURL", "grid", "retry"})
public void setup(String browserName, String env, String grid) throws MalformedURLException {
logg.info("Initializing browser setup");
logg.info(browserName " Session has started");
if (grid.equalsIgnoreCase("true")) {
logg.info("Remote session intiated");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("browserName", "chrome");
capabilities.setCapability("platform", "linux");
driver = new RemoteWebDriver(new URL(MvnProperties.gridUrl), capabilities);
} else {
if (browserName.equalsIgnoreCase("Firefox")) {
// create firefox instance
System.setProperty("webdriver.gecko.driver", "/usr/local/bin/geckodriver");
driver = new FirefoxDriver();
}
// Check if parameter passed as 'chrome'
if (browserName.equalsIgnoreCase("Chrome")) {
// set path to chromedriver.exe
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver");
// create chrome instance
driver = new ChromeDriver();
}
// Check if parameter passed as 'chrome'
if (browserName.equalsIgnoreCase("Chrome Dev")) {
// set path to chromedriver.exe
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriverdev");
// create chrome instance
driver = new ChromeDriver();
}
// Check if parameter passed as 'Edge'
if (browserName.equalsIgnoreCase("Edge")) {
// set path to Edge.exe
System.setProperty("webdriver.edge.driver", "/usr/local/bin/msedgedriver");
// create Edge instance
driver = new EdgeDriver();
}
}
logg.info("Waiting for browser to load");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
logg.info("Maximizing window");
driver.manage().window().maximize();
logg.info("******** Browser has been initialized********");
// directs test to environment
logg.info("Opening " env " environment");
driver.get("*****");
logg.info(env " was reached");
if (env.equals("stage")) {
logg.info("Opening " env " environment");
driver.get("*****");
logg.info(env " was reached");
logg.info("*****");
logg.info("*****");
logg.info("*****");
logg.info("*****");
logg.info("*****");
}
if (env.equals("prod")) {
logg.info("Opening " env " environment");
driver.get("*****");
logg.info(env " was reached");
}
}
/**
* This function will execute after each Test tag in testng.xml
*
* @param none
* @throws Exception
*/
@AfterMethod
public void teardown() {
logg.info("****** Test Finished: Beginning teardown ******");
logg.info("Closing browser");
driver.quit();
}
}
XML File - I was hoping to be able to achieve this through the parameter retry as shown below, however I was running into issues trying to find the correct way to handle something like this on google
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestSuite">
<listeners>
<listener class-name="listeners.TestListener" />
</listeners>
<listeners>
<listener class-name="IRetryAnalyzer.RetryAnalyzer"/>
</listeners>
<listeners>
<listener class-name="IRetryAnalyzer.AnnotationTransformer"/>
</listeners>
<test name="LoginTests">
<parameter name="browser" value="Chrome" />
<parameter name="grid" value="false" />
<parameter name="environmentURL" value="stage" />
<parameter name="retry" value="true" />
<classes>
<class name="tests.LoginTests">
</class>
</classes>
</test>
</suite>
CodePudding user response:
You can do this by having your retry analyser set only when a JVM argument is set to true. Your modified annotation transformer would look like below.
This implementation would wire in your retry analyser only when it finds a JVM argument named retry.tests
set to true
.
So whenever you would like the retry analyser to be enabled, then pass in the JVM argument -Dretry.tests=true
package IRetryAnalyzer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
public class AnnotationTransformer implements IAnnotationTransformer {
@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor,Method testMethod) {
if (Boolean.getBoolean("retry.tests")) {
annotation.setRetryAnalyzer(RetryAnalyzer.class);
}
}
}