├── src ├── test │ ├── resources │ │ ├── testdata.xlsx │ │ └── login.json │ └── java │ │ └── com │ │ └── qed42 │ │ └── qa │ │ ├── tests │ │ ├── LoginExampleTest.java │ │ ├── BaseTest.java │ │ ├── JsonExampleTest.java │ │ └── ExcelExampleTest.java │ │ └── pageobjects │ │ └── LoginExamplePage.java └── main │ ├── resources │ └── log4j2.properties │ └── java │ └── com │ └── qed42 │ └── qa │ ├── configurations │ └── Configuration.java │ ├── utilities │ ├── PropertiesFileReader.java │ ├── JsonFileReader.java │ ├── TestListener.java │ └── ExcelManager.java │ ├── reportmanager │ ├── ExtentManager.java │ └── Report.java │ └── driver │ └── DriverManager.java ├── config.properties ├── testng.xml ├── .gitignore ├── README.md └── pom.xml /src/test/resources/testdata.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qed42/headway/HEAD/src/test/resources/testdata.xlsx -------------------------------------------------------------------------------- /config.properties: -------------------------------------------------------------------------------- 1 | baseUrl = http://demo.guru99.com/test/newtours/login.php 2 | browser = chrome 3 | 4 | platformName = mac 5 | reportPath = ./reports/Report_ 6 | -------------------------------------------------------------------------------- /src/test/resources/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "users": [ 3 | { 4 | "username": "selenium@qa", 5 | "password": "qa@12345" 6 | }, 7 | { 8 | "username": "selenium", 9 | "password": "qa@123" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /src/main/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | status = error 2 | name = PropertiesConfig 3 | 4 | # appenders = console, file 5 | appenders = file 6 | 7 | # Appender for writing to console 8 | appender.console.type = Console 9 | appender.console.name = STDOUT 10 | appender.console.layout.type = PatternLayout 11 | appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 12 | 13 | # Appender for writing to a file 14 | appender.file.type = File 15 | appender.file.name = FileLogger 16 | appender.file.filename = reports/logfile.log 17 | appender.file.layout.type = PatternLayout 18 | appender.file.layout.pattern = %d [%t] %-5p %c - %m%n 19 | 20 | # Root logger option 21 | rootLogger.level = debug 22 | #rootLogger.appenderRefs = stdout, file 23 | rootLogger.appenderRefs = file 24 | #rootLogger.appenderRef.stdout.ref = STDOUT 25 | rootLogger.appenderRef.file.ref = FileLogger 26 | -------------------------------------------------------------------------------- /testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/configurations/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.configurations; 2 | 3 | import java.util.Properties; 4 | import com.qed42.qa.utilities.PropertiesFileReader; 5 | 6 | /** 7 | * Configuration is an interface that stores application related specific keys 8 | * which can be used as constant for configuration of the application 9 | * 10 | * @author QED42 11 | * 12 | */ 13 | public interface Configuration { 14 | 15 | public static final String PROJECT_DIR = System.getProperty("user.dir"); 16 | public static final Properties config = PropertiesFileReader.read(PROJECT_DIR + "/config.properties"); 17 | 18 | public static final String BASE_URL = config.getProperty("baseUrl"); 19 | public static final String BROWSER_NAME = config.getProperty("browser"); 20 | public static final String PLATFORM_NAME = config.getProperty("platformName"); 21 | 22 | public static final String MAIN_RESOURCE_PATH = PROJECT_DIR + "/src/main/resources/"; 23 | public static final String TEST_RESOURCE_PATH = PROJECT_DIR + "/src/test/resources/"; 24 | 25 | public static final String REPORT_PATH = config.getProperty("reportPath"); 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | test-output/ 3 | reports/ 4 | screenshots/ 5 | .idea/ 6 | .DS_Store 7 | 8 | # Package Files # 9 | *.jar 10 | *.war 11 | *.nar 12 | *.ear 13 | *.zip 14 | *.tar.gz 15 | *.rar 16 | 17 | ### Java ### 18 | # Compiled class file 19 | *.class 20 | .classpath 21 | 22 | # Log file 23 | *.log 24 | 25 | ### Eclipse ### 26 | .metadata 27 | bin/ 28 | tmp/ 29 | *.tmp 30 | *.bak 31 | *.swp 32 | *~.nib 33 | local.properties 34 | .settings/ 35 | .loadpath 36 | .recommenders 37 | 38 | # Code Recommenders 39 | .recommenders/ 40 | 41 | # Annotation Processing 42 | .apt_generated/ 43 | 44 | # Scala IDE specific (Scala & Java development for Eclipse) 45 | .cache-main 46 | .scala_dependencies 47 | .worksheet 48 | 49 | ### Eclipse Patch ### 50 | # Eclipse Core 51 | .project 52 | 53 | # JDT-specific (Eclipse Java Development Tools) 54 | .classpath 55 | 56 | # Annotation Processing 57 | .apt_generated 58 | 59 | .sts4-cache/ 60 | 61 | ### Maven ### 62 | pom.xml.tag 63 | pom.xml.releaseBackup 64 | pom.xml.versionsBackup 65 | pom.xml.next 66 | release.properties 67 | dependency-reduced-pom.xml 68 | buildNumber.properties 69 | .mvn/timing.properties 70 | .mvn/wrapper/maven-wrapper.jar 71 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/utilities/PropertiesFileReader.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.utilities; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.util.Properties; 7 | 8 | /** 9 | * PropertiesFileReader class reads properties files and returns instance of "Properties" class. 10 | * It provides one method - read(fileName), which take filepath as the parameter. 11 | * 12 | * @author QED42 13 | * 14 | */ 15 | public class PropertiesFileReader { 16 | public static Properties properties; 17 | 18 | /** 19 | * Reads properties file and returns instance of Properties class 20 | * 21 | * @param fileName 22 | * @return 23 | */ 24 | public static Properties read(String fileName) { 25 | try { 26 | properties = new Properties(); 27 | FileInputStream ip = new FileInputStream(fileName); 28 | properties.load(ip); 29 | } catch (FileNotFoundException e) { 30 | // TODO Auto-generated catch block 31 | e.printStackTrace(); 32 | System.out.println("File not found"); 33 | } catch (IOException e) { 34 | System.out.println("IO Exception"); 35 | } 36 | return properties; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/qed42/qa/tests/LoginExampleTest.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.tests; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Listeners; 5 | import org.testng.annotations.Test; 6 | import com.aventstack.extentreports.Status; 7 | import com.qed42.qa.driver.DriverManager; 8 | import com.qed42.qa.pageobjects.LoginExamplePage; 9 | import com.qed42.qa.reportmanager.Report; 10 | 11 | @Listeners(com.qed42.qa.utilities.TestListener.class) 12 | 13 | public class LoginExampleTest extends BaseTest { 14 | 15 | @Test 16 | public void testLoginValidInput() throws Exception { 17 | LoginExamplePage obj1 = new LoginExamplePage(DriverManager.getDriver()); 18 | obj1.login("selenium@qa","qa@12345"); 19 | Report.log(Status.PASS, "Login is successful"); 20 | Assert.assertEquals(obj1.getPageCurrentUrl(), "https://demo.guru99.com/test/newtours/login_sucess.php"); 21 | } 22 | 23 | @Test 24 | public void testLoginInvalidInput() throws Exception { 25 | LoginExamplePage obj2 = new LoginExamplePage(DriverManager.getDriver()); 26 | obj2.login("selenium", "qa@123"); 27 | Report.log(Status.FAIL, "Login unsuccessful"); 28 | Assert.assertEquals(obj2.getPageCurrentUrl(), "https://demo.guru99.com/test/newtours/login_sucess.php"); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/qed42/qa/tests/BaseTest.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.tests; 2 | 3 | import org.testng.annotations.AfterClass; 4 | import org.testng.annotations.AfterMethod; 5 | import org.testng.annotations.BeforeMethod; 6 | import org.testng.annotations.Listeners; 7 | import org.testng.annotations.Optional; 8 | import org.testng.annotations.Parameters; 9 | 10 | import com.qed42.qa.driver.DriverManager; 11 | 12 | @Listeners(com.qed42.qa.utilities.TestListener.class) 13 | 14 | public class BaseTest { 15 | 16 | /** 17 | * This method initializes the driver and launches browser. It maximizes the browser window. 18 | * It is called before each test. 19 | * 20 | * @param browser 21 | */ 22 | @Parameters({ "browser" }) 23 | @BeforeMethod 24 | public void init(@Optional("chrome") String browser) { 25 | DriverManager.initialize(browser); 26 | } 27 | 28 | /** 29 | * quit() method is called after every test. It closes the browser 30 | * 31 | */ 32 | @AfterMethod 33 | public void quit() { 34 | DriverManager.quit(); 35 | 36 | } 37 | 38 | /** 39 | * terminate() method is called after every class. It removes the ThreadLocal driver. 40 | */ 41 | @AfterClass 42 | public void tearDown() { 43 | DriverManager.terminate(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/qed42/qa/pageobjects/LoginExamplePage.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.pageobjects; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | import com.aventstack.extentreports.Status; 6 | import com.qed42.qa.configurations.Configuration; 7 | import com.qed42.qa.reportmanager.Report; 8 | 9 | public class LoginExamplePage { 10 | 11 | WebDriver driver; 12 | 13 | public By txtUserName = By.name("userName"); 14 | public By txtPassword = By.name("password"); 15 | public By btnSubmit = By.name("submit"); 16 | 17 | public LoginExamplePage(WebDriver driver) { 18 | this.driver = driver; 19 | } 20 | 21 | /** 22 | * Login with valid credentials 23 | * 24 | * @param userName 25 | * @param password 26 | * @throws Exception 27 | */ 28 | public void login(String userName, String password) throws Exception { 29 | driver.get(Configuration.BASE_URL); 30 | Report.log(Status.PASS, "Navigated to the login page"); 31 | driver.findElement(txtUserName).sendKeys(userName); 32 | driver.findElement(txtPassword).sendKeys(password); 33 | driver.findElement(btnSubmit).click(); 34 | } 35 | 36 | /** 37 | * 38 | * @return 39 | * @throws Exception 40 | */ 41 | public String getPageCurrentUrl() throws Exception { 42 | return driver.getCurrentUrl(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/utilities/JsonFileReader.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.utilities; 2 | 3 | import java.io.FileReader; 4 | import org.json.simple.JSONArray; 5 | import org.json.simple.JSONObject; 6 | import org.json.simple.parser.JSONParser; 7 | 8 | /** 9 | * JSONFileReader class reads a JSON file 10 | * 11 | * @author QED42 12 | * 13 | */ 14 | public class JsonFileReader { 15 | 16 | /** 17 | * Reads JSON file and returns JSONArray 18 | * 19 | * @param fileName 20 | * @return JSONObject 21 | * @throws Exception 22 | */ 23 | 24 | public JSONObject readJson(String filename) throws Exception { 25 | JSONParser jsonParser = new JSONParser(); 26 | FileReader filereader = new FileReader((filename)); 27 | 28 | JSONObject obj = (JSONObject) jsonParser.parse(filereader); 29 | return obj; 30 | } 31 | 32 | /** 33 | * Reads JSON file and returns JSONArray with specific sets of JSON key 34 | * 35 | * @param filename 36 | * @param JSONkey 37 | * @return 38 | * @throws Exception 39 | */ 40 | public JSONArray readJson(String filename, String JSONkey) throws Exception { 41 | JSONParser jsonParser = new JSONParser(); 42 | FileReader filereader = new FileReader((filename)); 43 | 44 | JSONObject obj = (JSONObject) jsonParser.parse(filereader); 45 | JSONArray arr = (JSONArray) obj.get(JSONkey); 46 | return arr; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/qed42/qa/tests/JsonExampleTest.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.tests; 2 | 3 | import org.testng.annotations.Test; 4 | import org.json.simple.JSONArray; 5 | import org.json.simple.JSONObject; 6 | import org.testng.Assert; 7 | import org.testng.annotations.DataProvider; 8 | import org.testng.annotations.Listeners; 9 | import com.aventstack.extentreports.Status; 10 | import com.qed42.qa.configurations.Configuration; 11 | import com.qed42.qa.driver.DriverManager; 12 | import com.qed42.qa.pageobjects.LoginExamplePage; 13 | import com.qed42.qa.reportmanager.Report; 14 | import com.qed42.qa.utilities.JsonFileReader; 15 | 16 | @Listeners(com.qed42.qa.utilities.TestListener.class) 17 | 18 | public class JsonExampleTest extends BaseTest { 19 | 20 | @Test(dataProvider = "userData") 21 | public void testJsonLogin(String username, String password) throws Exception { 22 | LoginExamplePage obj = new LoginExamplePage(DriverManager.getDriver()); 23 | 24 | obj.login(username, password); 25 | Assert.assertEquals(obj.getPageCurrentUrl(), "https://demo.guru99.com/test/newtours/login_sucess.php"); 26 | Report.log(Status.PASS, "Login Successful"); 27 | } 28 | 29 | @DataProvider 30 | public Object[][] userData() throws Exception { 31 | JsonFileReader jsonReader = new JsonFileReader(); 32 | JSONArray usersList = jsonReader.readJson(Configuration.TEST_RESOURCE_PATH + "/login.json", "users"); 33 | Object[][] dataObj = new Object[usersList.size()][2]; 34 | 35 | for (int i = 0; i < dataObj.length; i++) { 36 | JSONObject user = (JSONObject) usersList.get(i); 37 | dataObj[i][0] = user.get("username"); 38 | dataObj[i][1] = user.get("password"); 39 | } 40 | return dataObj; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/reportmanager/ExtentManager.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.reportmanager; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | import com.aventstack.extentreports.ExtentReports; 7 | import com.aventstack.extentreports.reporter.ExtentSparkReporter; 8 | import com.aventstack.extentreports.reporter.configuration.ExtentSparkReporterConfig; 9 | import com.aventstack.extentreports.reporter.configuration.Theme; 10 | import com.qed42.qa.configurations.Configuration; 11 | 12 | /** 13 | * ExtentManager class implements Configuration interface. 14 | * In this class, we create an ExtentReports object which can be reachable via getExtentReports() method. 15 | * Also, we set ExtentReports report HTML file location. 16 | * 17 | */ 18 | public class ExtentManager implements Configuration { 19 | 20 | private static ExtentReports extentreport; 21 | 22 | /** 23 | * getExtentReports() is a static method that creates and configures ExtenetReports object. 24 | * This method sets the theme of the report to STANDARD and title to "Test Report". 25 | * 26 | * @return 27 | */ 28 | public synchronized static ExtentReports getExtentReports() { 29 | if (extentreport == null) { 30 | // String date = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date()); 31 | String date = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss").format(new Date()); 32 | ExtentSparkReporter htmlreporter = new ExtentSparkReporter(REPORT_PATH + date); 33 | extentreport = new ExtentReports(); 34 | extentreport.attachReporter(htmlreporter); 35 | htmlreporter.config( 36 | ExtentSparkReporterConfig.builder().theme(Theme.STANDARD).documentTitle("Test Report").build()); 37 | } 38 | return extentreport; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/qed42/qa/tests/ExcelExampleTest.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.tests; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.DataProvider; 5 | import org.testng.annotations.Listeners; 6 | import org.testng.annotations.Test; 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import com.aventstack.extentreports.Status; 11 | import com.codoid.products.exception.FilloException; 12 | import com.qed42.qa.configurations.Configuration; 13 | import com.qed42.qa.driver.DriverManager; 14 | import com.qed42.qa.pageobjects.LoginExamplePage; 15 | import com.qed42.qa.reportmanager.Report; 16 | import com.qed42.qa.utilities.ExcelManager; 17 | 18 | @Listeners(com.qed42.qa.utilities.TestListener.class) 19 | 20 | public class ExcelExampleTest extends BaseTest { 21 | ArrayList loginCreds = new ArrayList(); 22 | 23 | @Test(dataProvider = "userData") 24 | public void testExcelLogin(String username, String password) throws Exception { 25 | LoginExamplePage obj = new LoginExamplePage(DriverManager.getDriver()); 26 | obj.login(username, password); 27 | Assert.assertEquals(obj.getPageCurrentUrl(), "https://demo.guru99.com/test/newtours/login_sucess.php"); 28 | Report.log(Status.PASS, "Login successful"); 29 | } 30 | 31 | @DataProvider 32 | public Object[][] userData() throws FilloException { 33 | ExcelManager fillo = new ExcelManager(); 34 | List> users = fillo.getAllData(Configuration.TEST_RESOURCE_PATH, "testdata.xlsx", "TestData"); 35 | Object[][] dataObj = new Object[users.size()][2]; 36 | 37 | for (int i = 0; i < users.size(); i++) { 38 | dataObj[i][0] = users.get(i).get("Username"); 39 | dataObj[i][1] = users.get(i).get("Password"); 40 | } 41 | return dataObj; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Headway - Selenium Data Driven Framework 2 | 3 | Headway is a data-driven testing framework that uses Selenium to automate web-based applications. It is designed to simplify the process of creating and executing automated tests by separating test data from test logic. 4 | 5 | ******************************************************************************** 6 | 7 | ## Features 8 | 9 | 1. Data-driven approach: Test data is stored separately from the test scripts, allowing for easy modification and reuse of test cases. 10 | 2. Modularity: The framework is built using a modular approach, making it easy to add or remove functionality as needed. 11 | 3. Reporting: The framework generates detailed test reports in HTML format, making it easy to track test results and identify issues. 12 | 4. Cross-browser compatibility: The framework supports testing on multiple browsers, including Chrome, Firefox, and Safari. 13 | 5. Parallel testing: The framework supports parallel execution of test cases, reducing the overall test execution time 14 | 15 | ## Requirements 16 | 17 | 1. Java 8 or higher 18 | 2. Maven 3.x 19 | 3. Selenium WebDriver 20 | 4. TestNG 21 | 5. Eclipse 22 | 23 | 24 | ## Installations 25 | 26 | 1. Clone this repository to your local machine. 27 | 2. Install the required dependencies by running mvn clean install in the root directory
28 | OR
29 | Import project as an existing Maven project in Eclipse, File > Import > Maven > Existing Maven Projects > Next >
30 | a. Browse to headway
31 | b. Ensure pom.xml is found
32 | c. Finish. 33 | 3. Update the config.properties file to configure the test settings such as the browser type and test URL. 34 | 4. Write your test cases in the src/test/java directory using TestNG annotation and POM design pattern. 35 | 36 | 37 | ## Contribution 38 | 39 | Contributions are welcome! Please feel free to open a pull request or submit an issue if you find any bugs or have any suggestions for improvement. 40 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/reportmanager/Report.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.reportmanager; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import com.aventstack.extentreports.ExtentReports; 6 | import com.aventstack.extentreports.ExtentTest; 7 | import com.aventstack.extentreports.Status; 8 | 9 | /** 10 | * extentTestMap holds the information of thread ids and ExtentTest instances. 11 | * ExtentReports instance created by calling getExtentReports() method from ExtentManager. 12 | * At startTest() method, an instance of ExtentTest is created and put into extentTestMap with current thread id. 13 | * At getTest() method, return ExtentTest instance in extentTestMap by using current thread id. 14 | * 15 | */ 16 | public class Report { 17 | static Map extentTestMap = new HashMap<>(); 18 | private static ExtentReports extent = ExtentManager.getExtentReports(); 19 | static ExtentTest test; 20 | 21 | public static synchronized ExtentTest getTest() { 22 | return extentTestMap.get((int) (long) (Thread.currentThread().getId())); 23 | } 24 | 25 | public static synchronized ExtentTest startTest(String testName) { 26 | return startTest(testName, ""); 27 | } 28 | 29 | public static synchronized ExtentTest startTest(String testName, String desc) { 30 | test = extent.createTest(testName, desc); 31 | extentTestMap.put((int) (long) (Thread.currentThread().getId()), test); 32 | return test; 33 | } 34 | 35 | public static synchronized void endTest() { 36 | extent.flush(); 37 | } 38 | 39 | public static synchronized void log(Status status, String desc, String methodName) { 40 | System.out.println(methodName + " : " + desc); 41 | Report.getTest().log(status, desc); 42 | } 43 | 44 | public static synchronized void log(Status status, String desc) { 45 | System.out.println("Thread Id : " + Thread.currentThread().getId() + " " + desc); 46 | Report.getTest().log(status, desc); 47 | } 48 | 49 | public static synchronized void log(Status status, Exception e) { 50 | Report.getTest().log(status, e); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/utilities/TestListener.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.utilities; 2 | 3 | import java.io.File; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import org.apache.commons.io.FileUtils; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | import org.testng.ITestContext; 10 | import org.testng.ITestListener; 11 | import org.testng.ITestResult; 12 | import com.aventstack.extentreports.Status; 13 | import com.qed42.qa.driver.DriverManager; 14 | import com.qed42.qa.reportmanager.Report; 15 | import org.openqa.selenium.OutputType; 16 | import org.openqa.selenium.TakesScreenshot; 17 | 18 | /** 19 | * TestListener class implements ITestListener interface. 20 | * We have added Extent Reports codes in each method. 21 | * This class is used to generate logs or customize the TestNG reports. 22 | * 23 | */ 24 | public class TestListener implements ITestListener { 25 | 26 | static Logger log = LogManager.getLogger(Report.class); 27 | 28 | public void onTestStart(ITestResult result) { 29 | System.out.println("\n" + " ***** Test Executing : " + result.getName()); 30 | log.info(" ***** Test Executing : " + result.getName()); 31 | Report.startTest(result.getMethod().getMethodName(), result.getMethod().getDescription()); 32 | } 33 | 34 | public void onTestSuccess(ITestResult result) { 35 | log.info("Test Passed : " + result.getName()); 36 | Report.log(Status.PASS, " Test Passed", result.getName()); 37 | } 38 | 39 | public void onTestFailure(ITestResult result) { 40 | log.info("Test Failed : " + result.getName()); 41 | try { 42 | 43 | // String date = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date()); 44 | String date = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss").format(new Date()); 45 | 46 | //Object currentInstance = result.getInstance(); 47 | TakesScreenshot ts = (TakesScreenshot) (DriverManager.getDriver()); 48 | 49 | File source = ts.getScreenshotAs(OutputType.FILE); 50 | String destination = System.getProperty("user.dir") + "/screenshots/" + result.getName() + "_" + date + ".png"; 51 | File finalDestination = new File(destination); 52 | 53 | FileUtils.copyFile(source, finalDestination); 54 | 55 | Report.log(Status.FAIL, " Test Failed " + result.getThrowable(), result.getName()); 56 | Report.getTest().addScreenCaptureFromPath(destination); 57 | } catch (Exception e) { 58 | // TODO Auto-generated catch block 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | public void onTestSkipped(ITestResult result) { 64 | log.info("Test Skipped : " + result.getName()); 65 | Report.log(Status.SKIP, " Test Skipped " + result.getThrowable(), result.getName()); 66 | } 67 | 68 | public void onTestFailedButWithinSuccessPercentage(ITestResult result) { 69 | // System.out.println("Test Failed but within success percentage : " + 70 | // result.getName()); 71 | } 72 | 73 | public void onStart(ITestContext context) { 74 | System.out.println("\n" + "---------------- TEST EXECUTION STARTED ---------------- "); 75 | } 76 | 77 | public void onFinish(ITestContext context) { 78 | Report.endTest(); 79 | System.out.println("\n" + "---------------- TEST EXECUTION FINISHED ---------------- "); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | com.qed42 7 | headway 8 | 0.0.1-SNAPSHOT 9 | 10 | headway 11 | 12 | http://www.example.com 13 | 14 | 15 | UTF-8 16 | 11 17 | 18 | 19 | 20 | 21 | org.seleniumhq.selenium 22 | selenium-java 23 | 4.11.0 24 | 25 | 26 | org.testng 27 | testng 28 | 7.4.0 29 | 30 | 31 | 32 | io.github.bonigarcia 33 | webdrivermanager 34 | 6.1.0 35 | 36 | 37 | com.aventstack 38 | extentreports 39 | 5.0.8 40 | 41 | 42 | org.apache.logging.log4j 43 | log4j-api 44 | 2.13.1 45 | 46 | 47 | org.apache.logging.log4j 48 | log4j-core 49 | 2.14.1 50 | 51 | 52 | com.codoid.products 53 | fillo 54 | 1.21 55 | 56 | 57 | com.googlecode.json-simple 58 | json-simple 59 | 1.1.1 60 | 61 | 62 | 63 | ch.qos.logback 64 | logback-classic 65 | 1.4.11 66 | compile 67 | 68 | 69 | 70 | 71 | 72 | 74 | 75 | 76 | 77 | maven-clean-plugin 78 | 3.1.0 79 | 80 | 81 | 82 | maven-resources-plugin 83 | 3.0.2 84 | 85 | 86 | maven-compiler-plugin 87 | 3.8.0 88 | 89 | 90 | maven-jar-plugin 91 | 3.0.2 92 | 93 | 94 | maven-install-plugin 95 | 2.5.2 96 | 97 | 98 | maven-deploy-plugin 99 | 2.8.2 100 | 101 | 102 | 103 | maven-site-plugin 104 | 3.7.1 105 | 106 | 107 | maven-project-info-reports-plugin 108 | 3.0.0 109 | 110 | 111 | org.apache.maven.plugins 112 | maven-surefire-plugin 113 | 3.0.0-M7 114 | 115 | 116 | testng.xml 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/driver/DriverManager.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.driver; 2 | 3 | import java.time.Duration; 4 | import org.apache.logging.log4j.LogManager; 5 | import org.apache.logging.log4j.Logger; 6 | import org.openqa.selenium.WebDriver; 7 | import org.openqa.selenium.WebDriverException; 8 | import org.openqa.selenium.chrome.ChromeDriver; 9 | import org.openqa.selenium.chrome.ChromeOptions; 10 | import org.openqa.selenium.edge.EdgeDriver; 11 | import org.openqa.selenium.firefox.FirefoxDriver; 12 | import org.openqa.selenium.firefox.FirefoxOptions; 13 | import org.openqa.selenium.safari.SafariDriver; 14 | import com.qed42.qa.configurations.Configuration; 15 | import org.testng.annotations.Optional; 16 | 17 | /** 18 | * DriverManager class contains methods to initialise browser driver & launch browser before test execution 19 | * and quit the browser after test execution. Browser type is passed as parameter via testng.xml file. 20 | * 21 | */ 22 | public class DriverManager { 23 | 24 | protected static ThreadLocal driver = new ThreadLocal<>(); 25 | static Logger log = LogManager.getLogger(DriverManager.class); 26 | 27 | private DriverManager() { 28 | // To prevent external instantiation of this class 29 | } 30 | 31 | /** 32 | * This method is used to retrieve the driver and does not take any parameters. 33 | * 34 | * @return 35 | */ 36 | public static WebDriver getDriver() { 37 | return driver.get(); 38 | } 39 | 40 | 41 | /** 42 | * This method initializes the driver and launches browser. It maximizes the browser window. 43 | * It is called before each test. 44 | * 45 | * @param browser 46 | */ 47 | public static void initialize(@Optional("chrome") String browser) { 48 | driver.set(getDriver(browser)); 49 | 50 | log.info(browser.toUpperCase() + " is configured"); 51 | 52 | getDriver().manage().window().maximize(); 53 | getDriver().manage().deleteAllCookies(); 54 | 55 | getDriver().manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); 56 | getDriver().manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10)); 57 | } 58 | 59 | /** 60 | * This method is used to retrieve the driver based on the browser parameter. 61 | * Supported browsers - Chrome, Chrome-headless Firefox, Firefox-headless, Safari and Edge. 62 | * 63 | * @param browserName 64 | * @return 65 | */ 66 | public static WebDriver getDriver(String browserName) { 67 | WebDriver driver = null; 68 | 69 | switch (browserName) { 70 | case "chrome": 71 | driver = new ChromeDriver(); 72 | break; 73 | case "chrome-headless": 74 | driver = new ChromeDriver(new ChromeOptions().addArguments("--headless=new")); 75 | break; 76 | case "firefox": 77 | driver = new FirefoxDriver(); 78 | break; 79 | case "firefox-headless": 80 | driver = new FirefoxDriver(new FirefoxOptions().addArguments("-headless")); 81 | break; 82 | case "edge": 83 | if (Configuration.PLATFORM_NAME.toLowerCase().contains("mac")) { 84 | throw new WebDriverException("Your operating system does not support the requested browser"); 85 | } else { 86 | driver = new EdgeDriver(); 87 | } 88 | break; 89 | case "safari": 90 | if (Configuration.PLATFORM_NAME.toLowerCase().contains("windows")) { 91 | throw new WebDriverException("Your operating system does not support the requested browser"); 92 | } else { 93 | driver = new SafariDriver(); 94 | } 95 | break; 96 | default: 97 | System.out.println("No driver found for:" + browserName); 98 | } 99 | return driver; 100 | } 101 | 102 | /** 103 | * quit() method is called after every test. It closes the browser 104 | * 105 | */ 106 | public static void quit() { 107 | getDriver().manage().deleteAllCookies(); 108 | getDriver().close(); 109 | } 110 | 111 | /** 112 | * terminate() method is called after every class. It removes the ThreadLocal driver. 113 | */ 114 | public static void terminate() { 115 | driver.remove(); 116 | } 117 | 118 | /* 119 | * Use below method when browser is passed as parameter in config.properties 120 | * 121 | * public void initialize() { 122 | * String browserName = properties.getProperty("browser"); 123 | * driver.set(getDriver(browserName)); 124 | * 125 | * log.info(browserName + " is configured"); 126 | * 127 | * getDriver().manage().window().maximize(); 128 | * getDriver().manage().deleteAllCookies(); 129 | * 130 | * getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 131 | * getDriver().manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS); 132 | * 133 | * } 134 | */ 135 | 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/com/qed42/qa/utilities/ExcelManager.java: -------------------------------------------------------------------------------- 1 | package com.qed42.qa.utilities; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import com.codoid.products.exception.FilloException; 7 | import com.codoid.products.fillo.Connection; 8 | import com.codoid.products.fillo.Fillo; 9 | import com.codoid.products.fillo.Recordset; 10 | 11 | /** 12 | * Fillo library is used for reading and writing data with excel files (xlsx and xls) using SQL queries. 13 | * Create an instance of 'ExcelManager' class and access methods to read and data from/to excel. 14 | * 15 | * @author QED42 16 | * 17 | */ 18 | public class ExcelManager { 19 | 20 | public String filepath1; 21 | 22 | /** 23 | * Performs "SELECT * From ". Returns all data from an excel sheet. 24 | * 25 | * @param filepath - Path of the excel file directory 26 | * @param excelName - Excel file name 27 | * @param sheetName - Sheet name in an excel file 28 | * @return 29 | * @throws FilloException 30 | */ 31 | public List> getAllData(String filepath, String excelName, String sheetName) 32 | throws FilloException { 33 | Fillo fillo = new Fillo(); 34 | filepath1 = filepath + excelName; 35 | List> recordList = new ArrayList<>(); 36 | 37 | Connection connection = fillo.getConnection(filepath1); 38 | String strQuery = "Select * from" + " " + sheetName; 39 | Recordset recordset = connection.executeQuery(strQuery); 40 | int columnCount = recordset.getFieldNames().size(); 41 | 42 | while (recordset.next()) { 43 | HashMap rowData = new HashMap(); 44 | 45 | for (int i = 0; i <= columnCount - 1; i++) { 46 | String fieldKey = recordset.getFieldNames().get(i); 47 | String fieldValue = recordset.getField(fieldKey); 48 | rowData.put(fieldKey, fieldValue); 49 | } 50 | recordList.add(rowData); 51 | } 52 | recordset.close(); 53 | connection.close(); 54 | return recordList; 55 | } 56 | 57 | /** 58 | * Performs "SELECT * From Where ". Returns data that 59 | * meet the condition(s) given in where clause, from an excel sheet. 60 | * 61 | * @param filepath - Path of the excel file directory 62 | * @param excelName - Excel file name 63 | * @param sheetName - Sheet name in an excel file 64 | * @param whereClause - Mention single or multiple conditions. With or without 65 | * LIKE Operator ex. "Select * from Sheet1 where userName 66 | * like 'Cod%'" 67 | * @return 68 | * @throws FilloException 69 | */ 70 | public List> getDataWithWhere(String filepath, String excelName, String sheetName, 71 | String whereClause) throws FilloException { 72 | Fillo fillo = new Fillo(); 73 | filepath1 = filepath + excelName; 74 | List> recordList = new ArrayList<>(); 75 | 76 | Connection connection = fillo.getConnection(filepath1); 77 | String strQuery = "Select * from" + " " + sheetName + " " + whereClause; 78 | Recordset recordset = connection.executeQuery(strQuery); 79 | int columnCount = recordset.getFieldNames().size(); 80 | 81 | while (recordset.next()) { 82 | HashMap rowData = new HashMap(); 83 | 84 | for (int i = 0; i <= columnCount - 1; i++) { 85 | String fieldKey = recordset.getFieldNames().get(i); 86 | String fieldValue = recordset.getField(fieldKey); 87 | rowData.put(fieldKey, fieldValue); 88 | } 89 | recordList.add(rowData); 90 | } 91 | recordset.close(); 92 | connection.close(); 93 | return recordList; 94 | } 95 | 96 | /** 97 | * Performs "SELECT * From Where 98 | * ". Returns data that meet the condition given in where clause, from an excel 99 | * sheet. 100 | * 101 | * @param filepath - Path of the excel file directory 102 | * @param excelName - Excel file name 103 | * @param sheetName - Sheet name in an excel file 104 | * @param fieldName - Column name 105 | * @param fieldValue - Column value 106 | * @param operator - ex. '=','!=','<','>','<=','>=' 107 | * @return 108 | * @throws FilloException 109 | */ 110 | public List> getDataWithWhere(String filepath, String excelName, String sheetName, 111 | String fieldName, String operator, String fieldValue) throws FilloException { 112 | Fillo fillo = new Fillo(); 113 | filepath1 = filepath + excelName; 114 | List> recordList = new ArrayList<>(); 115 | 116 | Connection connection = fillo.getConnection(filepath1); 117 | String strQuery = "Select * from" + " " + sheetName + " " + "where " + fieldName + operator + "'" + fieldValue 118 | + "'"; 119 | Recordset recordset = connection.executeQuery(strQuery); 120 | int columnCount = recordset.getFieldNames().size(); 121 | 122 | while (recordset.next()) { 123 | HashMap rowData = new HashMap(); 124 | 125 | for (int i = 0; i <= columnCount - 1; i++) { 126 | String fieldKey = recordset.getFieldNames().get(i); 127 | String fieldValue1 = recordset.getField(fieldKey); 128 | rowData.put(fieldKey, fieldValue1); 129 | } 130 | recordList.add(rowData); 131 | } 132 | recordset.close(); 133 | connection.close(); 134 | return recordList; 135 | } 136 | 137 | /** 138 | * Performs "INSERT into" ( ) Values () ". 139 | * Inserts record into an excel sheet. 140 | * 141 | * @param filepath - Path of the excel file directory 142 | * @param excelName - Excel file name 143 | * @param sheetName - Sheet name in an excel file 144 | * @param fieldNames - Column names Ex. "Username,Password" 145 | * @param fieldValues - Column values Ex. "'abc','123'" 146 | * @return 147 | * @throws FilloException 148 | */ 149 | public void insertRowData(String filepath, String excelName, String sheetName, String fieldNames, 150 | String fieldValues) throws FilloException { 151 | 152 | Fillo fillo = new Fillo(); 153 | filepath1 = filepath + excelName; 154 | 155 | Connection connection = fillo.getConnection(filepath1); 156 | String strQuery = "INSERT into " + sheetName + " (" + fieldNames + ") Values(" + fieldValues + ")"; 157 | connection.executeUpdate(strQuery); 158 | connection.close(); 159 | } 160 | 161 | /** 162 | * Performs "UPDATE" set = where 163 | * ) ". Updates a field for records matching the condition given in 164 | * where clause. 165 | * 166 | * @param filepath - Path of the excel file directory 167 | * @param excelName - Excel file name 168 | * @param sheetName - Sheet name in an excel file 169 | * @param whereClause 170 | * @param fieldName - Column name Ex. "Username" 171 | * @param fieldValue - Column value Ex. "'abc'" 172 | * @return 173 | * @throws FilloException 174 | */ 175 | public void updateDataWithWhere(String filepath, String excelName, String sheetName, String fieldName, 176 | String fieldValue, String whereClause) throws FilloException { 177 | Fillo fillo = new Fillo(); 178 | filepath1 = filepath + excelName; 179 | Connection connection = fillo.getConnection(filepath); 180 | 181 | String strQuery = "Update " + sheetName + " set " + fieldName + "=" + fieldValue + " " + whereClause; 182 | connection.executeUpdate(strQuery); 183 | connection.close(); 184 | } 185 | 186 | /** 187 | * Performs "UPDATE" set = where 188 | * ) ". Updates field of all records. 189 | * 190 | * @param filepath - Path of the excel file directory 191 | * @param excelName - Excel file name 192 | * @param sheetName - Sheet name in an excel file 193 | * @param fieldName - Column name Ex. "Username" 194 | * @param fieldValue - Column value Ex. "'abc'" 195 | * @return 196 | * @throws FilloException 197 | */ 198 | public void updateData(String filepath, String excelName, String sheetName, String fieldName, String fieldValue) 199 | throws FilloException { 200 | 201 | Fillo fillo = new Fillo(); 202 | filepath1 = filepath + excelName; 203 | 204 | Connection connection = fillo.getConnection(filepath); 205 | String strQuery = "Update " + sheetName + " set " + fieldName + "=" + fieldValue; 206 | connection.executeUpdate(strQuery); 207 | connection.close(); 208 | } 209 | 210 | } 211 | --------------------------------------------------------------------------------