Selenium coding - java

i am new to selenium and i have created a java project with different classes (each class for every page of my application). The project has only 1 main method and the class having main method is inherited by all other classes.
So, is it correct to code in this way that the class having main is inherited by all other classes?
Or is there some other better way to code?
Another question is,
The main method has the chrome driver initiation in it as well in addition to objects of all classes used to call the methods of different classes.
Should main contain only objects for all classes? or is there a way to initiate chrome in some other way.
Sample of my code below (main class and login class):
public class Main {
static WebDriver driver;
static Logger logger;
public static void main(String[] args) throws IOException {
logger=Logger.getLogger("Log4jdemo");
PropertyConfigurator.configure("Log4j.property.txt");
String exePath = "F:\\selenium\\Chrome Driver\\New Folder\\chromedriver.exe";
System.setProperty("webdriver.chrome.driver", exePath);
driver = new ChromeDriver();
driver.get("https://www.gmail.com");
driver.manage().window().maximize();
logger.info("Browser launched");
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.withTimeout(15, TimeUnit.SECONDS);
wait.pollingEvery(1, TimeUnit.SECONDS);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ei-login-Username")));
Login l1 = new Login();
l1.login();
A name= new A();
name.InitiateJourney();
B IO = new B();
IO.Help();
Agreeterms a = new Agreeterms();
a.Agreeterm();
AmendDetails ad = new AmendDetails();
ad.Amend();
AmendBank ab = new AmendBank();
ab.amendbankdetails();
}
}
public class Login extends Main{
public void login() throws IOException{
File src = new File("F:\\selenium\\AutomationData.xlsx");
FileInputStream fin = new FileInputStream(src);
XSSFWorkbook wbook = new XSSFWorkbook(fin);
XSSFSheet sheet = wbook.getSheetAt(0);
WebElement username =driver.findElement(By.id("ei-login-Username"));
username.sendKeys("12365478");
WebElement next =driver.findElement(By.id("btnSubmit"));
next.click();
driver.manage().timeouts().implicitlyWait(6, TimeUnit.SECONDS);
WebElement pin =driver.findElement(By.id("ei-login-Pin"));
pin.sendKeys("971997");
WebElement login =driver.findElement(By.id("btnPinSubmit"));
login.click();
}
}

Try TestNG or JUnit frameworks, Main method is not Mandatory for selenium. You can write your own classes and methods. Can call them by Annotations.

Related

how to make driver as thread safe to run methods of a class in parallel in selenium java

I have 3 test methods using driver from Base class. I tired to run these methods in parallel but getting failures. Reponse to my problem is appreciated. Thanks
Class having 3 test methods
public class TestCases extends BaseClass {
#Test
public void Test1() {
homePage.checkIfElementIsDisplayed(homePage.emailElement);
homePage.checkIfElementIsDisplayed(homePage.passwordElement);
homePage.checkIfElementIsDisplayed(homePage.signInElement);
homePage.emailElement.sendKeys("karteek#gmail.com");
homePage.passwordElement.sendKeys("******");
}
#Test
public void Test2() {
homePage.checkValuesInListGroup();
homePage.checkSecondListItem();
homePage.checkSecondListItemBadgeValue();
}
#Test
public void Test3() throws InterruptedException {
homePage.ScrolltotheElement(homePage.dropDownOption);
homePage.checkDefaultSelectedValue();
homePage.selectOption3();
}
}
Base Class
public class BaseClass {
public WebDriver driver;
public HomePage homePage;
public WebDriver setup() throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\resource\\GlobalData.Properties");
prop.load(fis);
String browserName = System.getProperty("browser") != null ? System.getProperty("browser")
: prop.getProperty("browser");
if (browserName.contains("chrome")) {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
}
else if (browserName.contains("edge")) {
WebDriverManager.edgedriver().setup();
driver = new EdgeDriver();
} else if (browserName.contains("firefox")) {
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
}
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().window().maximize();
return driver;
}
#BeforeMethod
public HomePage LaunchApplication() throws IOException {
driver = setup();
homePage = new HomePage(driver);
homePage.goTo();
return homePage;
}
#AfterMethod
public void tearDown() throws IOException {
driver.close();
}
I tried creating ThreadLocal Class for WebDriver as
ThreadLocal<WebDriver> threadSafeDriver=new ThreadLocal<WebDriver>();
and use this in setup() method of BaseClass by writing
threadSafeDriver.set(driver);
but this didnot really help
Most likely you are using the TestNG framework. One of the differences between JUnit and TestNG is that JUnit creates a new class instance for each test method by default but TestNG creates a single instance for all test methods in the class.
You can see the parallel option in TestNG suite (see docs) but there is no way to force TestNG to create a new instance for each test.
The simplest solution is to switch to JUnit framework. Then the code from the example should work.

