Testng opens only one browser for parallel config - java

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/

Related

Executing Selenium tests one after the other without re launching the browser through testng

I have two testcases that has to be executed
1.Login to an App
2.Perform some operations
Below is the design of my code:
BaseTest.java
public abstract class BaseTest {
public WebDriver driver;
#BeforeSuite
public void openApplication() {
System.setProperty(chrome_key,chrome_value);
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-notifications");
driver = new ChromeDriver(options);
driver.manage().window().maximize();
driver.get(url);
}
}
LoginPage.java
public class LoginPage extends BasePage{
#FindBy (xpath = "//input[#id='username']")
WebElement userName;
#FindBy (xpath = "//input[#id='password']")
WebElement password;
public LoginPage(WebDriver driver) {
super(driver);
PageFactory.initElements(driver, this);
}
public void loginToApp(String username, String pwd) {
}
}
Account.java:
public class NewAccount extends BasePage{
#FindBy(xpath = "//span[text()='Accounts']/../..")
WebElement accountsTab;
public NewAccount(WebDriver driver) {
super(driver);
PageFactory.initElements(driver, this);
}
public void createNewAccount() {
}
}
LoginToApp.java:
public class LoginToApp extends BaseTest {
#Test
public void a_verifyLogin() throws IOException {
LoginPage hp = new LoginPage(driver);
hp.loginToApp(username, password);
}
}
CreateAccount.java:
public class CreateAccount extends BaseTest {
#Test
public void b_createAccountRecord() {
NewAccount na = new NewAccount(driver);
na.createNewAccount();
}
}
testng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Test">
<classes>
<class name="com.testcases.LoginToApp"/>
<class name="com.testcases.CreateAccount"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
With this framework structure, When I execute the testng.xml file, the first test in LoginToApp executes as expected. And When the control comes to the test in CreateAccount, the driver becomes Null and hence failing the execution of the 2nd Test.
Expected Flow:
1.Initialise Browser
2.Launch the url
3.Execute the #Test method of LoginToApp.java
4.Execute the #Test method of CreateAccount.java
Is it possible to achieve the above flow without making the WebDriver as static? If yes, please explain.
1.Initialise Browser (set this under before method)
2.Launch the url (give priority =0)
3.Execute the #Test method of LoginToApp.java (give priority =1)
4.Execute the #Test method of CreateAccount.java( give depends on method )
depends on method only execute if your loginapp test successfully run

How to initialize driver once in WebDriver class and then use it to start other classes?

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.

How to use the same browser window in multiple classes using TestNG Selenium webdriver in java?

I am trying to automate a webpage which has a login and post login has many menu item. I would like to automate it in such a way that it logs into the webpage only once and then use the different menu items. Each new menu item automation is created in a different class.
package pack1;
public class Init {
public WebDriver driver;
ChromeOptions options;
#BeforeSuite
public void beforeSuite() throws AWTException, InterruptedException, IOException {
//Setting Chrome Driver and disabling the save password option
System.setProperty(“webdriver.chrome.driver”,”C:\\Users\\user\\Desktop\\Demo\\chromedriver.exe”);
options = new ChromeOptions();
Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put(“credentials_enable_service”, false);
prefs.put(“profile.password_manager_enabled”, false);
options.setExperimentalOption(“prefs”, prefs);
driver=new ChromeDriver(options);
//Opening the URL
driver.get(“myURL”);
driver.manage().window().maximize();
//Login to the portal
driver.findElement(By.xpath(“.//*[#id=’content-wrapper’]/div/div/div/div/div/div/div/form/div/div[1]/input”)).sendKeys(username);
driver.findElement(By.xpath(“.//*[#id=’content-wrapper’]/div/div/div/div/div/div/div/form/div/div[2]/input”)).sendKeys(password);
driver.findElement(By.xpath(“.//*[#id=’content-wrapper’]/div/div/div/div/div/div/div/form/div/div[3]/button”)).click();
}
#AfterSuite
public void afterSuite() {
//Closing the driver
// driver.close();
}
}
Class A
package pack1;
public class ClassA extends Init{
#Test (priority=0, enabled = true)
public void Setup() throws InterruptedException{
//Traversing the menu to reach contract grower setup
Thread.sleep(5000);
driver.findElement(By.linkText(“Menu1”)).click();
driver.findElement(By.linkText(“SubMenu1”)).click();
}
}
Class B
package pack1;
public class ClassBextends Init{
#Test (priority=0, enabled = true)
public void Setup() throws InterruptedException{
//Traversing the menu to reach contract grower setup
Thread.sleep(5000);
driver.findElement(By.linkText(“Menu2”)).click();
driver.findElement(By.linkText(“SubMenu2”)).click();
}
}
testing.xml
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE suite SYSTEM “http://testng.org/testng-1.0.dtd”>
<suite name=”Suite”>
<test name=”Test”>
<classes>
<class name=”pack1.ClassA”/>
<class name=”pack1.ClassB”/>
<class name=”pack1.Init”/>
</classes>
</test> <!– Test –>
</suite> <!– Suite –>
You should make the following changes:
Configure WebDriver in the Init Class to be static
Don't inherit the Init class in the Test Classes
To use driver in test classes, access it as Init.getDriver();
Base Class
public class Init {
private static WebDriver driver;
public static WebDriver getDriver() {
return driver;
}
#BeforeSuite
public void beforeSuite() {
System.out.println("BS");
System.setProperty("webdriver.chrome.driver", "");
driver = new ChromeDriver();
driver.get("https://www.google.com");
}
#AfterSuite
public void afterSuite() {
System.out.println("AS");
driver.quit();
}
}
Class A
public class ClassA {
#Test(priority = 0, enabled = true)
public void classATest() throws InterruptedException {
System.out.println("classATest");
Init.getDriver().findElement(By.name("q")).sendKeys("Class 1");
}
}
Class B
public class ClassB {
#Test(priority = 0, enabled = true)
public void class2Test() throws InterruptedException {
System.out.println("classBTest");
Init.getDriver().findElement(By.name("q")).sendKeys("Class 2");
}
}
TestNG XML File
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="System Testing" parallel="none" thread-count="1">
<test name="MenuTest" verbose="0">
<classes>
<class name="com.pack1.ClassA" />
<class name="com.pack1.ClassB" />
<class name="com.pack1.Init" />
</classes>
</test>
</suite>
Output
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running TestSuite
BS
Starting ChromeDriver 2.33.506120 (e3e53437346286c0bc2d2dc9aa4915ba81d9023f) on port 16311
Only local connections are allowed.
Mar 09, 2018 2:33:59 PM org.openqa.selenium.remote.ProtocolHandshake.createSession
INFO: Detected dialect: OSS
classATest
classBTest
AS
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.541 sec - in TestSuite

Webdriver object gets overwritten when tests are run in parallel

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();
}

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;
}

Categories

Resources