How to run multiple test classes in testng using page factory? - java

I have created two page classes to locate the elements for the two web pages (named LoginPage.java and AddEmployee.java)in one package. After that in another package i have created two test classes for the above two corresponding classes respectively(named VerifyloginpageTest.java and VerifyAddEmployeeTest.java) also i have created another class named BrowserFactory.java to initialize browser and create driver instance. Using the page factory I want to first run login page Test cases in their priority order and then after successfully logging into the website it should move on to the add employee web page.
**
BrowserFactory.java
**
package OrangeTestCases.Helper;
public class BrowserFactory {
public static WebDriver driver;
#BeforeClass
public static WebDriver startBrowser(String browsername,String url)
{
System.setProperty("webdriver.chrome.driver","C:\\Users\\int120\\Downloads\\EXE FILES\\chromedriver_win32\\chromedriver.exe");
driver=new ChromeDriver();
driver.manage().window().maximize();
driver.get(url);
return driver;
}
**
LoginPage.java
package OrangeTestCases.orangeHRM.Pages;
public class LoginPage{
// WebDriver driver;
#FindBy(id="txtUsername")
WebElement username;
#FindBy(how=How.ID,using="txtPassword")
WebElement password;
#FindBy(how=How.ID,using="btnLogin")
WebElement loginBtn;
#FindBy(how=How.XPATH,using="//*[#id=\"spanMessage\"]")
WebElement errormsg;
#FindBy(how=How.XPATH,using="//*[#id=\"menu_dashboard_index\"]/b")
WebElement dashboard;
//public LoginPage(WebDriver driver) {
//
// this.driver=driver;
// }
public void typeUsername(String u_name)
{
username.clear();
username.sendKeys(u_name);
}
public void typePassword(String pass)
{
password.clear();
password.sendKeys(pass);
}
public void clickLogin()
{
loginBtn.click();
}
public String findErrorMsg()
{
String actual_error=errormsg.getText();
return actual_error;
}
public boolean findDashBorad()
{
boolean dashboard_display=dashboard.isDisplayed();
return dashboard_display;
}
}
**
AddEmployee.java
package OrangeTestCases.orangeHRM.Pages;
public class AddEmployee {
#FindBy(how=How.XPATH,using="//*[#id=\"menu_pim_viewPimModule\"]/b")
WebElement pim;
#FindBy(how=How.XPATH,using="//*[#id=\"menu_pim_addEmployee\"]")
WebElement addemployee;
#FindBy(how=How.XPATH,using="//*[#id=\"firstName\"]")
WebElement f_name;
#FindBy(how=How.XPATH,using="//*[#id=\"middleName\"]")
WebElement m_name;
#FindBy(how=How.XPATH,using="//*[#id=\"lastName\"]")
WebElement l_name;
#FindBy(how=How.XPATH,using="//*[#id=\"photofile\"]")
WebElement photo;
#FindBy(how=How.XPATH,using="//*[#id=\"chkLogin\"]")
WebElement create_chkbox;
#FindBy(how=How.ID,using="user_name")
WebElement username;
#FindBy(how=How.XPATH,using="//*[#id=\"user_password\"]")
WebElement pswrd1;
#FindBy(how=How.ID,using="re_password")
WebElement confirm_emp_pswrd;
#FindBy(how=How.XPATH,using="//*[#id=\"status\"]")
WebElement status;
#FindBy(how=How.XPATH,using="//*[#id=\"btnSave\"]")
WebElement save;
// WebDriver driver;
//
//
// public AddEmployee(WebDriver driver)
// {
// this.driver=driver;
// }
public void clickPIM()
{
pim.click();
}
public void clickAddEmployee()
{
addemployee.click();
}
public void typefirstname(String fname)
{
f_name.sendKeys(fname);
}
public void typemiddlename(String mname)
{
m_name.sendKeys(mname);
}
public void typelastname(String lname)
{
l_name.sendKeys(lname);
}
public void uploadPhoto(String photo1)
{
photo.sendKeys(photo1);
}
public void clickCheckbox()
{
create_chkbox.click();
}
public void typeUsername(String u_name)
{
username.sendKeys(u_name);
}
public void typePassword(String pass)
{
pswrd1.sendKeys(pass);
}
public void confirmPassword(String con_pass)
{
confirm_emp_pswrd.sendKeys(con_pass);
}
public void selectStatus(String status_test)
{
Select status1=new Select(status);
status1.selectByVisibleText(status_test);
}
public void clickSavebtn()
{
save.click();
}
}
**
VerifyloginpageTest.java
package OrangeTestCases.orangeHRM.Testcases;
import OrangeTestCases.Helper.BrowserFactory;
import OrangeTestCases.orangeHRM.Pages.LoginPage;
public class VerifyloginpageTest{
String url="https://opensource-demo.orangehrmlive.com/";
WebDriver driver=BrowserFactory.startBrowser("chrome", url);
LoginPage login=PageFactory.initElements(driver, LoginPage.class);
VerifyAddEmployeeTest verify_addEmployee=new VerifyAddEmployeeTest();
//LoginPageObjects loginPage = PageFactory.initElements(driver, LoginPageObjects.class);
//To verify that error message occur when username is wrong
#Test(priority=1)
public void verify2() throws InterruptedException
{
//LoginPage login=new LoginPage(driver);
Thread.sleep(2000);
login.typeUsername("adm");
login.typePassword("admin123");
login.clickLogin();
String actualError=login.findErrorMsg();
String expectedError="Invalid credentials";
Assert.assertEquals(actualError,expectedError);
}
//To verify that error message occur when password is wrong
#Test(priority=2)
public void verify3() throws InterruptedException
{
// LoginPage login=new LoginPage(driver);
Thread.sleep(2000);
login.typeUsername("admin");
login.typePassword("adm");
login.clickLogin();
String actualError=login.findErrorMsg();
String expectedError="Invalid credentials";
Assert.assertEquals(actualError,expectedError);
}
//To verify that error message occur both username and password are wrong
#Test(priority=3)
public void verify4() throws InterruptedException
{
// LoginPage login=new LoginPage(driver);
Thread.sleep(2000);
login.typeUsername("adm");
login.typePassword("adm");
login.clickLogin();
String actualError=login.findErrorMsg();
String expectedError="Invalid credentials";
Assert.assertEquals(actualError,expectedError);
}
//To verify that error message occur both username and password are empty
#Test(priority=4)
public void verify5() throws InterruptedException
{
// LoginPage login=new LoginPage(driver);
Thread.sleep(2000);
login.typeUsername("");
login.typePassword("");
login.clickLogin();
String actualError=login.findErrorMsg();
String expectedError="Username cannot be empty";
Assert.assertEquals(actualError,expectedError);
}
//To verify that error message occur password is empty
#Test(priority=5)
public void verify6() throws InterruptedException
{
// LoginPage login=new LoginPage(driver);
Thread.sleep(2000);
login.typeUsername("admin");
login.typePassword("");
login.clickLogin();
String actualError=login.findErrorMsg();
String expectedError="Password cannot be empty";
Assert.assertEquals(actualError,expectedError);
}
//To verify login is successful
#Test(priority=6)
public void verifyloginpage() throws Exception {
//login=new LoginPage( driver);
Thread.sleep(5000);
login.typeUsername("Admin");
login.typePassword("admin123");
login.clickLogin();
boolean actual_adminText=login.findDashBorad();
Assert.assertTrue(actual_adminText);
}
#Test(priority=7)
public void add_Employee()
{
verify_addEmployee.webPage(driver);
}
}
**
VerifyAddEmployeeTest.java
**
package OrangeTestCases.orangeHRM.Testcases;
import OrangeTestCases.orangeHRM.Pages.AddEmployee;
public class VerifyAddEmployeeTest {
AddEmployee add_emp;
//String url="https://opensource-demo.orangehrmlive.com/";
//WebDriver driver=BrowserFactory.startBrowser("chrome", url);
// WebDriver driver=BrowserFactory.getDriver();
// LoginPage login=PageFactory.initElements(driver, LoginPage.class);
void webPage(WebDriver driver) {
add_emp=PageFactory.initElements(driver, AddEmployee.class);
}
// to fill the registration form
#Test
public void verifyAddEmployeepage() {
// login = new LoginPage(driver);
// login.typeUsername("Admin");
// login.typePassword("admin123");
// login.clickLogin();
try {
System.out.println("value to object of driver sent successfully");
add_emp.clickPIM();
add_emp.clickAddEmployee();
add_emp.typefirstname("kumar");
add_emp.typemiddlename("sanu");
add_emp.typelastname("Singh");
add_emp.uploadPhoto("C:\\Users\\int120\\Desktop\\nw\\head2.png");
add_emp.clickCheckbox();
add_emp.typeUsername("kumar.sanu");
add_emp.typePassword("kumar_singh123");
add_emp.confirmPassword("kumar_singh123");
add_emp.selectStatus("Enabled");
add_emp.clickSavebtn();
} catch (Exception e) {
e.printStackTrace();
}
}
}
So when I am running VerifyloginpageTest.java class it is successfully exexcuting all 6 login test cases and logging in the website but its not executing AddEmployee page.

According to TestNG documentation You should create testng.xml file if it is not there and after you should configure it as you want.
Example testng.xml file :
<suite name="TestExample">
<test name="Login">
<classes>
<class name="packageOfYourTest.VerifyloginpageTest" />
</classes>
</test>
<test name="AddEmployee">
<classes>
<class name="packageOfYourTests.AddEmployee" />
</classes>
</test>
</suite>
And Output will be like below :
testBeforeSuite()
testBeforeTest()
testLogin()
testAfterTest()
testBeforeTest()
testAddEmployee()
testAfterTest()

To make test classes run in parallel using TestNG, you should create testNG config xml file.
<suite name="SuiteName">
<test name="TestName">
<classes>
<class name="path.to.your.test.class.goes.here" />
</classes>
</test>
</suite>
Please note that using Before methods you actually create a thread and it's a good practice to create new instance of your driver for each thread.
Add parallel attribute to your config file on the 'suite' tag:
<suite name="SuiteName" parallel='classes'>
<test name="TestName">
<classes>
<class name="path.to.your.test.class.goes.here" />
</classes>
</test>
</suite>
You might parallel "methods", "tests" or "instances". But since you need run classes in parallel, use appropriate value.
Now, you can also add an attribute "thread-count" on the 'suite' tag as well to set max amount of classes which will run in parallel. In case you don't specify this attribute's value, amount will be equals 5 by default.
Now it's very important: whenever you call #Before TestNG creates new thread and you need to create driver for each thread and work with it within the exact thread. For doing this, you have to put every new driver instance into ThreadLocal<> container.
private static final ThreadLocal<WebDriver> DRIVER = new ThreadLocal<>();
public static WebDriver getDriver() {
return DRIVER.get();
}
#BeforeMethod
public void setUp() {
if (DRIVER.get() == null) {
DRIVER.set(new FirefoxDriver());
}
}
#AfterMethod
public void tearDown() {
if (DRIVER.get() != null) {
DRIVER.remove();
}
}
Thus you will make your driver thread-safe. Also note that if you start driver in #BeforeClass, you need to driver.qiut() in #AfterClass. If start in #BeforeSuite - driver.qiut() in #AfterSuite and so on. To make sure everything works fine, you can print into your log thread id whenever you create or kill driver.
More info here:
http://testng.org/doc/documentation-main.html#parallel-running
https://www.swtestacademy.com/selenium-parallel-tests-grid-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

Java + Selenium Session ID is null. Using WebDriver after calling quit()

I am having issues trying to run Selenium Web driver in a specific way, I've have setup TestNG + Selenium Web driver in my framework, the thing that I would like to accomplish is to run two suites that I've set up in the TestNG.xml files as bellow:
TestNG.xml
<suite>
<suite-files>
<suite-file path="src/testNG/suites/UserSignsOn.xml" />
<suite-file path="src/testNG/suites/PreSetup.xml" />
</suite-files>
</suite>
PreSetup.xml
<suite name="Pre Setup">
<test name="pre setup suite">
<classes>
<class name="Tests.PreSetup" />
</classes>
</test>
</suite>
UserSignsOn.xml
<suite name="User Signs On">
<test name="Get the Web Application">
<classes>
<class name="Tests.LoginPageTest" />
</classes>
</test>
</suite>
My test files look like this:
LoginPageTest.class
public class LoginPageTest extends BaseTest {
#Test
#Description("Login to the web application")
public void signInTheWebApplicationLocalHost(){ // some steps here }
}
PreSetup.class
public class PreSetup extends BaseTest {
#Test
#Description("Pre setup")
public void preSetupSteps(){ // some steps here }
}
As you can see my Test files extends a class, which is the following:
BaseTest.class
public class BaseTest {
protected EnvironmentManager environmentManager;
#BeforeTest
public void testSetup() {
environmentManager = EnvironmentManager.getInstance();
if(environmentManager.getDriver() == null){
// Here I am set up the driver!!!
environmentManager.initWebdriver();
environmentManager.startWebApplication();
}
}
#BeforeMethod
public void testName(ITestResult result){ // perform some actions }
#AfterMethod
public void status(ITestResult result){ // perform some actions }
#AfterTest // Here I am shutting down the driver
public void tearDown() { environmentManager.shutdownDriver(); }
}
The BaseTest.class calls to the EnvironmentManager.class which is a singleton class
It has the bellow code:
public class EnvironmentManager {
private static EnvironmentManager instance = null;
private WebDriver driver = null;
private String url = "www.google.com";
private EnvironmentManager(){}
// Public Methods
public void initWebdriver() {
if(driver == null){ driver = new ChromeDriver(); }
}
public void startWebApplication(){ driver.get(url); }
// Singleton method
public static EnvironmentManager getInstance() {
if (instance == null) instance = new EnvironmentManager();
return instance;
}
public void shutdownDriver(){
driver.quit();
driver = null;
}
public WebDriver getDriver(){ return driver; }
}
The issue resides after running the second test "PreSetup", in the console I got the error:
Session ID is null. Using WebDriver after calling quit()?
I notice that in the first test the driver session is:
ChromeDriver: chrome on MAC (0ff799fbfd14fc275b3b45c414765b15)
And in the second test is a different one:
ChromeDriver: chrome on MAC (09c6c47344756fe2979ee8a84094b1e3)
Any help is welcome :)
for all interested the solution is to rename the following testNG annotations:
#BeforeTest
#AfterTest
to
#BeforeSuite
#AfterSuite

TestNG Parameterisation: NullPointerException when passing browser type to Base class

I have a Base class with a method to open my URL that is called as #BeforeMethod in my test cases. The method takes a string argument for browser type which determines which browser is called. I am attempting to set a parameter in my xml launch file that can be inputted in my #BeforeMethod as argument for the openURL method.
Here is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="FullRegressionSuite" parallel="false">
<listeners>
<listener class-name="reporting.CustomReporter"></listener>
</listeners>
<test name="Test">
<parameter name ="browserType" value="Chrome"/>
<classes>
<class name="reporting.reporterTest"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Here are my tests:
#Listeners(CustomListener.class)
public class reporterTest extends Base {
#Test
public void testOne() {
Assert.assertTrue(true);
}
#Test
public void testTwo() {
Assert.assertTrue(false);
}
#Parameters({ "browserType" })
#BeforeMethod
public void setUp(String browserType) throws InterruptedException {
System.out.println(browserType);
openURL(browserType);
}
#AfterMethod
public void tearDown() {
driver.quit();
}
}
Here is my base class:
public class Base {
public static WebDriver driver = null;
//CALL WEB BROWSER AND OPEN WEBSITE
public static void openURL(String browser) throws InterruptedException {
//launches browser based on argument given
try{
if (browser == "Chrome") {
System.setProperty("webdriver.chrome.driver", "/Users/rossdonohoe/Desktop/SeleniumJava/Drivers/chromedriver");
driver = new ChromeDriver();
}
else if (browser == "Firefox") {
System.setProperty("webdriver.gecko.driver", "/Users/rossdonohoe/Desktop/SeleniumJava/Drivers/geckodriver");
driver = new FirefoxDriver();
}
else {
System.out.println("Error: browser request not recognized");
}
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
driver.get("https://www.google.com");
}
catch(Exception E) {
E.printStackTrace();
}
}
}
My #BeforeMethod is definitely receiving the parameter, as I'm printing its value to check and I'm getting "Chrome" in the console. However, openURL is failing at the 'delete all cookies' line with a null pointer exception (and my line "Error: browser request not recognized' is being printed in console), indicating that the string is not reaching openURL as an argument. Can anyone see what I'm doing wrong?
As the browser is a String variable , you need to use equals or contains or equalsIgnoreCase to check if the browser that you are fetching is "Chrome" or "Firefox".
So you need to use: if(browser.equals("Chrome")) and if(browser.equals("Firefox")) as the conditions instead of the conditions that you have used.

FAILED CONFIGURATION: Method beforeTest requires 1 parameters but 0 were supplied in the #Configuration annotation

I was trying to create a function for Browserloading, and called it from another class , but getting below error.
FAILED CONFIGURATION: #BeforeMethod beforeTest
org.testng.TestNGException:
Method beforeTest requires 1 parameters but 0 were supplied in the #Configuration annotation.
I also created testNG parameter in testNG xml file
Below is my function I created for Browser loading so that i can call it from another classes
import com.seleniumdata.zmartano.LoanDetails;
public class Browser {
public static WebDriver driver;
LoanDetails objLoan = new LoanDetails();
#BeforeMethod
#Parameters("Browser")
public void beforeTestUtility(String browser) throws Exception {
LoanDetails.beforeTest(browser);
}
#Test
public static void GetBrowser(String Browser)
{
if (Browser.equalsIgnoreCase("Firefox")) {
Log.info("Driver Initiated");
System.setProperty("webdriver.firefox.driver", Constants.geckodriver);
driver = new FirefoxDriver();
driver.get(Constants.URL);
Log.info("Application Opening");
driver.manage().window().maximize();
}
else if (Browser.equalsIgnoreCase("Chrome")) {
Log.info("Driver Initiated");
System.setProperty("webdriver.chrome.driver", Constants.chromedriver);
driver = new ChromeDriver();
driver.get(Constants.URL);
Log.info("Application Opening");
driver.manage().window().maximize();
}
}
}
My another class from where i need to call the browser function
public class LoanDetails {
public static WebDriver driver ;
public static void beforeTest(String browser) throws Exception {
Browser.GetBrowser(browser);
}
tesng xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="2">
<test name ="FirefoxTest">
<parameter name="Browser" value ="Firefox"/>
<classes>
<class name="com.seleniumdata.zmartano.LoanDetails"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
You are passing browser object to void beforeTest() method in LoanDetails class,
So you need to pass #Parameter annotation on #BeforeMethod annotation:
public class LoanDetails {
WebDriver driver ;
public void commonMethod(String browser) throws Exception {
driver = Browser.GetBrowser(browser);
}
}
Call separate class in to Test class,
public class Browser {
private static WebDriver driver;
LoanDetails objLoan = new LoanDetails();
#BeforeMethod
#Parameters("Browser")
public void beforeTestUtility(String browser) throws Exception {
objLoan.commonMethod(browser);
}
#Test
public static WebDriver GetBrowser(String Browser)
{
if (driver != null)
return driver;
else if (Browser.equalsIgnoreCase("Firefox")) {
Log.info("Driver Initiated");
System.setProperty("webdriver.firefox.driver", Constants.geckodriver);
driver = new FirefoxDriver();
driver.get(Constants.URL);
Log.info("Application Opening");
driver.manage().window().maximize();
return driver;
}
else if (Browser.equalsIgnoreCase("Chrome")) {
Log.info("Driver Initiated");
System.setProperty("webdriver.chrome.driver", Constants.chromedriver);
driver = new ChromeDriver();
driver.get(Constants.URL);
Log.info("Application Opening");
driver.manage().window().maximize();
return driver;
}
return driver;
}
}

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>

Categories

Resources