Selenium PageObject throws Invocation Target Exception

I am trying to create a framework(Selenium+TestNg+java) for a Web app(The environment is MacOs+ChromeDriver and the driver server is in \usr\local\bin) but got stuck in basic structure. I have a class(Driversetup.java) that starts the browser, another one that contains WebElements and methods(ProfileUpdateObjects.java) and the third one containing test methods. Now, when I try to run this TestNG class having just a single method, I get following exception.
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:138).
Below is the code (All the classes are in different packages).
public class ProfileUpdateTest {
#Test(enabled = true, priority = 1)
public void profileUpdate() throws MalformedURLException, InterruptedException, ParseException {
WebDriver driver = DriverSetup.startBrowser("chrome");
ProfileUpdateObjects pu = PageFactory.initElements(driver, ProfileUpdateObjects.class);
pu.navigateProfile();
}
}
The code for ProfileUpdateObject class
public class ProfileUpdateObjects {
WebDriver driver;
public ProfileUpdateObjects(WebDriver cdriver) {
this.driver = cdriver;
}
#FindBy(xpath = " //div[#class='ico-menu']")
private WebElement menu;
#FindBy(xpath = "//a[#title='My Dashboard']")
private WebElement myDashboard;
#FindBy(xpath = " //a[contains(text(),'View Profile')]")
public WebElement profile;
#FindBy(xpath = "//li[contains(text(),'Permanent Address')]")
private WebElement permanentAddress;
#FindBy(xpath = "//li[contains(text(),'Banking Information')]")
private WebElement bankingInformation;
WebDriverWait waitfor = new WebDriverWait(driver, 2000);
public void navigateProfile() throws InterruptedException {
menu.click();
profile.click();
waitfor.until(ExpectedConditions.visibilityOf(permanentAddress));
}
}
DriverSetup.java
public class DriverSetup {
public static WebDriver driver;
public static WebDriver startBrowser(String browserName, String url) {
if (browserName.equalsIgnoreCase("chrome")) {
driver = new ChromeDriver();
}
driver.manage().window().maximize();
driver.get(url);
return driver;
}
}
It is failing in pu.navigateProfile() call. Also, is it true that #FindBy takes more memory compared to driver.find() syntax and besides POM are there any other design principles for Automation framework because most of the resources over Web are one or the other implementation of POM.
Simple solution is to move new WebDriverWait. It should not be instantiated as instance variable.
Instead of:
WebDriverWait waitfor = new WebDriverWait(driver, 2000);
public void navigateProfile() throws InterruptedException {
menu.click();
profile.click();
waitfor.until(ExpectedConditions.visibilityOf(permanentAddress));
}
Use:
public void navigateProfile() {
menu.click();
profile.click();
new WebDriverWait(driver, 2000).until(ExpectedConditions.visibilityOf(permanentAddress));
}
This will solve your issue (Already tested it)

Create TestNG.xml file dynamically and pass parameter

