I am having a selenium grid hub and a selenium node :
java -jar selenium-server-standalone-3.14.0.jar -role hub
java -Dwebdriver.chrome.driver=c:\selenium\chromedriver.exe -jar selenium-server-standalone-3.14.0.jar -role node -hub http://10.X.X.X:4444/grid/register
I have 2 different tests in 2 separate files and classes class A and class B:
The first one, the driver:
#BeforeTest
public void setup() throws MalformedURLException {
nodeUrl = "http://10.133.2.80:4444/wd/hub";
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setBrowserName("chrome");
capabilities.setPlatform(Platform.WINDOWS);
driver = new RemoteWebDriver(new URL(nodeUrl), capabilities);
}
And the second one:
#BeforeTest
public void setup() throws MalformedURLException {
nodeUrl = "http://10.133.2.80:4444/wd/hub";
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setBrowserName("chrome");
capabilities.setPlatform(Platform.WINDOWS);
driver = new RemoteWebDriver(new URL(nodeUrl), capabilities);
}
Now what I want is to run them at the same time, on 2 separate chrome browsers, how would I do it ? I am using testng.
You can use parameters in your testng.xml runner file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestSuite" thread-count="2" parallel="tests" >
<test name="ChromeTest">
<parameter name="browser" value="Chrome" />
<classes>
<class name="parallelTest.CrossBrowserScript"> </class>
</classes>
</test>
<test name="FirefoxTest">
<parameter name="browser" value="Firefox" />
<classes>
<class name="parallelTest.CrossBrowserScript"></class>
</classes>
</test>
</suite>
And in your #BeforeTest you can do something like bellow:
#BeforeTest
#Parameters("browser")
public void setup(String browser) throws Exception{
//Check if parameter passed from TestNG is 'firefox'
if(browser.equalsIgnoreCase("firefox")){
//create firefox instance
System.setProperty("webdriver.firefox.marionette", ".\\geckodriver.exe");
driver = new FirefoxDriver();
}
//Check if parameter passed as 'chrome'
else if(browser.equalsIgnoreCase("chrome")){
//set path to chromedriver.exe
System.setProperty("webdriver.chrome.driver",".\\chromedriver.exe");
//create chrome instance
driver = new ChromeDriver();
}
else{
//If no browser passed throw exception
throw new Exception("No Browser");
}
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
This question could help as well:
How to Launch browsers for each single testng XML file in selenium
BUT you need to use one xml file with multiple tests tags as above.
Related
I'm doing some tests using Java + TestNG, but I noticed that the tests are not executing the #AfterTest method. The browser remains open when the other tests are running (when it runs the first test, CreateNewUserWithValidData(), this one doesn't call the #AfterTest method, causing that the other tests fail). I need that every test call the #AfterTest method.
My testng.xml file has the following structure:
<suite name="Sample Tests" verbose="1" >
<listeners>
<listener class-name="Utilities.Listeners.TestListener"></listener>
<listener class-name="Utilities.Listeners.AnnotationTransformer"></listener>
</listeners>
<test name="Regression" >
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="CreateNewUserWithValidData" />
<include name="LoginWithAValidUser" />
<include name="LoginWithAnInvalidUser" />
</methods>
</class>
</classes>
</test>
</suite>
My BaseTest class looks like this.-
public class BaseTest {
protected String baseURL;
protected WebDriver driver;
protected WebDriverWait wait;
protected APAuthenticationPage apAuthenticationPage;
protected APCreateAccountPage apCreateAccountPage;
protected APHomePage apHomePage;
protected APMyAccountPage apMyAccountPage;
protected APShoppingCartAddressesPage apShoppingCartAddressesPage;
protected APShoppingCartOrderConfirmationPage apShoppingCartOrderConfirmationPage;
protected APShoppingCartOrderSummaryBankwirePage apShoppingCartOrderSummaryBankwirePage;
protected APShoppingCartPaymentMethodPage apShoppingCartPaymentMethodPage;
protected APShoppingCartShippingPage apShoppingCartShippingPage;
protected APShoppingCartSummaryPage apShoppingCartSummaryPage;
public WebDriver getDriver() {
return driver;
}
#BeforeTest(alwaysRun = true)
public void setUp() {
Log.info("I am in Before Method! Test is starting!");
driver = WebDriverFactory.getDriver(BrowserType.Chrome);
wait = new WebDriverWait(driver, 10);
driver.manage().window().maximize();
}
#BeforeMethod
public void initSetup() {
String propertiesFile = "data.properties";
PropertyReader propertyReader = new PropertyReader();
apAuthenticationPage = new APAuthenticationPage(driver);
apCreateAccountPage = new APCreateAccountPage(driver);
apHomePage = new APHomePage(driver);
apMyAccountPage = new APMyAccountPage(driver);
apShoppingCartAddressesPage = new APShoppingCartAddressesPage(driver);
apShoppingCartOrderConfirmationPage = new APShoppingCartOrderConfirmationPage(driver);
apShoppingCartOrderSummaryBankwirePage = new APShoppingCartOrderSummaryBankwirePage(driver);
apShoppingCartPaymentMethodPage = new APShoppingCartPaymentMethodPage(driver);
apShoppingCartShippingPage = new APShoppingCartShippingPage(driver);
apShoppingCartSummaryPage = new APShoppingCartSummaryPage(driver);
baseURL = propertyReader.getProperty(propertiesFile, "AUTOMATION_PRACTICE_URL");
}
#AfterTest(alwaysRun = true)
public void tearDown() {
Log.info("I am in After Method! Test is ending!");
driver.close();
driver.quit();
}
}
And my tests are the following ones.-
public class AutomationPracticesTests extends BaseTest {
// Properties
private String emailAddress, password;
// Tests
#Test(description = "It creates a new user in the store",
priority = 1)
public void CreateNewUserWithValidData(Method method) {
startTest(method.getName(), "It creates a new user in the store");
emailAddress = Mocks.personalData().get(0).getEmail();
password = Mocks.personalData().get(0).getPassword();
apHomePage.goTo(baseURL);
apHomePage.clickOnSignInButton();
apAuthenticationPage.fillCreateAccountForm(emailAddress);
apAuthenticationPage.clickOnCreateAccountButton();
apCreateAccountPage.fillRegisterForm(Mocks.personalData());
apCreateAccountPage.clickOnRegisterButton();
Assert.assertTrue(apMyAccountPage.isLoaded());
}
#Test(description = "It logins successfully in the store with a valid user",
priority = 2)
public void LoginWithAValidUser(Method method) {
apHomePage.goTo(baseURL);
apHomePage.clickOnSignInButton();
apAuthenticationPage.fillSignInForm(emailAddress, password);
apAuthenticationPage.clickOnSignInButton();
Assert.assertTrue(apMyAccountPage.isLoaded());
}
#Test(description = "It throws an error when the user attempts to login with an invalid user",
priority = 3)
public void LoginWithAnInvalidUser(Method method) {
apHomePage.goTo(baseURL);
apHomePage.clickOnSignInButton();
apAuthenticationPage.fillSignInForm(Mocks.invalidPersonalData().getEmail(), Mocks.invalidPersonalData().getPassword());
apAuthenticationPage.clickOnSignInButton();
Assert.assertEquals("Authentication failed.", apAuthenticationPage.IsErrorBannerDisplayed());
}
}
I'm suspecting that's something related to the testng.xml file (but, tbh, there are some things that I don't understand about how to configure correctly this file).
I'll appreciate any help to solve my problem. Thanks in advance!
It's not a bug. It work as expected.
BeforeTest
BeforeMethod
Method 1: CreateNewUserWithValidData
BeforeMethod
Method 2: LoginWithAValidUser
BeforeMethod
Method 3: LoginWithAnInvalidUser
AfterTest
If you want to close the browser before method 2, then you need to change AfterTest --> AfterMethod, and initialize browser in BeforeMethod
If you just want to change the testng.xml
<test name="test1">
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="CreateNewUserWithValidData"/>
</methods>
</class>
</classes>
</test>
<test name="test2">
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="LoginWithAValidUser"/>
</methods>
</class>
</classes>
</test>
<test name="test3">
<classes>
<class name="Tests.AutomationPracticesTests">
<methods>
<include name="LoginWithAnInvalidUser"/>
</methods>
</class>
</classes>
</test>
#BeforeClass I get null null errors I believe it's something with my before class.What about optional do you need them? FAILED CONFIGURATION: #BeforeClass setUp(null, null) I tried to add different maven dependiencies maybe its because of selenium version its still wont work.
public class Practice {
WebDriver driver;
//Check this ont out
#BeforeClass(alwaysRun = true)
#Parameters({ "browser", "url" })
public void setUp(#Optional("browser") String browser, #Optional("url") String url) {
BaseTest base = new BaseTest(browser, url);
driver = base.getDriver();
}
#Test
public void Check() {
try {
System.out.println("Passed Test case...");
Assert.assertTrue(driver.getTitle().contentEquals("Google"));
} catch (Exception ee) {
System.out.println("NOOOOO ");
ee.printStackTrace();
Assert.assertEquals("noooo " + ee, "iT SHOULD NOT fAIL");
}
}
public class Selen {
private WebDriver driver;
private String browser;
private String url;
public Selen(String browser, String url) {
this.browser = browser;
this.url = url;
if (browser.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.firefox.marionette",
"C:\\Users\\geckodriver.exe");
final FirefoxProfile firefox = new FirefoxProfile();
driver = new FirefoxDriver();
driver.get(url);
}
else if (browser.equalsIgnoreCase("chrome")) {
// set path to chromedriver.exe
System.setProperty("webdriver.chrome.driver", "C:\\Drivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--enable-automation", "test-type=browser", "--disable-plugins", "--disable-infobars",
"--disable-notifications", "start-maximized");
driver = new ChromeDriver(options);
driver.get(url);
}
else if (browser.equalsIgnoreCase("Edge")) {
// set path to Edge.exe
System.setProperty("webdriver.edge.driver", ".\\MicrosoftWebDriver.exe");
driver = new EdgeDriver();
driver.get(url);
} else {
}
}
public String getBrowser() {
return this.browser;
}
public String getBaseUrl() {
return this.url;
}
public WebDriver getDriver() {
return this.driver;
}
#AfterClass
public void tearDown(WebDriver driver) {
quitDriver(driver);
}
protected static void quitDriver(WebDriver driver) {
try {
if (driver != null) {
driver.quit();
}
} catch (Exception ee) {
System.out.println("Failed: " + ee);
;
}
}
**Failed Configuration**
[RemoteTestNG] detected TestNG version 6.14.3
Check() test case...
There was a problem:
java.lang.NullPointerException
at com.seleniumae.exercise.Practice.Check(Practice.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
TeNg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test thread-count="5" name="Test">
<parameter name="browser" value= "Chrome" />
<parameter name="url" value="https://www.google.com/"/>
<classes>
<class name="com.seleniumae.exercise.Practice"/>
<class name="com.seleniumae.exercise.Practice1"/>
<class name="com.seleniumae.exercise.Practice2.java"/>
</classes>
</test> <!-- Test -->
<test thread-count="5" name="Test">
<parameter name="browser" value ="Firefox" />
<parameter name="url" value="https://www.google.com/"/>
<classes>
<class name="com.seleniumae.exercise.Practice"/>
<class name="com.seleniumae.exercise.Practice1"/>
<class name="com.seleniumae.exercise.Practice2"/>
</classes>
</test> <!-- Test -->
<test thread-count="5" name="Test">
<parameter name="browser" value="InternetExplore" />
<parameter name="url" value="https://www.google.com/"/>
<classes>
<class name="com.seleniumae.exercise.Practice"/>
<class name="com.seleniumae.exercise.Practice1"/>
<class name="com.seleniumae.exercise.Practice2.java"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
The issue could be about parameters with browser taking one parameter like chrome when it should be another parameter.
Syntax to define #Optional annotation :
public void setUp(#Optional("browser_name") String browser, #Optional("site_name") String url)
And you are implementing in following way without using #Optional("value")
public void setUp(#Optional String browser, #Optional String url) throws MalformedURLException {
TestNG.xml - please write parameters like below
<suite name="Suite">
<test thread-count="5" name="Test">
<parameter name="url" value="https://www.google.com/"/>
<parameter name="browser" value= "Chrome" />
Note - TestNG provides you flexibility of declaring parameters as optional. When we declare a parameter as optional and If defined parameter is not found in your testng.xml file, The test method will receive the default value which is specified inside the #Optional annotation.
I have created 2 separate classes to test a webpage. But, unfortunately when I add them both to the testing.xml, only one of them execute and the other doesn't. The browsers open in parallel even after setting them to preserve-order="true" parallel="false" in the XML. I'm confused as to where I'm doing it wrong.
This is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" preserve-order="true" parallel="false">
<test name="Test">
<classes>
<class name="TestServiceNow.loginOne"/>
<class name="TestServiceNow.loginTwo"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
loginOne is as follows:
package TestServiceNow;
import org.testng.annotations.Test;
import ServiceNow.login;
public class loginOne extends loginTest{
#Test
public void test_Login(){
//Create Login Page object
objLogin = new login(driver);
//login to application
objLogin.loginGurukula("admin", "admin");
}
}
loginTwo is as follows:
import org.testng.annotations.Test;
import ServiceNow.login;
public class loginTwo extends loginTest{
#Test
public void test_Login_Fail(){
//Create Login Page object
objLogin = new login(driver);
//login to application
objLogin.loginGurukula("admin", "admin1");
}
}
The base class is as follows:
public class loginTest {
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
File file = new File("C:/Users/gattu_000/Documents/selenium-java-3.0.0-beta2/chromedriver_win32/chromedriver.exe");
WebDriver driver;
login objLogin;
#BeforeClass
public void a() {
driver = new ChromeDriver(capabilities);
capabilities.setCapability("marionette", true);
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
System.out.println("Before class called");
}
#BeforeTest
public void setup(){
System.out.println("Before test called");
driver.get("http://localhost:8080/#/login");
}
#AfterTest
public void close() {
System.out.println("After test called");
}
#AfterClass
public void b() {
System.out.println("After class called");
driver.close();
}
}
The results look like
After the Edit
You are extending loginTest by both loginOne and loginTwo. But in loginTest you initialized your driver. That's why two browser are opening. To get around this issue, you can initialize your driver inside a setup method like #BeforeTest or #BeforeSuite. As an example here's a code snippet -
#BeforeSuite
public void a() {
driver = new ChromeDriver(capabilities);
System.out.println("Before suite called");
}
Do other things as usual like before except the initialization part.
Edit
I missed something. You are closing your driver at the after test method. To run your tests properly remove the driver.close() from your after test method and place it to aftereSuite section.
The XML is supposed to be like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" preserve-order="true">
<test name="Test">
<classes>
<class name="TestServiceNow.loginOne"/>
</classes>
</test> <!-- Test -->
<test name="Test1">
<classes>
<class name="TestServiceNow.loginTwo"/>
</classes>
</test>
</suite> <!-- Suite -->
To launch the browser twice, we need to have 2 separate tests. (Possibly, this may be one of the solutions out of many)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Selenium Test Suite">
<test name="Selenium Test Suite">
<classes>
<class name="packagename.classname1"/>
<class name="packagename.classname1"/>
</classes>
</test>
</suite>
Which is proper. If you are getting null point don't use driver in all the class. because of that only you are getting null pointer i guess.
I want to run tests on different browsers, using junit, selenium, i have this code:
#Test //Test1
public void logInFaildTest() {
GridTest gridTest = new GridTest();
WebDriver webDriver = gridTest.getWebDriver();//get driver
LoginPage logIn = new LoginPage(webDriver, url);
String userName = "user";
String pass="pass";
......................................
webDriver.close();
}
#Test //Test2 change
public void logInFaildTest(WebDriver webDriver ) {
LoginPage logIn = new LoginPage(webDriver, url);
String userName = "user";
String pass="pass";
......................................
webDriver.close();
}
#Test //Test3
public void loginSucsecc(WebDriver webDriver )
{
WebDriver webDriver = gridTest.getWebDriver();
LoginPage logIn = new LoginPage(webDriver, url);
......................................
webDriver.quit();
assertEquals(expected, actual);
}
In test 1 i create an instance of webdriver inside the test method, in test 2 and 3 i want to get the test driver as parameter and execute the test with the specific webdriver, how can i run test case that can run each function with different web driver(one on firefox other on chrome...).
solution To send test function parameters, must set class as #RunWith(Parameterized.class).
Another solve is to read properties file in each test method, and run the test as the properties.
best way to do is , group the tests which you want to run specific browser.
Send browser parameter from testNg to run in specific browser.
Test Class:
#Parameters({ "browser" })
#Test(groups="IE")
public void logInFaildTest(String browser) {
GridTest gridTest = new GridTest();
WebDriver webDriver = gridTest.getWebDriver();//get driver
LoginPage logIn = new LoginPage(webDriver, url);
String userName = "user";
String pass="pass";
......................................
webDriver.close();
}
#Parameters({ "browser" })
#Test(groups="IE")
public void logInFaildTest(String browser ) {
LoginPage logIn = new LoginPage(webDriver, url);
String userName = "user";
String pass="pass";
......................................
webDriver.close();
}
#Parameters({ "browser" })
#Test(groups="Chrome")
public void loginSucsecc(String browser )
{
WebDriver webDriver = gridTest.getWebDriver();
LoginPage logIn = new LoginPage(webDriver, url);
......................................
webDriver.quit();
assertEquals(expected, actual);
}
TestNg:
<test name="Testing Parameterization">
<parameter name="browser" value="IE"/>
<parameter name="username" value="testuser"/>
<parameter name="password" value="testpassword"/>
<groups>
<run>
<include name="IE"/>
</run>
</groups>
<classes>
<class name="com.parameterization.TestParameters" />
</classes>
</test>
<test name="Testing Parameterization">
<parameter name="browser" value="Firefox"/>
<parameter name="username" value="testuser"/>
<parameter name="password" value="testpassword"/>
<groups>
<run>
<include name="chrome"/>
</run>
</groups>
<classes>
<class name="com.parameterization.TestParameters" />
</classes>
</test>
The code I am using is shown below.
MultiBrowser
package com;
import java.io.File;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class MultiBrowser {
public WebDriver driver;
// Passing Browser parameter from TestNG xml
#Parameters("browser")
#BeforeClass
public void beforeTest(String browser) {
// If the browser is Firefox, then do this
if(browser.equalsIgnoreCase("firefox")) {
driver = new FirefoxDriver();
}else if (browser.equalsIgnoreCase("ie")) {
DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
File fil = new File("C:\\IEDriver\\IEDriverServer.exe");
System.setProperty("webdriver.ie.driver", fil.getAbsolutePath());
driver = new InternetExplorerDriver(capabilities);
}
driver.get("http://www.store.demoqa.com");
}
#Test
public void login() throws InterruptedException{
driver.findElement(By.xpath(".//*[#id='account']/a")).click();
driver.findElement(By.id("log")).sendKeys("testuser_1");
driver.findElement(By.id("pwd")).sendKeys("Test#123");
driver.findElement(By.id("login")).click();
}
#AfterClass
public void afterTest(){
driver.quit();
}
}
TestNG.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="none">
<test name="FirefoxTest">
<parameter name="browser" value="firefox" />
<classes>
<class name="com.MultiBrowser" />
</classes>
</test>
<test name="IETest">
<parameter name="browser" value="ie" />
<classes>
<class name="com.MultiBrowser" />
</classes>
</test>
</suite>
It works fine when I use Firefox but I get the below issue when I run the same code on IE
Exception :
Unable to find element with xpath == .//*[#id='account']/a (WARNING: The server did not provide any stacktrace information)
It needs to set Security level in all zones. To do that follow the steps below:
1.Open IE
2.Go to Tools -> Internet Options -> Security
3.All check boxes in Security should be enabled.