For the purpose of demo here i’ve used this site – http://automationpractice.com/index.php
I wanted to keep the framework light with two main aims:
- Ease of maintenance and debugging
- Ease of reporting
While Page object model was obvious choice for Point#1, i tried to implement ExtentReports for point#2. But due to some reason, it didn’t work out well for me. So let me put a disclaimer here; If you are here to learn about ExtentReport (keyword search landed you here), please hit back button on your browser window now.
For any test automation script, it is important we use proper logging in the reports. This will not only help locate the errors easily, but also helps in debugging of the script. So instead of wasting time in create eye-catching reports with all those pie-charts and colorful graphs, i decided to keep it simple. I just focused on the primary objective – log everything that you do on the browser.
Let me talk about POM first: Again, i have not used Page factory in my framework. So if you are here to learn PageFactory, please hit the back button.
- In the application, there is home page, Login page and Landup page (screen that you navigate once you login)
- I created a eCommerce Package and in that, i added one Java class each for each of the above screens
- I then created a Test eCommerce Package in which i created Java Class that will have my test cases.
- The 3rd package is Utility package – this will contain the functions that is used to do mundane tasks like excel file reading, that can be used in any of the above 2 packages
Data Driven framework: With the help of POM, i was able to create repository of objects in relevant classes that helped greatly in debugging, I now started thinking how to iterate my test cases for various sets of data. That’s when i went with traditional way of running the same Test cases for various input data saved in CSV files. TestNG provides the dataprovider annotation to do that. I just used APACHE poi Jar to read the data from Excel and iterate my @Test Methods.
That’s it. I’ve pasted the code snippet below. Before trying to understand the code, i strongly suggest you to check the demo site first. This helps you to understand the framework and the code better.
eCommWebsite Package
Home Page class
package testEcommerceWebsite;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import pomEcommerceWebsite.eCommPageObjects_HomePage;
import pomEcommerceWebsite.eCommPageObjects_LandupPage;
import pomEcommerceWebsite.eCommPageObjects_LoginPage;
import utilityPackage.utilityClass;
public class eCommTestClass {
//Create Objects of each screen Page object
eCommPageObjects_HomePage h;
eCommPageObjects_LoginPage lo;
eCommPageObjects_LandupPage la;
int testCaseNum=0;
String testCaseType;
WebDriver d;
@BeforeClass
public void setup(){
File file = new File("C:/Selenium/IEDriverServer.exe");
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
d = new InternetExplorerDriver();
d.get("http://automationpractice.com/index.php");
Reporter.log("Browser Opened");
h = new eCommPageObjects_HomePage(d);
lo = new eCommPageObjects_LoginPage(d);
la = new eCommPageObjects_LandupPage(d);
}
@Test(dataProvider = "dp")
public void TestCase1(String tcType, String userName, String password) {
testCaseType = tcType;
testCaseNum = testCaseNum+1;
//try{
d.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
h.clickOnSignIn();
lo.enterCredentials(userName, password);
la.signOut();
}
@AfterMethod
public void td(ITestResult result) {
if (result.getStatus() == ITestResult.FAILURE) {
System.out.println(result.getStatus());
TakesScreenshot ts = (TakesScreenshot)d;
File source = ts.getScreenshotAs(OutputType.FILE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
try {
FileUtils.copyFile(source, new File("C:\\Selenium\\Screesnhots\\TestCase# "+testCaseNum+"_"+timeStamp+".jpg"));
d.navigate().to("http://automationpractice.com/index.php");
Reporter.log("Test # " + testCaseNum + "has failed. Please check the screenshot C:\\Selenium\\Screesnhots\\TestCase# "+testCaseNum+".jpg");
} catch (IOException e) {
e.printStackTrace();
}
}
}
@DataProvider (name = "dp")
public String[][] dataExtractor() throws Exception{
utilityClass uc = new utilityClass();
String[][] signInCredentials = uc.excelDataReader("C:\\Selenium\\TestData\\eCommTest.xlsx");
return signInCredentials;
}
}
Login Page Class
package pomEcommerceWebsite;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Reporter;
public class eCommPageObjects_LoginPage {
WebElement emailAddress,password,loginButton;
WebDriver driver;
public eCommPageObjects_LoginPage(WebDriver d){
this.driver = d;
}
public void enterCredentials(String email, String passw){
String title = "Login - My Store";
if (title.equals(driver.getTitle())){
emailAddress = driver.findElement(By.id("email"));
password = driver.findElement(By.id("passwd"));
loginButton = driver.findElement(By.xpath("//button[@name = 'SubmitLogin'][@id = 'SubmitLogin']"));
emailAddress.sendKeys(email);
password.sendKeys(passw);
loginButton.click();
}else{
Reporter.log("Not in Login Page");
//org.testng.Assert.fail();
}
}
}
Landup Page Class
package pomEcommerceWebsite;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Reporter;
public class eCommPageObjects_LandupPage {
WebElement logOutButton;
WebDriver driver;
public eCommPageObjects_LandupPage(WebDriver d){
this.driver = d;
}
public void signOut(){
//check whether we are in right window
String title = driver.getTitle();
if (title.equals(driver.getTitle())){
//Click Logout button
logOutButton = driver.findElement(By.xpath("//a[@title = 'Log me out'][@class = 'logout']"));
driver.manage().timeouts().implicitlyWait(2,TimeUnit.SECONDS);
logOutButton.click();
//Go to Home Screen to accept next set of credentials
driver.navigate().to("http://automationpractice.com/index.php");
}else{
Reporter.log("Not in Landup Page");
//org.testng.Assert.fail();
}
}
}
eCommTest Package : Contains all Test case suite.
Test Class
package testEcommerceWebsite;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import pomEcommerceWebsite.eCommPageObjects_HomePage;
import pomEcommerceWebsite.eCommPageObjects_LandupPage;
import pomEcommerceWebsite.eCommPageObjects_LoginPage;
import utilityPackage.utilityClass;
public class eCommTestClass {
//Create Objects of each screen Page object
eCommPageObjects_HomePage h;
eCommPageObjects_LoginPage lo;
eCommPageObjects_LandupPage la;
int testCaseNum=0;
String testCaseType;
WebDriver d;
@BeforeClass
public void setup(){
File file = new File("C:/Selenium/IEDriverServer.exe");
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
d = new InternetExplorerDriver();
d.get("http://automationpractice.com/index.php");
Reporter.log("Browser Opened");
h = new eCommPageObjects_HomePage(d);
lo = new eCommPageObjects_LoginPage(d);
la = new eCommPageObjects_LandupPage(d);
}
@Test(dataProvider = "dp")
public void TestCase1(String tcType, String userName, String password) {
testCaseType = tcType;
testCaseNum = testCaseNum+1;
//try{
d.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
h.clickOnSignIn();
lo.enterCredentials(userName, password);
la.signOut();
}
@AfterMethod
public void td(ITestResult result) {
if (result.getStatus() == ITestResult.FAILURE) {
System.out.println(result.getStatus());
TakesScreenshot ts = (TakesScreenshot)d;
File source = ts.getScreenshotAs(OutputType.FILE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
try {
FileUtils.copyFile(source, new File("C:\\Selenium\\Screesnhots\\TestCase# "+testCaseNum+"_"+timeStamp+".jpg"));
d.navigate().to("http://automationpractice.com/index.php");
Reporter.log("Test # " + testCaseNum + "has failed. Please check the screenshot C:\\Selenium\\Screesnhots\\TestCase# "+testCaseNum+".jpg");
} catch (IOException e) {
e.printStackTrace();
}
}
}
@DataProvider (name = "dp")
public String[][] dataExtractor() throws Exception{
utilityClass uc = new utilityClass();
String[][] signInCredentials = uc.excelDataReader("C:\\Selenium\\TestData\\eCommTest.xlsx");
return signInCredentials;
}
}
Here i’m performing simple login test. The test case runs as many times as the number of rows of data is there in the input data sheet. I’m passing the user id and password from the data sheet.
You can see here that I’ve created a function in AfterTest to capture the screenshot. This will get invoked only if the test case fails due to some exception. The ITestresult of TestNG is used to check the Test case status.
Initially, i wanted to design the test case such that, if i pass the parameter as “Negative Test case” through the data sheet, the test case shouldn’t fail. In other words, if i pass invalid login credentials, i know the login will not be success. But that is the expected result for the test case and i wanted the test case to pass and not to throw “Element not found exception”. But there were some issues in getting the test case result passed forcefully. So i discarded that idea. If i really want to do that, i will create separate datasheet just for negative test and make sure that all the test cases fail .
Utility Package: Contains a class that holds functions to perform repetitive tasks
package utilityPackage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class utilityClass {
int testCaseNum;
//Method to read Excel Data
public String[][] excelDataReader (String fileLocation) throws IOException{
String[][] signInData = null;
//Create a object of File class to open xlsx file
File file = new File ("C:\\Selenium\\TestData\\eCommTest.xlsx");
//Create an object of FileInputStream class to read excel file
FileInputStream f = new FileInputStream(file);
//Create XLSX workbook object
Workbook signInTestData = new XSSFWorkbook(f);
//Get Sheet
String sheetName = new String("Sheet1");
Sheet testDataSheet = signInTestData.getSheet(sheetName);
//Get RowCount
int rowCount = testDataSheet.getLastRowNum();
System.out.println(testDataSheet.getLastRowNum());
//Declare row variable of type Row Class
Row row = testDataSheet.getRow(0);
//Get COlumn Count
int colCount = row.getLastCellNum();
System.out.println(colCount);
//Declare and intialize the String object, that will store excel data
signInData = new String[rowCount][colCount];
System.out.println(testDataSheet.getRow(0).getCell(1).getStringCellValue());
//Read the excel and store the value in array
//Starting reading from 2nd row, as first row is header
for (int r = 1; r<=rowCount; r++){
row = testDataSheet.getRow(r);
testCaseNum = r;
for(int c = 0;c<row.getLastCellNum();c++){
signInData [r-1][c] = row.getCell(c).getStringCellValue();
}
}
signInTestData.close();
return signInData;
}
}
In the next post, i will talk about what are the issues or challenges i faced in this POM framework.