I have to execute test scripts using dynamic testng.xml file which means I have to create testng.xml file thru code and pass the parameters to the #Test methods pro grammatically.
For that I have created two Java files DynamicTestNG.java which should generate testng.xml file and run SampleClass.java where the #Test method has been written along with the parameters.
DynamicTestNG.java
public class DynamicTestNG {
public void runTestNGTest(Map<String,String> testngParams) {
//Create an instance on TestNG
TestNG myTestNG = new TestNG();
//Create an instance of XML Suite and assign a name for it.
XmlSuite mySuite = new XmlSuite();
mySuite.setName("MySuite");
//Create an instance of XmlTest and assign a name for it.
XmlTest myTest = new XmlTest(mySuite);
myTest.setName("MyTest");
//Add any parameters that you want to set to the Test.
myTest.setParameters(testngParams);
//Create a list which can contain the classes that you want to run.
List<XmlClass> myClasses = new ArrayList<XmlClass> ();
myClasses.add(new XmlClass("SampleClass"));
//Assign that to the XmlTest Object created earlier.
myTest.setXmlClasses(myClasses);
//Create a list of XmlTests and add the Xmltest you created earlier to it.
List<XmlTest> myTests = new ArrayList<XmlTest>();
myTests.add(myTest);
//add the list of tests to your Suite.
mySuite.setTests(myTests);
//Add the suite to the list of suites.
List<XmlSuite> mySuites = new ArrayList<XmlSuite>();
mySuites.add(mySuite);
//Set the list of Suites to the testNG object you created earlier.
myTestNG.setXmlSuites(mySuites);
TestListenerAdapter tla = new TestListenerAdapter();
myTestNG.addListener(tla);
//invoke run() - this will run your class.
myTestNG.run();
}
public static void main (String args[])
{
DynamicTestNG dt = new DynamicTestNG();
//This Map can hold your testng Parameters.
Map<String,String> testngParams = new HashMap<String,String> ();
testngParams.put("searchtext1", "testdata1");
testngParams.put("searchtext2", "testdata2");
dt.runTestNGTest(testngParams);
}
}
And SampleClass.java
public class SampleClass {
private WebDriver driver;
#BeforeTest
public void setUp()
{
System.setProperty("webdriver.chrome.driver","C:\\Users\\AK5040691\\Desktop\\IE driver\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.navigate().to("http://executeautomation.com/blog/custom-testng-library-for-appium/#more-1562");
}
//#Parameters({"searchText1","searchText2"})
//#Test
public void searchText(String text1, String text2)
{
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.className("search-field")).sendKeys(text1);
driver.findElement(By.className("search-field")).clear();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.findElement(By.className("search-field")).sendKeys(text2);
}
}
Its not running. Please let me know the mistake here.
You have to uncomment the #Test annotation in your SampleClass file. And if your SampleClass is in a package , then absolute package name + class name is to be specified in this statement.
myClasses.add(new XmlClass("com.some.package.SampleClass"));
Generally TestNG classes have a suffix or prefix labelled "Test" so that surefire plugin can include them in the execution flow, in case if you are using maven.
You can instead use the constructor with parameter of class object .
myClasses.add(new XmlClass(SampleClass.class));

how to pass parameter from #Test method in 1 class file to a annotated method in another class file(testNG)

