Trying to run my automation project in parallel using java - java
I built an automation framewoek using maven, java, testng, selenium.
As for now I am running my tests sequential and I would like to run them in parallel, however each time I try to run them in parallel there are several browsers that opens (like intended to) but I pay attention that only one window get the actions and other one opens (navigate to the url needed, but no action is being done beside it), I am using threads in order to initialize my webdriver and that they won't intefere each other in doing the actions.
This is my BaseTest class where I declare my webdriver and init it:
public class BaseUiTest extends BaseApiTest {
private static final Browser BROWSER = Browser.valueOf(EnvConf.getProperty("ui.browser.type"));
protected DriverWrapper driver;
protected LoginPage loginPage;
protected TopBar topBar;
protected CmsPage cmsPage;
#BeforeClass(alwaysRun = true)
public final void BaseUiSetup(ITestContext context) throws IOException {
driver = DriverWrapper.open(BROWSER, TEST_OUTPUT_FOLDER);
DriverFactory.getInstance().setDriver(driver);
driver = DriverFactory.getInstance().getDriver();
System.out.println("HEREREREREFSLKFSKJHFKJSHKJFSHKJFSHKJFSHKJFSHKJ");
loginPage = new LoginPage(driver);
cmsPage = new CmsPage(driver);
}
#AfterClass(alwaysRun = true)
public final void baseTeardown() {
Date testEndTime = new Date();
if (driver != null) {
printBrowserLog();
DriverFactory.getInstance().removeDriver();
}
Log.i("testEndTime=[%s]", testEndTime);
}
}
My DriverWrapper class only wrap the traditional WebDriver interface in this manner:
public class DriverWrapper implements WebDriver {
private final WebDriver driver;
private final static Logger Log = Logger.getLogger(DriverWrapper.class.getName());
private static final Duration WAIT_ELEMENT_TIMEOUT = new Duration(EnvConf.getAsInteger("ui.locator.timeout.sec"), TimeUnit.SECONDS);
private DriverWrapper(WebDriver driver){
this.driver = driver;
}
public static DriverWrapper open(Browser browser, File downloadsFolder) {
Log.info(String.format("Starting new %s browser driver", browser));
switch (browser) {
case FIREFOX:
return createFireFoxInst();
case CHROME:
return createChromeInst(downloadsFolder);
default:
throw new IllegalArgumentException("'" + browser + "'no such browser type");
}
}
private static DriverWrapper createChromeInst(File downloadsFolder){
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.setHeadless(EnvConf.getAsBoolean("selenium.headless"));
options.setAcceptInsecureCerts(true);
options.addArguments("--lang=" + EnvConf.getProperty("selenium.locale"));
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.SEVERE);
options.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
options.addArguments("--window-size=" + EnvConf.getProperty("selenium.window_size"));
ChromeDriverService service = ChromeDriverService.createDefaultService();
ChromeDriver driver = new ChromeDriver(service, options);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//enabling downloading resources when driver is headless
enableHeadlessDownload(service, driver, downloadsFolder);
return new DriverWrapper(driver);
}
private static void enableHeadlessDownload(ChromeDriverService service, ChromeDriver driver, File downloadsFolder){
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
Map<String, Object> commandParams = new HashMap<>();
commandParams.put("cmd", "Page.setDownloadBehavior");
Map<String, String> params = new HashMap<>();
params.put("behavior", "allow");
params.put("downloadPath", downloadsFolder.getAbsolutePath());
commandParams.put("params", params);
ObjectMapper objectMapper = new ObjectMapper();
String command = objectMapper.writeValueAsString(commandParams);
String u = service.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
CloseableHttpResponse response = httpClient.execute(request);
Log.info(String.format("enable download, status code=[%d]", response.getCode()));
}catch (Exception e){
Log.error("failed to send command=[age.setDownloadBehavior] to chrome server");
Log.error(e.getMessage());
}
}
}
This is my DriverFactory class (where all the magic happens and where I defined my webdriver threads):
public class DriverFactory {
private DriverFactory() {}
private static DriverFactory instance = new DriverFactory();
public static DriverFactory getInstance() {
return instance;
}
ThreadLocal<DriverWrapper> driver = new ThreadLocal<>(); //thread local driver object for webdriver
public DriverWrapper getDriver() {
return driver.get();
}
public void setDriver(DriverWrapper driverParam){ //call this method to set the driver object
driver.set(driverParam);
}
public void removeDriver(){
driver.get().quit();
driver.remove();
}
}
And this is my testng.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Automation_Suite" parallel="tests" thread-count="4">
<test name="Critical tests to run after DEV deploy build">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.categories.CategoriesTest"/>
</classes>
</test>
<test name="Critical tests to run after DEV deploy build2">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.content_manager.ContentManagerPresentationTest"/>
</classes>
</test>
<test name="Critical tests to run after DEV deploy build3">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.cyberpedia.TermsTest"/>
</classes>
</test>
<test name="Critical tests to run after DEV deploy build4">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.institutions.ClassesTest"/>
</classes>
</test>
</suite>
And this is the profiles section in my pom.xml file that defines this profile(critical tests):
<profiles>
<profile>
<id>critical</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>critical_tests.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
This is a test class for example:
public class ContentManagerPresentationTest extends BaseUiTest {
private static final String PREVIEW_IMAGE_PATH = "/automation-tests/src/test/resources/images/lion.png";
private static final String PPT_FILE_PATH = "/automation-tests/src/test/resources/ppt/Google_Adword_Project.pptx";
private static final String NOT_EXIST_PRESENTATION_NAME = "Not Exist";
private ContentManagerPresentationsCMSPage contentManagerPresentationsCMSPage;
private VideosNPresentationsRow row;
#BeforeMethod(alwaysRun = true)
public void setUpMethod(){
adminSignIn();
topBar.clickItem(TopNavBarItem.CMS);
contentManagerPresentationsCMSPage = cmsPage.selectItemSidePanelDropDownMenu(SidePanelDropDownMenuOptions.CONTENT_MANAGER, "presentations");
Assert.assertTrue(contentManagerPresentationsCMSPage.verifyElement());
}
#AfterMethod(alwaysRun = true)
public void tearDownMethod(){
cmsPage.clickLogoutButtonAndVerify();
}
#Test(priority = 10, dataProvider = "cancelUploadPresentationsProvider", description = "Cancel upload a new presentation")
public void cancelUploadNewPresentation(String name, String desc, String previewImgPath, String pptFilePath, boolean toCreate) throws FileNotFoundException {
contentManagerPresentationsCMSPage
.uploadNewPresentationOrVideo(name, desc, previewImgPath, pptFilePath, toCreate);
Assert.assertTrue(contentManagerPresentationsCMSPage.verifyElement(), "Expected to be on presentation main page");
T_Logger.info("cancelling and returning to main presentation page is successful!");
}
#DataProvider(name = "cancelUploadPresentationsProvider")
public Object[][] cancelUploadPresentationsProvider(){
return new Object[][]{
{"Automation Test", "Automation Desc",
PREVIEW_IMAGE_PATH,
PPT_FILE_PATH,
false}
};
}
#Test(priority = 20, description = "Negative test for non exist presentation in the table")
public void verifyNonExistPresentationInTable(){
row = contentManagerPresentationsCMSPage.findRowByVideoName(NOT_EXIST_PRESENTATION_NAME);
Assert.assertNull(row);//, String.format("Row should be null, instead we got =[%s]", row.toString()));
T_Logger.info("Verification of not exist row in the table is successful");
}
#Test(priority = 25, dataProvider = "validationFieldsProvider", description = "Verify mandatory field requirements are fulfilled")
public void verifyMandatoryFieldsPresentation(String name, String desc, String imagePreviewPath,
String pptFilePath, boolean toCreate, int msgNumber, String expectedMsg) throws FileNotFoundException {
contentManagerPresentationsCMSPage
.uploadNewPresentationOrVideo(name, desc,
imagePreviewPath,
pptFilePath,
toCreate);
Assert.assertEquals(contentManagerPresentationsCMSPage.getActualErrorMsg(msgNumber), expectedMsg,
String.format("Expected error message=[%s] is not displayed as expected, instead actual message=[%s]",
expectedMsg, contentManagerPresentationsCMSPage.getActualErrorMsg(msgNumber)));
contentManagerPresentationsCMSPage.clickCreateOrCancel(false);
T_Logger.info("Verification of mandatory fields is successful");
}
#DataProvider(name = "validationFieldsProvider")
public Object[][] validationFieldsProvider(){
return new Object[][] {
{"", "Automation Desc", PREVIEW_IMAGE_PATH, PPT_FILE_PATH, true, 1, "Enter Presentation name"},
{"Automation Test", "Automation Desc", "", PPT_FILE_PATH, true, 2, "Preview Image is required"},
{"Automation Test", "Automation Desc", PREVIEW_IMAGE_PATH, "", true, 3, "Presentation file is required"}
};
}
#Test(priority = 30, dataProvider = "addNewPresentationsProvider", description = "Add new presentation",groups = {"critical"})
public void addNewPresentationAndVerify(String name, String desc, String previewImgPath, String pptFilePath, boolean toCreate) throws FileNotFoundException {
contentManagerPresentationsCMSPage
.uploadNewPresentationOrVideo(name, desc, previewImgPath, pptFilePath, toCreate);
row = contentManagerPresentationsCMSPage.findRowByVideoName(name);
Assert.assertEquals(row.getNameTxt(), name, String.format("Actual name is =[%s] not as expected", row.getNameTxt()));
}
#DataProvider(name = "addNewPresentationsProvider")
public Object[][] addNewPresentationsProvider(){
return new Object[][]{
{"Automation Test", "Automation Desc", PREVIEW_IMAGE_PATH, PPT_FILE_PATH, true}
};
}
#Test(priority = 35, dataProvider = "caseSensitiveProvider", description = "Validation existence of presentation - case sensitive")
public void searchTablePresentationsCaseSensitive(String pptName){
row = contentManagerPresentationsCMSPage.findRowByVideoName(pptName);
Assert.assertNotNull(row);
}
#DataProvider(name = "caseSensitiveProvider")
public Object[][] caseSensitiveProvider(){
return new Object[][] {
{"Automation Test"},
{"AUTOMATION TEST"}
};
}
}
The problem: when I run mvn test -Pcritical there are 4 chrome browsers which opens but the actions occur only in one browser (although I defined and manage my webdrivers as threads to handle each one in his own thread), what am I missing?
Related
Selenium, TestNg parallel run not working as expected
I have 3 test classes consisting of multiple test methods that I want to run in parallel. I'm using ThreadLocal for isolating webdriver instances per thread. When I run the tests in sequential manner everything looks fine but problem arises when I run them in parallel. Below is my suite file <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="platform" parallel="classes" thread-count="5"> <test name="platform"> <classes> <class name="com.sat.platform.mobile.PlatformMobileIdCaptureMonitoringWf11"></class> <class name="com.sat.platform.mobile.PlatformMobileIdVerificationMonitoringWf2"></class> <class name="com.sat.platform.mobile.PlatformMobileIdandIVMonitoringWf3"></class> <class name="com.sat.platform.mobile.PlatformMobileLivenessMonitoringWf6"></class> <class name="com.sat.platform.mixed.PlatformMixedIdSimilarityMonitoringWf2and5"></class> </classes> </test> </suite> I'm initializing Webdriver in #BeforeClass in BrowserClient.java as below. protected WebDriver driver; private static int implicitWaitTime; private static int explicitWaitTime; private static int fluentWaitTime; private static int pollingTime; protected static WebDriverWait explicitWait; protected static Wait<WebDriver> fluentWait; private static String browser; protected static Browsers browsers; static { Properties prop = new Properties(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); InputStream stream = loader.getResourceAsStream("browser.properties"); try { prop.load(stream); } catch (IOException e) { } implicitWaitTime = Integer.parseInt(prop.getProperty("browser.implicit.wait.timeout")); explicitWaitTime = Integer.parseInt(prop.getProperty("browser.explicit.wait.timeout")); fluentWaitTime = Integer.parseInt(prop.getProperty("browser.fluent.wait.timeout")); pollingTime = Integer.parseInt(prop.getProperty("browser.wait.polling.time")); browser = System.getProperty("browser"); } #BeforeClass public void initializeEnv() throws MalformedURLException { driver = BrowserFactory.createInstance(browser, implicitWaitTime); DriverFactory.getInstance().setDriver(driver); driver = DriverFactory.getInstance().getDriver(); explicitWait = new WebDriverWait(driver, explicitWaitTime); fluentWait = new FluentWait(driver).withTimeout(Duration.of(fluentWaitTime, SECONDS)) .pollingEvery(Duration.of(pollingTime, SECONDS)) .ignoring(NoSuchElementException.class); } the used class here i.e BrowserFactory.java public static WebDriver createInstance(String browser, int implicitWaitTime) throws MalformedURLException { WebDriver driver = null; Browsers browserEnum = Browsers.valueOf(browser); String testVideo = ImageProcessingUtils.getAbsolutePath("digital_copy.mjpeg", false); switch (browserEnum) { case chrome: ChromeOptions options = new ChromeOptions(); options.addArguments("--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream", "--use-file-for-fake-video-capture=" + testVideo, "--start-maximized"); driver = new ChromeDriver(options); break; case firefox: FirefoxProfile firefoxProfile = new FirefoxProfile(); firefoxProfile.setPreference("media.navigator.permission.disabled", true); firefoxProfile.setPreference("media.navigator.streams.fake", true); firefoxProfile .setPreference("browser.private.browsing.autostart", false); FirefoxOptions firefoxOptions = new FirefoxOptions(); firefoxOptions.setProfile(firefoxProfile); driver = new FirefoxDriver(firefoxOptions); break; } } DriverFactory.java public class DriverFactory { private static DriverFactory instance = new DriverFactory(); private static ThreadLocal<WebDriver> driver = new ThreadLocal<>(); private static List<WebDriver> driversList = new ArrayList(); private DriverFactory(){ } public static DriverFactory getInstance() { return instance; } public WebDriver getDriver(){ WebDriver localDriver = driver.get(); driversList.add(localDriver); return localDriver; } public void setDriver(WebDriver driver){ this.driver.set(driver); } public static void removeDriver(){ for(WebDriver driver : driversList) { driver.quit(); } } } And my test classes extends BrowserClient.java where i can use the driver directly. One of the common method in all 3 test classes is merchant_gets_oauth_token() as shown below. The problem is when test suite is run, 3 firefox browsers are open in parallel and all of them navigates to the login page but only 1 and sometimes 2 of the tests passes while the 3rd one fails (unable to login). #Test public void merchant_gets_oauth_token() { OAuth2Client client = new OAuth2Client(); String loginUrl = DslConfigFactory.getEnvConfig("portal.customer.url"); driver.get(loginUrl); CustomerPortalLoginPage loginPage = new CustomerPortalLoginPage(driver); log.info("----------merchant logging to customer portal to get oauth token----------"); loginPage.login(merchantUser.getEmail(), merchantUser.getPassword()); CustomerPortalHomePage homePage = new CustomerPortalHomePage(driver); homePage.clickOnSettings(); CustomerPortalSettingsPage settingsPage = new CustomerPortalSettingsPage(driver); settingsPage.clickOnApiCredentials(); CustomerPortalApiCredentialsPage apiCredentialsPage = new CustomerPortalApiCredentialsPage(driver); clientCredentials = apiCredentialsPage.getOauth2ClientCredentials(); oauthToken = client.getOauthToken(clientCredentials.get("token"), clientCredentials.get("secret")); } I have been struggling with this problem for a while and had looked up lot of online resources without help. Maybe somebody here is able to do the RCA. Thanks in Advance!!
public static void removeDriver(){ for(WebDriver driver : driversList) { driver.quit(); } } Here, replace driver.quit() with driver.close(). driver.close() method it will close only current driver. driver.close() closes all drivers. When first instance executes removeDriver(), it will closes all windows/drivers. Then next instance try to execute removeDriver(),there driver is not available because it is already closed by previous instance of driver.so you get error.
Parellel testing with TestNG - Tests only run on one browser
I have created a test suite using DataProvider DataFactory and my TestNG file is sending browser details as parameters. In testNG XML I'm calling my data factory class. I'm also using browsestack for testing (although I doubt this has anything to do with the problem I"m having) Tests run without any issues when I don't add parrellel="true" to testng file. I have a feeling it has something to do with same driver being used by each browser, but I'm out of depth to solve this at the moment. Any guidance is appreciated. Here's the code. TestNG.XML <suite name="Suite" verbose="1" parallel="tests"> <!-- Test with Chrome --> <test name="ChromeTest" group-by-instances="true"> <parameter name="browser" value="Chrome"></parameter> <parameter name="browserVersion" value="47"></parameter> <parameter name="platform" value="Windows"></parameter> <parameter name="platformVersion" value="7"></parameter> <classes> <class name="Resources.TestFactory"/> </classes> </test> <!-- Test with Firefox --> <test name="FirefoxTest" group-by-instances="true"> <parameter name="browser" value="Firefox"></parameter> <parameter name="browserVersion" value="43"></parameter> <parameter name="platform" value="Windows"></parameter> <parameter name="platformVersion" value="7"></parameter> <classes> <class name="Resources.TestFactory"/> </classes> </test> </suite> Data Factory Class public class TestFactory { #Factory(dataProvider = "LoginCredentials", dataProviderClass=TestData.class) public Object[] createInstances(int testNo, String userName, String password) { Object[] result = new Object[1]; int i=0; System.out.println("Inside LoginCredentials Factory - " + userName + "---" + password); if(testNo==1){ result[i] = new Test_BookingEngine_Login(userName, password); i++; System.out.println("Object Array : " + Arrays.deepToString(result)); } else if(testNo==2){ result[i] = new Test_BookingManagement_OpenBooking(userName); i++; System.out.println("Object Array : " + Arrays.deepToString(result)); } System.out.println("outside for"); return result; } } Suite - Driver Initialization #BeforeTest #Parameters(value ={"browser", "browserVersion", "platform", "platformVersion"}) public void initBrowser(String browser, String browserVersion, String platform, String platformVersion) throws Exception{ //Initializing browser in cloud cloudCaps = new DesiredCapabilities(); cloudCaps.setCapability("browser", browser); cloudCaps.setCapability("browser_version", browserVersion); cloudCaps.setCapability("os", platform); cloudCaps.setCapability("os_version", platformVersion); cloudCaps.setCapability("browserstack.debug", "true"); cloudCaps.setCapability("browserstack.local", "true"); driver = new RemoteWebDriver(new URL(URL), cloudCaps); } Sample Test public Test_BookingEngine_Login(String userName, String password) { this.userName = userName; this.password = password; } #Test (groups = {"Login"}) public void testHomePageAppearCorrect() throws InterruptedException{ //Starting test and assigning test category test = logger.startTest("Login to Temptation", "<b>Successful user login or Pop up advising incorrect login details</b><br/><br/>" + browserInfo) .assignCategory("Regression", "Booking Engine") .assignAuthor("Dinesh Cooray"); System.out.println("Inside login test"); System.out.println("Browser inside login test : "); driver.get("http://dev-thor2.tempoholidays.com/"); test.log(LogStatus.INFO, "HTML", "Navigated to http://dev-thor2.tempoholidays.com/"); //create Login Page object objLogin = new BookingEngine_Login(driver); //login to application objLogin.loginToTemptationBookingEngine(userName, password, test); //check if alert advising username or password is is incorrect try { //incorrect login details, user should not allow login if(driver.switchTo().alert().getText().toLowerCase().contains("user name or password is wrong")){ test.log(LogStatus.INFO, "HTML", "<b>Popup - </b>" + driver.switchTo().alert().getText()); driver.switchTo().alert().accept(); Assert.assertTrue(true); } }
I am guessing RemoteWebDriver driver; would be a line you added at the class level. What is happening is that you have already declared the variable at class level. i.e. memory is already allocated to it.When you do something like this driver = new RemoteWebDriver(new URL(URL), cloudCaps); you are just setting and resetting the values of the same variable in every #BeforeTest What you need to do is create a factory that will return an instance of RemoteWebDriver based on a parameter you pass to it.Essentially the factory will create a new object and return only if an existing object doesn't exist. Declare and initialise the driver (from factory) in your #Test Methods Sample code for the factory would be something like static RemoteWebDriver firefoxDriver; static RemoteWebDriver someOtherDriver; static synchronized RemoteWebDriver getDriver(String browser, String browserVersion, String platform, String platformVersion) { if (browser == 'firefox') { if (firefoxDriver == null) { DesiredCapabilities cloudCaps = new DesiredCapabilities(); cloudCaps.setCapability("browser", browser); cloudCaps.setCapability("browser_version", browserVersion); cloudCaps.setCapability("os", platform); cloudCaps.setCapability("os_version", platformVersion); cloudCaps.setCapability("browserstack.debug", "true"); cloudCaps.setCapability("browserstack.local", "true"); firefoxDriver = new RemoteWebDriver(new URL(URL),cloudCaps); } } else { if (someOtherDriver == null) { DesiredCapabilities cloudCaps = new DesiredCapabilities(); cloudCaps.setCapability("browser", browser); cloudCaps.setCapability("browser_version", browserVersion); cloudCaps.setCapability("os", platform); cloudCaps.setCapability("os_version", platformVersion); cloudCaps.setCapability("browserstack.debug", "true"); cloudCaps.setCapability("browserstack.local", "true"); someOtherDriver = new RemoteWebDriver(new URL(URL),cloudCaps); } return someOtherDriver; } } }
Execute one method in one test tag in parallel in testng
This is my class containing test method which I want to execute in parallel. Each input from Data Provider is a new thread. When I execute this method in 2 threads as Data Provider has 2 inputs, test hangs in one browser and other executes public class DemoTest { private static final ThreadLocal<WebDriver> webDriverThreadLocal= new InheritableThreadLocal<>(); private String baseUrl; private String severity; #BeforeMethod public void beforeMethod() { WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS); driver.manage().window().maximize(); webDriverThreadLocal.set(driver); System.out.println("In before method:"+Thread.currentThread().getId()); System.out.println("FF hashcode:"+driver.hashCode()); } #DataProvider(name = "data-provider", parallel=true) public Object[][] dataProviderMethod() throws IOException { System.out.println("On dp"); new Object[] { 1, "a" }, new Object[] { 2, "b" }, } public void testProgramOptions(Integer n, String s) { WebDriver driver = webDriverThreadLocal.get(); baseUrl = "http://www.google.com/"; driver.get(baseUrl); System.out.println("method f id:"+Thread.currentThread().getId()+" n:"+n+" s:"+s); //test continues } #AfterMethod public void afterMethod() { WebDriver driver = webDriverThreadLocal.get(); System.out.println("In after method for id:"+Thread.currentThread().getId()); driver.quit(); } } This is testng.xml <suite name="Suite" parallel="methods"> <test name="prelogin" > <classes> <class name="DemoTest"></class> </classes> </test> </suite>
Parameterized Selenium Tests in Parallel with TestNG
First of all, sorry for my english, it's not so perfect :) So I'm facing with the following problem: I'm trying to run parallel tests in different browsers using Selenium Grid and TestNg and I pass the parameters in the #BeforeTest method. My problem is that when every test get initialized, it seems that they will use the last test's parameters. So in this example when I run the test, it will open two Chrome, instead of one Firefox and one Chrome. (The browser.getDriver() method returns a RemoteWebDriver) TestNG.xml: <suite thread-count="2" verbose="10" name="testSuite" parallel="tests"> <test name="nameOfTheTestFirefox"> <parameter name="platform" value="windows"/> <parameter name="browserVersion" value="32"/> <parameter name="browserName" value="firefox"/> <classes> <class name="example.test.login.LoginOverlayTest"/> </classes> </test> <!-- nameOfTheTestFirefox --> <test name="nameOfTheTestChrome"> <parameter name="platform" value="windows"/> <parameter name="browserVersion" value="38"/> <parameter name="browserName" value="chrome"/> <classes> <class name="example.test.login.LoginOverlayTest"/> </classes> </test> <!-- nameOfTheTestChrome --> </suite> <!-- testSuite --> The AbstractTest class: public class SeleniumTest { private static List<WebDriver> webDriverPool = Collections.synchronizedList(new ArrayList<WebDriver>()); private static ThreadLocal<WebDriver> driverThread; public static BrowserSetup browser; #Parameters({ "browserName", "browserVersion", "platform"}) #BeforeTest() public static void beforeTest(String browserName, #Optional("none") String browserVersion, String platform) throws WrongBrowserException, WrongPlatformException { final BrowserSetup browser = new BrowserSetup(browserName, browserVersion, platform); driverThread = new ThreadLocal<WebDriver>() { #Override protected WebDriver initialValue() { final WebDriver webDriver = browser.getDriver(); webDriverPool.add(webDriver); return webDriver; } }; } public static WebDriver getDriver() { return driverThread.get(); } #AfterTest public static void afterTest() { for (WebDriver driver : webDriverPool) { driver.quit(); } } } And my example #Tests: #Test public void test1() throws InterruptedException { WebDriver driver = getDriver(); System.out.println("START: test1"); driver.get("http://google.com"); Thread.sleep(5000); System.out.println("END: test1, title: " + driver.getTitle()); } #Test public void test2() throws InterruptedException { WebDriver driver = getDriver(); System.out.println("START: test2"); driver.get("http://amazon.com"); Thread.sleep(5000); System.out.println("END: test2, title: " + driver.getTitle()); } #Test public void test3() throws InterruptedException { WebDriver driver = getDriver(); System.out.println("START: test3"); driver.get("http://stackoverflow.com"); Thread.sleep(5000); System.out.println("END: test3, title: " + driver.getTitle()); } So my question is how can I run the tests in parallel with the given parameters in separate threads? Thanks in advance! Peter
Don't make the fields static. private static List<WebDriver> webDriverPool = Collections.synchronizedList(new ArrayList<WebDriver>()); private static ThreadLocal<WebDriver> driverThread; public static BrowserSetup browser;
beforeTest() and afterTest() shouldn't be static if you want to run it in parallel, or make it synchronized to have it thread safe. Also, you do not use declared variable: public static BrowserSetup browser; at all, or you missed something there since you also have: final BrowserSetup browser = new BrowserSetup(browserName, browserVersion, platform); inside beforeTest(...)
testNG parallel execution not working
I am trying to run following test in parallel for two browsers using testNG, while running both the browsers are getting launched with the URL, but the complete test execution is happening for only one browser. Here is my Test Suite class #Test (groups = {"Enable"}) #SuppressWarnings("unused") public class EETestSuite_01 extends ApplicationFunctions{ String URL = Globals.GC_EMPTY; #BeforeTest #Parameters("browser") public void loadTest(String browser) throws IOException{ InitializeTestEnv("EE|BizApp"); if(browser.equalsIgnoreCase("Firefox")) GetBrowser("Firefox"); else if(browser.equalsIgnoreCase("Chrome")){ GetBrowser("Chrome"); } } #AfterMethod public void cleartest() throws InterruptedException{ driver.close(); driver.quit(); driver = null; } public void TC001_Phone_First_Acquisition_Journey_PAYM() throws InterruptedException{ URL = EnvDetail.get(Globals.GC_HOME_PAGE); Map<String,String> TDChoosePlan = null; TDChoosePlan = getData(appName+Globals.GC_TEST_DATA_SHEET,"ChoosePlan",1); try{ launchApp(URL); //driver.navigate().to("javascript:document.getElementById('overridelink').click()"); EEHomePage homePage = PageFactory.initElements(driver, EEHomePage.class); EEShopPage shopPage = homePage.GetToShopPage(); EEPhoneMatrixPage phonePage = shopPage.GetToPhoneMatrixPage(); EEChoosePlanPage planPage = phonePage.ChoosePhone("NokiaLumia1020"); // Implement select phone EEAddonsPage addonPage = planPage.SelectPhonesPlan(TDChoosePlan); EEBasket basketPage = addonPage.GoToBasketPage(); EESecureCheckOut secureChkOutPage = basketPage.GoToSecureCheckOutPage(); secureChkOutPage.ChooseNonExistingCustomer(); EEConfirmation confPage = secureChkOutPage.FillUserRegisterForm(2); }catch(Exception e){ e.printStackTrace(); } } } My XML looks like this <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name = "EEAutomationTestSuite" verbose="2" parallel = "tests" thread-count="100"> <test name="PAYM Acquisition in Chrome"> <parameter name="browser" value="Firefox"></parameter> <classes> <class name="com.testsuite.EETestSuite_01"> </class> </classes> </test> <test name="PAYM Acquisition in FF"> <parameter name="browser" value="Firefox"></parameter> <classes> <class name="com.testsuite.EETestSuite_01"> </class> </classes> </test> </suite> And my code for the Home page is this */ public EEShopPage GetToShopPage() throws InterruptedException{ // longWait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(OR.getProperty("wblShopHeader")))); lblShopHeader = driver.findElement(By.cssSelector(OR.getProperty("wblShopHeader"))); Actions builder = new Actions(driver); Actions hoverOverRegistrar = builder.moveToElement(lblShopHeader); hoverOverRegistrar.perform();Thread.sleep(10000); lnkStartShopping = driver.findElement(By.cssSelector(OR.getProperty("lnkStartShopping"))); mediumWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(OR.getProperty("lnkStartShopping")))); lnkStartShopping.click(); return PageFactory.initElements(driver,EEShopPage.class ); } } Here is the driver public static void GetBrowser(String browser){ try{ if (browser.equalsIgnoreCase("firefox")) { // FirefoxProfile firefoxProfile = new FirefoxProfile(); // File pathToBinary = new File(Globals.GC_FIREFOX_BIN_PATH); // FirefoxBinary ffBinary = new FirefoxBinary(pathToBinary); //firefoxProfile.setPreference("webdriver.load.strategy","unstable"); driver = new FirefoxDriver(); } else if (browser.equalsIgnoreCase("iexplorer")){ System.setProperty("webdriver.ie.driver", System.getProperty("user.dir") + "//resource//drivers//IEDriverServer.exe"); DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); driver = new InternetExplorerDriver(capabilities); } else if (browser.equalsIgnoreCase("chrome")){ System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "//resource//drivers//chromedriver.exe"); I am just guessing that there is a hover action in the home page, and for one browser it works fine but for the other nothing happens.... is it due focus issue ?? Please let me know how to solve this with an example
I cannot make it out from your code, which constructor you are using for your page Object EEHomePage. Because, if you are using default constructor then your PageFactory will not be able to initialize your web elements unless they are defined by #FindBy annotation, PageFactory takes webDriver and Object class as arguments and internally initializes that Object class with provided webDriver.This can be achieved by two ways as below : 1) either define your webElements in your pageObjects using #FindBy annotations as follow : #FindBy(css=//your locator value here) private WebElement lblShopHeader; OR 2) define constructor and initialize your pageobject webdriver by PageFactory provided webdriver as follow : EEHomeShop(WebDriver driver){ this.driver=driver; }