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.
Related
I want to run multiple tests in chrome. i.e 2 tests parallel in 2 chrome. I do have a maven project defined by the POM (testing.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="mytestsuite" parallel="tests" >
<test name="case1">
<classes>
<class name="Testcases.hello1Test"></class>
</classes>
</test>
<test name="case2">
<classes>
<class name="Testcases.hello2.Test"></class>
</classes>
</test>
</suite>
Code to invoke browse is within my baseTest :
public hello1Page1 hellopage1;
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", chromePrefs);
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setJavascriptEnabled(true);
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
cap.setCapability(ChromeOptions.CAPABILITY, options);
chromePath = System.getProperty("user.dir") + prop.getProperty("driverrPath");
System.setProperty("webdriver.chrome.driver", chromePath);
driver = new ChromeDriver(options);
driver.get(Prop.getProperty("URL"));
hellopage1 = PageFactory.initElements(driver, helloPage1.class);
This is page class :
public class hello1Page extends BaseTest {
WebDriver driver;
public hello1Page(WebDriver driver){
this.driver = driver;
}
public hello1Page method1 {... return this;}
public hello1Page method2 {... return this;}
}
This is test class :
public class hello1Test extends BaseTest
{
#Test(priority = 0)
public void methodT1(){
hello1page.method1();
}
}
I have other tests that follow this same pattern.
What I am assuming is when I run testng.xml, It should go to baseTest 2 times and open 2 chrome then run my 2 tests in separate chrome. But somehow this is not happening. It opens only 1 chrome browser and run only 1 test.
Normally everything works fine like run single test case using maven command but issue is with parallel.
I am expecting this is root cause
hellopage1 = PageFactory.initElements(driver, helloPage1.class);
In BaseTest.
In Pages, declare
WebDriver driver;
also
public className(WebDriver driver){
this.driver = driver;
}
In Test Case
WebDriver driver;
PageClassName obj;
#Test(priority=0)
public void test(){
//Create Login Page object
objLogin = new PageClassName(driver);
List item
Try with following steps :-
Create Threadsafe Webdriver instance like this :
private static ThreadLocal webDriver = new ThreadLocal();
Use getter and setter to use driver like this :-
public static WebDriver getDriver() {
return webDriver.get();
}
static void setWebDriver(WebDriver driver) {
webDriver.set(driver);
}
Add thread-count=2 (TestNg xml file) like this :-
Hope this will help .Thank You! Refer this for more info - https://rationaleemotions.wordpress.com/2013/07/31/parallel-webdriver-executions-using-testng/
If I have 10 classes in testng.xml, it will open 10 browser sessions.
How can I initialize the driver once and only open one browser for one test case then close and open a window again for the second test case and so on?
I have my driver setup code in a constructor, which is maybe a bad way to approach it? How can I initialize it in TNGDriver class and then use it in Testcase1 class?
I tried using #BeforeClass and have a setUp method but that did not work.
TNGDriver class
public abstract class TNGDriver {
public static WebDriver driver;
private static String chromeDriverPath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe";
#SuppressWarnings("deprecation")
public TNGDriver() {
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
ChromeOptions options = new ChromeOptions();
options.addArguments("--incognito");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
driver = new ChromeDriver(capabilities);
driver.manage().window().maximize();
}
public static WebDriver getDriver() {
return driver;
}
public static void setDriver(WebDriver driver) {
TNGDriver.driver = driver;
}
Testcase1 class
public class Testcase1 extends Registration {
#Test(priority = 1)
public void step1_checkSomething() {
//do something
}
#Test(priority = 2)
public void step2_clickOnSomething() {
//click on something
}
}
testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="AutomationFramework" parallel="false" preserve-order="true">
<test name="Registration">
<classes>
<class name="regression.Testcase01" />
<class name="regression.Testcase02" />
</classes>
</test>
</suite>
Chrome Driver opens every time private window by default, You don't need this really.
//options.addArguments("--incognito");
You can make structure like below :
public class TNGDriver {
public static WebDriver driver;
private static String chromeDriverPath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe";
public void DriverConfiguration() {
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
ChromeOptions options = new ChromeOptions();
options.addArguments("--incognito");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
driver = new ChromeDriver(capabilities);
driver.manage().window().maximize();
}
public void QuitDriver(){
driver.quit();
}
}
Unit Test cases:
public class Testcase1 extends Registration {
TNGDriver objTND = new TNGDriver();
#BeforeTest
public void initializeDriver(){
objTND.DriverConfiguration();
}
#Test(priority = 1)
public void step1_checkSomething() {
//do something
}
#Test(priority = 2)
public void step2_clickOnSomething() {
//click on something
}
#AfterTest
public void initializeDriver(){
objTND.QuitDriver();
}
}
If you want to use browser(to open) before each #Test, You can use this same method with #BeforeMethod annotation.
I need some help to figure out the problem while cross-browser selenium java test execution through the Saucelabs. I'm running one test over 2 browsers selected from the Jenkins job.
While the execution one test is passed another one (the similar) is getting failure with the error: 504 Gateway Time-out. The server didn't respond in time.
So it's unable to move into the next step.
It seems like one test interrupts another. Both tests are running under their own tunnel and thread.
Aug 30, 2018 7:17:44 AM org.openqa.selenium.remote.ProtocolHandshake
createSession
INFO: Detected dialect: OSS
30-08-2018 07:17:49.235 [TestNG-PoolService-0] INFO
[com.***.tests.TestBase_Local:96] - Open a site URLDriver: RemoteWebDriver:
chrome on XP (4f5a5d685f4c44c9a5864e91cb8f11e9)
Driver: RemoteWebDriver: chrome on XP (4f5a5d685f4c44c9a5864e91cb8f11e9)
thread id:14 Timestamp :2018-08-30T07:17:49.370
30-08-2018 07:17:51.912 [TestNG-PoolService-0] INFO
[com.**.tests.TestBase_Local:35] - Select 'No thanks' on the popup
Aug 30, 2018 7:17:53 AM org.openqa.selenium.remote.ProtocolHandshake
createSession
INFO: Detected dialect: OSS
30-08-2018 07:17:58.886 [TestNG-PoolService-1] INFO
[com.**.tests.TestBase_Local:96] - Open a site URLDriver:
RemoteWebDriver: MicrosoftEdge on ANY (c6978c03531d408485588ba501ff0589)
Driver: RemoteWebDriver: MicrosoftEdge on ANY
(c6978c03531d408485588ba501ff0589)
thread id:15 Timestamp :2018-08-30T07:17:58.887
30-08-2018 07:18:03.406 [TestNG-PoolService-1] INFO
[com.**.tests.TestBase_Local:35] - Select 'No thanks' on the popup
30-08-2018 07:18:05.337 [TestNG-PoolService-1] INFO
[com.**.tests.TestBase_Local:38] - Search by input
Sharing the code:
public class Search extends RemoteTestBase {
#Test(dataProvider = "browsers")
public void SolrSearchTest(String browser, String version, String os, Method method) throws Exception {
this.createRemoteDriver(browser, version, os, method.getName());
System.out.println("Driver: " + driver.toString());
Application app = new Application(driver);
ConfigFileReader configRead = new ConfigFileReader();
WebDriverWait wait = new WebDriverWait(driver,100);
app.homePage().SelectNoThanks();
Log.info("Select 'No thanks' on the popup");
app.searchField().SearchBy(configRead.SearchInput());
Log.info("Search by input");
}
}
The extended RemoteTestBase class:
public class RemoteTestBase {
public WebDriver driver;
private static String baseUrl;
RandomDataSelect randomuser;
private PropertyLoader propertyRead;
public Logger Log = Logger.getLogger(TestBase_Local.class.getName());
private static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
private static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");
#BeforeMethod
#DataProvider(name = "browsers", parallel = true)
public static Object[][] sauceBrowserDataProvider(Method testMethod) throws JSONException {
String browsersJSONArrayString = System.getenv("SAUCE_ONDEMAND_BROWSERS");
System.out.println(browsersJSONArrayString);
JSONArray browsersJSONArrayObj = new JSONArray(browsersJSONArrayString);
Object[][] browserObjArray = new Object[browsersJSONArrayObj.length()][3];
for (int i=0; i < browsersJSONArrayObj.length(); i++) {
JSONObject browserObj = (JSONObject)browsersJSONArrayObj.getJSONObject(i);
browserObjArray[i] = new Object[]{ browserObj.getString("browser"), browserObj.getString("browser-version"), browserObj.getString("os")};
}
return browserObjArray;
}
void createRemoteDriver(String browser, String version, String os, String methodName) throws Exception {
DesiredCapabilities capabilities = new DesiredCapabilities();
Class<? extends RemoteTestBase> SLclass = this.getClass();
capabilities.setCapability("browserName", browser);
if (version != null) {
capabilities.setCapability("browser-version", version);
}
capabilities.setCapability("platform", os);
capabilities.setCapability("name", SLclass.getSimpleName());
capabilities.setCapability("tunnelIdentifier", "***");
driver = (new RemoteWebDriver(new URL("http://" + SAUCE_USERNAME + ":" + SAUCE_ACCESS_KEY + "#ondemand.saucelabs.com:80/wd/hub"), capabilities));
randomuser = new RandomDataSelect();
propertyRead = new PropertyLoader();
baseUrl = propertyRead.getProperty("site.url");
getURL();
}
private void getURL () {
driver.get(baseUrl);
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
this.annotate("Visiting HDSupply page..." + driver.toString());
Log.info("Open a site URL" + "Driver: " + driver.toString());
}
private void printSessionId() {
String message = String.format("SauceOnDemandSessionID=%1$s job-name=%2$s",(((RemoteWebDriver) driver).getSessionId()).toString(), "some job name");
System.out.println(message);
}
#AfterMethod(description = "Throw the test execution results into saucelabs")
public void tearDown(ITestResult result) throws Exception {
((JavascriptExecutor) driver).executeScript("sauce:job-result=" + (result.isSuccess() ? "passed" : "failed"));
printSessionId();
driver.quit();
}
void annotate(String text) {
((JavascriptExecutor) driver).executeScript("sauce:context=" + text);
}
}
The suite.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Tests Suite" verbose="4" parallel="tests" data-provider-thread-count="2">
<test name="AllTests" parallel="methods">
<classes>
<class name="com.***.tests.Search"/>
</classes>
</test>
</suite>
Project info: java, selenium, testng, maven, saucelabs, jenkins
The problem lies in your test code. Its definitely related to race condition between your #Test methods [ you have your parallel="true" in your #DataProvider annotation and parallel="methods" ]
You need to refactor your code such that your driver object is thread safe.
Some of the ways in which you can do it is using :
ThreadLocal variants of WebDriver.
Create your webdriver instance and inject that as an attribute into the ITestResult object.
The below sample shows how to use a ThreadLocal variant to make your code thread-safe
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
public class RemoteTestBase {
public static final ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<>();
private static String baseUrl;
private static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
private static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");
void createRemoteDriver(String browser, String version, String os, String methodName)
throws Exception {
DesiredCapabilities capabilities = new DesiredCapabilities();
Class<? extends RemoteTestBase> SLclass = this.getClass();
capabilities.setCapability("browserName", browser);
if (version != null) {
capabilities.setCapability("browser-version", version);
}
capabilities.setCapability("platform", os);
capabilities.setCapability("name", SLclass.getSimpleName());
capabilities.setCapability("tunnelIdentifier", "***");
URL url = new URL(
"http://" +
SAUCE_USERNAME + ":" +
SAUCE_ACCESS_KEY + "#ondemand.saucelabs.com:80/wd/hub");
RemoteWebDriver rwd = new RemoteWebDriver(url, capabilities);
driver.set(rwd);
getURL();
}
protected static RemoteWebDriver getDriver() {
return driver.get();
}
private void getURL() {
getDriver().get(baseUrl);
getDriver().manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
this.annotate("Visiting HDSupply page..." + driver.toString());
}
private void printSessionId() {
String message = String.format("SauceOnDemandSessionID=%1$s job-name=%2$s",
getDriver().getSessionId(), "some job name");
System.out.println(message);
}
#AfterMethod(description = "Throw the test execution results into saucelabs")
public void tearDown(ITestResult result) {
String txt = "sauce:job-result=" + (result.isSuccess() ? "passed" : "failed");
getDriver().executeScript(txt);
printSessionId();
getDriver().quit();
}
void annotate(String text) {
getDriver().executeScript("sauce:context=" + text);
}
}
All your sub-classes would try to access the RemoteWebDriver object via getDriver() method.
The caveat is that your #BeforeMethod needs to call createRemoteDriver() so that the RemoteWebDriver object gets instantiated and pushed into the ThreadLocal context which will be valid and be accessible within a #Test method.
The rule is always #BeforeMethod (driver instantiation happens) > #Test (driver gets consumed > #AfterMethod (driver cleanup should happen). This is the only combo wherein a RemoteWebDriver object is valid within a ThreadLocal context.
I'm writing Java based selenium-web-driver tests to run a parallel cross browser test using testng .
I have set the tests to run parallel on my xml file.The file looks like this :
<suite name="TestSuite" thread-count="2" parallel="tests" >
<test name="ChromeTest">
<parameter name="browser" value="Chrome" />
<classes>
<class name="test.login"/>
<class name="test.main"/>
<class name="test.logout"/>
</classes>
</test>
<test name="FirefoxTest">
<parameter name="browser" value="Firefox" />
<classes>
<class name="test.login"/>
<class name="test.main"/>
<class name="test.logout"/>
</classes>
</test>
But when i run test, both browser instances gets opened (Chrome opens first and starts execution and after a delay Firefox is opened).
In that case , the driver object gets overwritten by Firefox driver and chrome stops execution.Tests continue execution on Firefox and
gets completed successfully.
The structure of the project is like this :
Created a driverbase.class to load driver corresponding to browser which has my #Beforesuite.
Crteated individual classes for pages.(Eg: login.class , main.class etc) which has only #Test method and have extended driverbase class to get driver.
Test are run suceessfully when i set parallel to none on xml file
<suite name="TestSuite" thread-count="2" parallel="none" >
How can i overcome this issue? How to run tests in parallel without this issue?
The driverbase class is like this :
public class driverbase {
private String baseUrl;
private String nodeUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
public static WebDriver driver = null;
/**
* This function will execute before each Test tag in testng.xml
* #param browser
* #throws Exception
*/
#BeforeSuite
#Parameters("browser")
public WebDriver setup(String browser) throws Exception{
//Check if parameter passed from TestNG is 'firefox'
if(browser.equalsIgnoreCase("firefox")){
System.out.println("Browser : "+browser);
FirefoxProfile profile = new FirefoxProfile();
profile.setAcceptUntrustedCertificates(true);
//create firefox instance
driver = new FirefoxDriver(profile);
}
//Check if parameter passed as 'chrome'
else if(browser.equalsIgnoreCase("chrome")){
System.out.println("Browser : "+browser);
//set path to chromedriver.exe You may need to download it from http://code.google.com/p/selenium/wiki/ChromeDriver
System.setProperty("webdriver.chrome.driver","C:\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--test-type");
//create chrome instance
driver = new ChromeDriver(options);
}
else{
//If no browser passed throw exception
System.out.println("Browser is incorrect");
throw new Exception("Browser is not correct");
}
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
return driver;
}
Thanks for the help :)
#BeforeSuite methods are not supposed to return something. => replace by void
Your testng has 2 differents tests, but #BeforeSuite will always be run once by suite what your comment shows you doesn't expect it. => replace by #BeforeTest
When you run in //, 2 threads are settings the driver value (one with firefox, one with chrome) which explains your problem.
You can try something like:
public class driverbase {
private String baseUrl;
private String nodeUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
public WebDriver driver;
#BeforeTest
#Parameters("browser")
public void setup(String browser) throws Exception {
if(browser.equalsIgnoreCase("firefox")) {
FirefoxProfile profile = new FirefoxProfile();
profile.setAcceptUntrustedCertificates(true);
driver = new FirefoxDriver(profile);
} else if(browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver","C:\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--test-type");
driver = new ChromeDriver(options);
} else {
throw new Exception("Browser is not correct");
}
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
You should have a look on http://fluentlenium.org/ too.
To sure that same instance of webdriver won't be assigned to multiple tests. The method where driver instances are being created should be synchronized. This should solve the issue.
public synchronized void setup(String browser) throws Exception {
if(browser.equalsIgnoreCase("firefox")) {
FirefoxProfile profile = new FirefoxProfile();
profile.setAcceptUntrustedCertificates(true);
driver = new FirefoxDriver(profile);
} else if(browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver","C:\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--test-type");
driver = new ChromeDriver(options);
} else {
throw new Exception("Browser is not correct");
}
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
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;
}