I am using selenium webdriver with java + testng to test my application gui. i have 2 class files in my project (same package). 1 class file has all the #Test methods and the second class file has 1 method which is used to generate an excel file with Id's generated in the test method in the first class file. Basically my AUT generates a unique ID each time i run the test method, which i need to capture.
code looks like this -
Test Method in 1st class file
#Test (invocationCount = 1)
public void TestIncident() {
ProfilesIni profile = new ProfilesIni();
FirefoxProfile myprofile = profile.getProfile("selenium");
WebDriver driver=new FirefoxDriver(myprofile);
vDriver = driver;
driver.manage().window().maximize();
driver.get("URL");
driver.findElement(By.id("username-id")).click();
driver.findElement(By.id("username-id")).sendKeys("username");
driver.findElement(By.id("pwd-id")).click();
driver.findElement(By.id("pwd-id")).sendKeys("password");
driver.findElement(By.name("login")).click();
Thread.sleep(5000);
driver.findElement(By.id("reg_img_304316340")).click();
driver.findElement(By.xpath("//div[#class='PageBody pbChrome']"));
//new Actions(driver).moveToElement(driver.findElement(By.xpath("//div[#class='PageBody pbChrome']"))).perform();
driver.findElement(By.xpath("//span[contains(.,'Page1')]")).click();
driver.findElement(By.xpath("//span[contains(.,'New Page')]")).click();
driver.findElement(By.xpath("//div[#class='PageBody pbChrome']")).click();
uniqueID = driver.findElement(By.xpath("//div[#id='WIN_0_304248710']/descendant::dd[#class='HNavSelected arfid304247442 ardbnz3Btn_BCItem3']/descendant::a[#class='btn']")).getAttribute("innerHTML");
driver.findElement(By.id("arid_WIN_3_303530000")).clear();
driver.findElement(By.id("arid_WIN_3_303530000")).click();
}
In the 2nd class file in the same package, i am doing something like this -
#BeforeClass
public void createExcel() throws IOException
{
System.out.println("did this run");
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("IncidentNo");
//some code to save uniqueID in excel file
}
Now i cannot figure out a way to send uniqueID from the #Test method in the first class file to the method in the second class file which saves these uniqueID's to an excel sheet. any suggestions whats an effective way to achieve this ?
Call a method of the 2nd Class from your test class, passing the uniqueID as an argument.
Your code should look like this
ExcelUtils objExcelutils; //Object of your 2nd class
public class Test{
//all the code from your first class
objExcelutils.writeUniqueID(uniqueID);
}
// this is your 2nd class
int rowCount=1; //variable for the row count
public class Excelutils
{
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet worksheet = workbook.createSheet("IncidentNo");
public void writeUniqueID(String uniqueID)
{
HSSFRow row = worksheet.createRow(rowCount);
HSSFCell cell = row.createCell(rowCount);
cell.setCellValue(uniqueID);
rowCount++;
}
}
try (FileOutputStream outputStream = new FileOutputStream("JavaBooks.xlsx")) {
workbook.write(outputStream);
}
}

How to call a method from property file using Java and Selenium WebDriver?

Currently Working on Selenium WebDriver and code I'm writing in Java.
I have created a MasterScript called Master.java which is the main script and it looks like this:
package test;
import org.openqa.selenium.WebDriver;
public class MasterScript {
public static void main(String[] args) throws Exception {
//*****************************************************
// Calling Methods
//*****************************************************
LoginOneReports utilObj = new LoginOneReports ();
WebDriver driver;
driver=utilObj.setUp();
if(utilObj.Login()){
System.out.println("Login sucessfully completed");
} else {
System.out.println("Login failed");
System.exit(0);
}
NewPR utilObj1 = new NewPR(driver); // instead of calling one PR it need to pick from the property file and it need to select the KPI in UI
if(utilObj1.test()){
System.out.println("NewPR KPI page has opened");
} else {
System.out.println("NewPR KPI not able to open");
}
FilterSection utilObj2 =new FilterSection(driver);
utilObj2.FilterMatching();
}
}
Put this dynamic values in the property file where each and every time it need to go to the property file and fetch the value, based on the value the related java file need to called.
Hi Just for example we will call the property file as setup.txt
say for example you have a url in ur setup file as "internal.url=https://google.com"
create a constructor
public MasterScript() throws IO Exception
{
setup_details();
}
public void setup_details()throws IOException{
FileInputStream inStream;
inStream = new FileInputStream(new File("Setupfiles\\setup.txt"));
Properties prop = new Properties();
prop.load(inStream);
internal_url=prop.getProperty("internal.url");
}
IN THE SETUP FILE*
internal.url=https://google.com
name the txt file as setup.txt
Now while using that in the main class u can just use "driver.get(internal_url);"
Hope This helps you...

Categories

Resources