├── .gitignore ├── README.md ├── docker-compose.yml ├── logs ├── TestCase1_1.log ├── TestCase2_1.log └── TestCase3_1.log ├── pom.xml ├── src ├── main │ ├── java │ │ ├── pageObjects │ │ │ ├── HomePageObjects.java │ │ │ ├── LoginPageObjects.java │ │ │ ├── TaskPageObjects.java │ │ │ └── UsersPageObjects.java │ │ ├── reusableComponents │ │ │ ├── ActionEngine.java │ │ │ ├── DB_Operations.java │ │ │ ├── ExcelOperations.java │ │ │ ├── JiraOperations.java │ │ │ ├── ListenersImplementation.java │ │ │ ├── PropertiesOperations.java │ │ │ ├── TestRetryAnalyzer.java │ │ │ └── TestRetryAnalyzerListener.java │ │ └── testBase │ │ │ ├── BrowserFactory.java │ │ │ ├── DriverFactory.java │ │ │ ├── ExtentFactory.java │ │ │ ├── ExtentReportNG.java │ │ │ ├── MyLogger.java │ │ │ └── TestBase.java │ └── resources │ │ └── log4j2.xml └── test │ ├── java │ └── Tests │ │ ├── TestCase.java │ │ └── UserLoginTests.java │ └── resources │ ├── config.properties │ └── testData │ └── TaskCreationTestData.xlsx └── testng.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | test-output/ 4 | target/ 5 | .settings -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Level - End to End Selenium Test Automation Framework (Testng - Java). 2 | 3 | For latest updates, do consider subscribe to my channel: https://www.youtube.com/automationtalks 4 | 5 | Before you go to this framework videos, You need to go through Basic Level Framework, Refer below Youtube Playlist for the same: 6 | Basic Level Selenium Framework: https://www.youtube.com/playlist?list=PL5fOKT7XR42Om0spD8QtxuQ4Y9ONra6dq 7 | 8 | Watch this space for more details on Advanced Level framework 9 | 10 | Refer below playlist (Under construction): https://www.youtube.com/playlist?list=PL5fOKT7XR42OgLXmX8wYYhB7L0sN-uqpR 11 | 12 | #Topic wise videos 13 | 14 | Video#1 - Course Introduction --> https://youtu.be/8OjTupvE8mI 15 | 16 | Video#2 - AUT and Test Cases walkthrough --> https://youtu.be/2cueo-051zI 17 | 18 | Video#3 - Create folder structure --> https://youtu.be/z-AKOHA1dnM 19 | 20 | Video#4 - Start creating Page Objects --> https://youtu.be/Thql1qrWFcI 21 | 22 | Video#5 - Demo on XPath writting tool - SelectorsHub --> https://youtu.be/QLCrVmy61Co 23 | 24 | Video#6 - Continued on Page Objects --> https://youtu.be/Jf-8Tte7bQE 25 | 26 | Video#7 - create browserfactory --> https://www.youtube.com/watch?v=pcVWuz8YEqQ 27 | 28 | Video#8 - create driverfactory --> https://www.youtube.com/watch?v=5wgusEV4uSQ 29 | 30 | Video#9 - Create Threadsafe TestBase --> https://youtu.be/diOPcwdGhmA 31 | 32 | video#10 - Create Threadsafe extent reporting --> https://youtu.be/N4JKX7qNw_s 33 | 34 | video#11 - Setup Extent Report via TestNG Listeners --> https://youtu.be/ro2mwk-YKvw 35 | 36 | video#12 - Setup Logging (Using Log4j2) - To Support Parallel Test Execution --> https://youtu.be/0JQekot_5V8 37 | 38 | Video#13 - Action Engine – Log every test action in Extent Report / Logger --> https://youtu.be/Tv2U0oa0OMY 39 | 40 | video#14 - Create Login Test – To verify Parallel Execution with Custom message logs --> https://youtu.be/6kuJUsS1haI 41 | 42 | video#15 - Create DataDriven Test for TaskCreation & Execute in Parallel - Part1 --> https://youtu.be/6CxQ6Pl6qS8 43 | 44 | video#16 - Database Validation in Selenium - Java Test Case (Threadsafe) --> https://youtu.be/7rgVF9x_HIk 45 | 46 | video#17 - Create DataDriven Test for TaskCreation & Execute in Parallel - Part2 --> https://youtu.be/Q6I90cyhlGM 47 | 48 | video#18 - Create Bug / Defect automatically in JIRA from Selenium Test Automation Framework (JIRA Rest API) --> 49 | 50 | video#19 - Add Attachment (Screenshot of failed Test Case) to Jira Issue (Via Jira Rest API) --> 51 | 52 | video#20 - Add Test Data in JIRA Automatic Defect / Bug Creation (Hashmap test data) --> 53 | 54 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # To execute this docker-compose yml file use `docker-compose -f docker-compose-v3.yml up` 2 | # Add the `-d` flag at the end for detached execution 3 | # To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`version: "3" 4 | services: 5 | hub: 6 | image: selenium/hub 7 | ports: 8 | - "4444:4444" 9 | environment: 10 | GRID_MAX_SESSION: 16 11 | GRID_BROWSER_TIMEOUT: 3000 12 | GRID_TIMEOUT: 3000 13 | 14 | chrome: 15 | image: selenium/node-chrome 16 | depends_on: 17 | - hub 18 | environment: 19 | HUB_PORT_4444_TCP_ADDR: hub 20 | HUB_PORT_4444_TCP_PORT: 4444 21 | volumes: 22 | - /dev/shm:/dev/shm 23 | links: 24 | - hub 25 | 26 | firefox: 27 | image: selenium/node-firefox 28 | depends_on: 29 | - hub 30 | environment: 31 | HUB_PORT_4444_TCP_ADDR: hub 32 | HUB_PORT_4444_TCP_PORT: 4444 33 | volumes: 34 | - /dev/shm:/dev/shm 35 | links: 36 | - hub -------------------------------------------------------------------------------- /logs/TestCase1_1.log: -------------------------------------------------------------------------------- 1 | [INFO ] 2020-09-13 14:25:52.235 - testBase.MyLogger:startTestCase 21==> 2 | 3 | ************** Execution Started : TestCase1************** 4 | 5 | [INFO ] 2020-09-13 14:25:52.276 - Tests.TestCase:TestCase1 23==> test 1 execution is in progress 6 | -------------------------------------------------------------------------------- /logs/TestCase2_1.log: -------------------------------------------------------------------------------- 1 | [INFO ] 2020-09-13 14:25:52.219 - testBase.MyLogger:startTestCase 21==> 2 | 3 | ************** Execution Started : TestCase2************** 4 | 5 | [INFO ] 2020-09-13 14:25:52.234 - Tests.TestCase:TestCase2 31==> test2 6 | -------------------------------------------------------------------------------- /logs/TestCase3_1.log: -------------------------------------------------------------------------------- 1 | [INFO ] 2020-09-13 14:25:52.088 - testBase.MyLogger:startTestCase 21==> 2 | 3 | ************** Execution Started : TestCase3************** 4 | 5 | [INFO ] 2020-09-13 14:25:52.218 - Tests.TestCase:TestCase3 40==> test3 6 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.AutomationTalks 6 | AdavencedLevel.QDPM 7 | 0.0.1-SNAPSHOT 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | 17 | org.apache.maven.plugins 18 | maven-compiler-plugin 19 | 3.8.1 20 | 21 | 1.8 22 | 1.8 23 | 24 | 25 | 26 | org.apache.maven.plugins 27 | maven-surefire-plugin 28 | 3.0.0-M1 29 | 30 | 31 | ${project.basedir}\Output\${maven.build.timestamp}\Logs\ 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | testng.xml 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.seleniumhq.selenium 52 | selenium-java 53 | 3.141.59 54 | 55 | 56 | org.testng 57 | testng 58 | 7.1.0 59 | 60 | 61 | io.github.bonigarcia 62 | webdrivermanager 63 | 4.2.0 64 | 65 | 66 | com.aventstack 67 | extentreports 68 | 4.1.7 69 | 70 | 71 | 72 | 73 | org.apache.poi 74 | poi 75 | 4.1.2 76 | 77 | 78 | 79 | org.apache.poi 80 | poi-ooxml 81 | 4.1.2 82 | 83 | 84 | org.slf4j 85 | slf4j-simple 86 | 1.7.21 87 | 88 | 89 | org.apache.logging.log4j 90 | log4j-core 91 | 2.11.1 92 | 93 | 94 | 95 | 96 | mysql 97 | mysql-connector-java 98 | 8.0.21 99 | 100 | 101 | 103 | 104 | com.googlecode.json-simple 105 | json-simple 106 | 1.1 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/main/java/pageObjects/HomePageObjects.java: -------------------------------------------------------------------------------- 1 | package pageObjects; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.PageFactory; 8 | import org.testng.Assert; 9 | 10 | import testBase.DriverFactory; 11 | import testBase.TestBase; 12 | 13 | public class HomePageObjects extends TestBase{ 14 | 15 | 16 | By sidebarMenu_Dashboard = By.xpath("//ul[@class='page-sidebar-menu']//i/following-sibling::span[text()='Dashboard']"); 17 | 18 | //click on menu bar - by passing name of menu 19 | public void clickOnSideMenu(String menu) { 20 | String MenuXpath = "//ul[@class='page-sidebar-menu']//i/following-sibling::span[text()='"+menu+"']"; 21 | DriverFactory.getInstance().getDriver().findElement(By.xpath(MenuXpath)).click(); 22 | } 23 | 24 | //click on sub menu bar - by passing name of menu 25 | public void clickOnSideSubMenu(String menu, String submenu) { 26 | String MenuXpath = "//ul[@class='page-sidebar-menu']//i/following-sibling::span[text()='"+menu+"']"; 27 | DriverFactory.getInstance().getDriver().findElement(By.xpath(MenuXpath)).click(); 28 | String submenuXpath="//ul[@class='page-sidebar-menu']//i/following-sibling::span[text()='"+menu+"']/ancestor::a/following-sibling::ul//span[text()='"+submenu+"']"; 29 | DriverFactory.getInstance().getDriver().findElement(By.xpath(submenuXpath)).click(); 30 | } 31 | 32 | public void checkIfDashBoardPageIsOpened() { 33 | Assert.assertTrue(isElementPresent_custom(DriverFactory.getInstance().getDriver().findElement(sidebarMenu_Dashboard), "DashBoardMenu")); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/pageObjects/LoginPageObjects.java: -------------------------------------------------------------------------------- 1 | package pageObjects; 2 | 3 | 4 | import org.openqa.selenium.By; 5 | 6 | import testBase.DriverFactory; 7 | import testBase.TestBase; 8 | 9 | public class LoginPageObjects extends TestBase { 10 | 11 | By EMAIL = By.name("login[email]"); 12 | By PASSWORD = By.name("login[password]"); 13 | By LOGIN_BTN = By.xpath("//button[@type='submit' and text()='Login ']"); 14 | 15 | 16 | //login to App 17 | public void login(String email, String password) { 18 | sendKeys_custom(DriverFactory.getInstance().getDriver().findElement(EMAIL), "LoginEmailFIeld", email); 19 | sendKeys_custom(DriverFactory.getInstance().getDriver().findElement(PASSWORD), "LoginPasswordFIeld", password); 20 | 21 | click_custom(DriverFactory.getInstance().getDriver().findElement(LOGIN_BTN), "LoginButton"); 22 | 23 | } 24 | 25 | 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/pageObjects/TaskPageObjects.java: -------------------------------------------------------------------------------- 1 | package pageObjects; 2 | 3 | import java.util.HashMap; 4 | 5 | import org.openqa.selenium.By; 6 | 7 | import testBase.DriverFactory; 8 | import testBase.TestBase; 9 | 10 | public class TaskPageObjects extends TestBase { 11 | 12 | 13 | By btn_addTask = By.xpath("//button[text()='Add Task']"); 14 | By field_Search = By.id("search_menu"); 15 | By txt_Search = By.xpath("//*[@id='search_menu']//input[@name='search[keywords]']"); 16 | By btn_Search = By.xpath("//*[@id='search_menu']//input[@type='submit']"); 17 | By dd_SelectProjectForNewTaskCreation = By.id("form_projects_id"); 18 | By dd_taskType = By.id("tasks_tasks_type_id"); 19 | By txt_taskName = By.id("tasks_name"); 20 | By dd_taskStatus = By.id("tasks_tasks_status_id"); 21 | By dd_taskPriority = By.id("tasks_tasks_priority_id"); 22 | By dd_taskLabel = By.id("tasks_tasks_label_id"); 23 | By dd_taskCreatedBy = By.id("tasks_created_by"); 24 | By btn_save = By.xpath("//button[@type='submit' and text()='Save']"); 25 | 26 | 27 | public void createTask(HashMap testData) throws Throwable { 28 | Thread.sleep(2000); 29 | selectDropDownByVisibleText_custom(DriverFactory.getInstance().getDriver().findElement(dd_SelectProjectForNewTaskCreation), "NewTaskProjectDropDown", testData.get("ProjectToCreateTaskUnder")); 30 | selectDropDownByVisibleText_custom(DriverFactory.getInstance().getDriver().findElement(dd_taskType), "NewTaskType", testData.get("TaskType")); 31 | sendKeys_custom(DriverFactory.getInstance().getDriver().findElement(txt_taskName), "newTaskName", testData.get("TaskName")); 32 | selectDropDownByVisibleText_custom(DriverFactory.getInstance().getDriver().findElement(dd_taskStatus), "NewTaskStatus", testData.get("TaskStatus")); 33 | selectDropDownByVisibleText_custom(DriverFactory.getInstance().getDriver().findElement(dd_taskPriority), "NewTaskPriority", testData.get("TaskPriority")); 34 | selectDropDownByVisibleText_custom(DriverFactory.getInstance().getDriver().findElement(dd_taskLabel), "NewTaskLabel", testData.get("Label")); 35 | click_custom(DriverFactory.getInstance().getDriver().findElement(btn_save), "NewTaskSaveButton"); 36 | 37 | } 38 | 39 | public void Search_Verify_TaskCreationOnUI(HashMap testData) throws Throwable { 40 | 41 | moveToElement_custom(DriverFactory.getInstance().getDriver().findElement(field_Search), "TaskSearchOption"); 42 | sendKeys_custom(DriverFactory.getInstance().getDriver().findElement(txt_Search), "TaskSearchBox", testData.get("TaskName")); 43 | click_custom(DriverFactory.getInstance().getDriver().findElement(btn_Search), "SearchButton"); 44 | 45 | //table verification 46 | assertEqualsString_custom(testData.get("TaskName"), getTaskTableCellValueByColumnName("Name"), "TaskNameInTable"); 47 | 48 | } 49 | 50 | private String getTaskTableCellValueByColumnName(String columnName) { 51 | 52 | String valueXpath = "//table[starts-with(@id, 'itmes_listing')]/tbody/tr/td[count(//table[starts-with(@id, 'itmes_listing')]/thead/tr/th/div[text()='"+columnName+"']/parent::th/preceding-sibling::th)+1]"; 53 | String value = DriverFactory.getInstance().getDriver().findElement(By.xpath(valueXpath)).getText(); 54 | return value; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/pageObjects/UsersPageObjects.java: -------------------------------------------------------------------------------- 1 | package pageObjects; 2 | 3 | import org.openqa.selenium.By; 4 | 5 | public class UsersPageObjects { 6 | 7 | By btn_addUser = By.xpath("//button[text()='Add User']"); 8 | By field_Search = By.id("search_menu"); 9 | By txt_Search = By.xpath("//*[@id='search_menu']//input[@name='search[keywords]']"); 10 | By btn_Search = By.xpath("//*[@id='search_menu']//input[@type='submit']"); 11 | By dd_group = By.id("users_users_group_id"); 12 | By txt_FullName = By.name("users[name]"); 13 | By txt_Password = By.name("users[password]"); 14 | By txt_Email = By.name("users[email]"); 15 | By txt_Phone = By.name("extra_fields[9]"); 16 | By btn_UserPhoto = By.id("users_photo"); 17 | By btn_Save = By.id("submit_button"); 18 | By chk_notifyUser = By.id("users_notify"); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/ActionEngine.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | import org.openqa.selenium.JavascriptExecutor; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.interactions.Actions; 6 | import org.openqa.selenium.support.ui.Select; 7 | import org.testng.Assert; 8 | 9 | import com.aventstack.extentreports.Status; 10 | 11 | import testBase.DriverFactory; 12 | import testBase.ExtentFactory; 13 | 14 | /** 15 | * @author: Prakash Narkhede 16 | * @Youtube: https://www.youtube.com/automationtalks 17 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 18 | */ 19 | public class ActionEngine { 20 | 21 | //Customized sendkeys method-> To log sendkeys message for every occ. 22 | public void sendKeys_custom(WebElement element, String fieldName, String valueToBeSent) { 23 | try { 24 | element.sendKeys(valueToBeSent); 25 | //log success message in exgent report 26 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Ented value as: "+valueToBeSent); 27 | } catch (Exception e) { 28 | //log failure in extent 29 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Value enter in field: "+fieldName + " is failed due to exception: "+e); 30 | } 31 | } 32 | 33 | 34 | //custom click method to log evey click action in to extent report 35 | public void click_custom(WebElement element, String fieldName) { 36 | try { 37 | element.click(); 38 | //log success message in exgent report 39 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Clicked Successfully! "); 40 | } catch (Exception e) { 41 | //log failure in extent 42 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Unable to click on field: " +fieldName +" due to exception: "+e); 43 | } 44 | } 45 | 46 | 47 | //clear data from field 48 | public void clear_custom(WebElement element,String fieldName) { 49 | try { 50 | element.clear(); 51 | Thread.sleep(250); 52 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Data Cleared Successfully! "); 53 | } catch (Exception e) { 54 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Unable to clear Data on field: " +fieldName +" due to exception: "+e); 55 | 56 | } 57 | } 58 | 59 | //custom mouseHover 60 | public void moveToElement_custom(WebElement element,String fieldName){ 61 | try{ 62 | JavascriptExecutor executor = (JavascriptExecutor) DriverFactory.getInstance().getDriver(); 63 | executor.executeScript("arguments[0].scrollIntoView(true);", element); 64 | Actions actions = new Actions(DriverFactory.getInstance().getDriver()); 65 | actions.moveToElement(element).build().perform(); 66 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Mouse hovered Successfully! "); 67 | Thread.sleep(1000); 68 | }catch(Exception e){ 69 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Unable to hover mouse on field: " +fieldName +" due to exception: "+e); 70 | 71 | } 72 | } 73 | 74 | 75 | //check if element is Present 76 | public boolean isElementPresent_custom(WebElement element,String fieldName){ 77 | boolean flag = false; 78 | try { 79 | flag = element.isDisplayed(); 80 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Presence of field is: "+ flag); 81 | return flag; 82 | } catch (Exception e) { 83 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Checking for presence of field: " +fieldName +" not tested due to exception: "+e); 84 | return flag; 85 | } 86 | } 87 | 88 | 89 | //Select dropdown value value by visibleText 90 | public void selectDropDownByVisibleText_custom(WebElement element, String fieldName, String ddVisibleText) throws Throwable { 91 | try { 92 | Select s = new Select(element); 93 | s.selectByVisibleText(ddVisibleText); 94 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Dropdown Value Selected by visible text: "+ ddVisibleText); 95 | } catch (Exception e) { 96 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Dropdown value not selected for field: " +fieldName +" due to exception: "+e); 97 | } 98 | } 99 | 100 | //Select dropdown value value by value 101 | public void selectDropDownByValue_custom(WebElement element, String fieldName, String ddValue) throws Throwable { 102 | try { 103 | Select s = new Select(element); 104 | s.selectByValue(ddValue); 105 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Dropdown Value Selected by visible text: "+ ddValue); 106 | } catch (Exception e) { 107 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Dropdown value not selected for field: " +fieldName +" due to exception: "+e); 108 | } 109 | } 110 | 111 | //String Asserts 112 | public void assertEqualsString_custom(String expvalue, String actualValue, String locatorName) throws Throwable { 113 | try { 114 | if(actualValue.equals(expvalue)) { 115 | ExtentFactory.getInstance().getExtent().log(Status.PASS, "String Assertion is successful on field "+ locatorName + " Expected value was: "+ expvalue + " actual value is: "+actualValue); 116 | }else { 117 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "String Assertion FAILED on field "+ locatorName + " Expected value was: "+ expvalue + " actual value is: "+actualValue); 118 | Assert.assertTrue(false); 119 | } 120 | } catch (Exception e) { 121 | Assert.assertTrue(false, e.toString()); 122 | } 123 | } 124 | 125 | //Get text from webelement 126 | public String getText_custom(WebElement element, String fieldName) { 127 | String text = ""; 128 | try { 129 | text = element.getText(); 130 | ExtentFactory.getInstance().getExtent().log(Status.PASS, fieldName+"==> Text retried is: "+ text); 131 | return text; 132 | } catch (Exception e) { 133 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, fieldName+"==> Text not retried due to exception: "+ e); 134 | 135 | } 136 | return text; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/DB_Operations.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | import java.sql.*; 4 | import java.util.HashMap; 5 | /** 6 | * @author: Prakash Narkhede 7 | * @Youtube: https://www.youtube.com/automationtalks 8 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 9 | */ 10 | public class DB_Operations { 11 | 12 | public synchronized HashMap getSqlResultInMap(String sql) { 13 | HashMap data_map = new HashMap<>(); 14 | 15 | try{ 16 | Class.forName("com.mysql.cj.jdbc.Driver"); 17 | Connection con=DriverManager.getConnection( 18 | "jdbc:mysql://localhost:3306/qdpm_qa?serverTimezone=UTC","root",""); 19 | 20 | Statement stmt=con.createStatement(); 21 | ResultSet rs=stmt.executeQuery(sql); 22 | ResultSetMetaData md = rs.getMetaData(); 23 | 24 | while (rs.next()) { 25 | for (int i = 1; i <= md.getColumnCount(); i++) { 26 | data_map.put(md.getColumnName(i), rs.getString(i)); 27 | } 28 | } 29 | System.out.println(data_map); 30 | con.close(); 31 | }catch(Exception e){ System.out.println(e);} 32 | return data_map; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/ExcelOperations.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | import java.io.File; 4 | import java.util.HashMap; 5 | 6 | import org.apache.poi.ss.usermodel.CellType; 7 | import org.apache.poi.ss.usermodel.Sheet; 8 | import org.apache.poi.ss.usermodel.Workbook; 9 | import org.apache.poi.ss.usermodel.WorkbookFactory; 10 | 11 | public class ExcelOperations { 12 | 13 | String filePath; 14 | Sheet sh; 15 | 16 | public ExcelOperations(String sheetName) { 17 | try { 18 | filePath = System.getProperty("user.dir")+PropertiesOperations.getPropertyValueByKey("testDataLocation"); 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | //open file - workbook 23 | File testDataFile = new File(filePath); 24 | Workbook wb = null; 25 | try { 26 | wb = WorkbookFactory.create(testDataFile); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | 31 | sh = wb.getSheet(sheetName); 32 | } 33 | 34 | //get test data from test data sheet in hashmap based on row number 35 | @SuppressWarnings("deprecation") 36 | public HashMap getTestDataInMap(int rowNum) throws Exception { 37 | //read data row by row and put in map 38 | HashMap hm = new HashMap(); 39 | 40 | for (int i = 0; i < sh.getRow(0).getLastCellNum(); i++) { 41 | String value; 42 | if(sh.getRow(rowNum).getCell(i) != null) { 43 | sh.getRow(rowNum).getCell(i).setCellType(CellType.STRING); 44 | value = sh.getRow(rowNum).getCell(i).toString(); 45 | } 46 | else { 47 | value = ""; 48 | } 49 | hm.put(sh.getRow(0).getCell(i).toString(), value); 50 | } 51 | return hm; 52 | } 53 | 54 | //get row count 55 | public int getRowCount() { 56 | return sh.getLastRowNum(); 57 | } 58 | 59 | //ger column count 60 | public int getColCount() { 61 | return sh.getRow(0).getLastCellNum(); 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/JiraOperations.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.Base64; 6 | 7 | import org.apache.http.HttpResponse; 8 | import org.apache.http.client.ClientProtocolException; 9 | import org.apache.http.client.HttpClient; 10 | import org.apache.http.client.methods.HttpPost; 11 | import org.apache.http.entity.StringEntity; 12 | import org.apache.http.entity.mime.MultipartEntityBuilder; 13 | import org.apache.http.entity.mime.content.FileBody; 14 | import org.apache.http.impl.client.HttpClientBuilder; 15 | import org.apache.http.util.EntityUtils; 16 | import org.json.simple.JSONObject; 17 | import org.json.simple.parser.JSONParser; 18 | import org.json.simple.parser.ParseException; 19 | 20 | /** 21 | * @author: Prakash Narkhede 22 | * @Youtube: https://www.youtube.com/automationtalks 23 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 24 | */ 25 | public class JiraOperations { 26 | String jiraURL = PropertiesOperations.getPropertyValueByKey("jiraURL"); 27 | String jiraUserName = PropertiesOperations.getPropertyValueByKey("jiraUserName"); 28 | String jiraAccessKey = PropertiesOperations.getPropertyValueByKey("jiraSecretKey"); 29 | 30 | 31 | //create Jira Issue as bug 32 | public String createJiraIssue(String ProjectName, String issueSummary, String issueDescription, String component, String priority, String label, String env, String assignee) throws ClientProtocolException, IOException, ParseException { 33 | 34 | String issueId = null; //to store issue / bug id. 35 | 36 | HttpClient httpClient = HttpClientBuilder.create().build(); 37 | String url = jiraURL+"/rest/api/3/issue"; 38 | HttpPost postRequest = new HttpPost(url); 39 | postRequest.addHeader("content-type", "application/json"); 40 | 41 | // BASE64Encoder base=new BASE64Encoder(); 42 | String encoding = Base64.getEncoder().encodeToString((jiraUserName+":"+jiraAccessKey).getBytes()); 43 | //String encoding = base.encode((jiraUserName+":"+jiraAccessKey).getBytes()); 44 | postRequest.setHeader("Authorization", "Basic " + encoding); 45 | 46 | StringEntity params = new StringEntity(createPayloadForCreateJiraIssue(ProjectName, issueSummary, issueDescription, component, priority, label, env, assignee)); 47 | postRequest.setEntity(params); 48 | HttpResponse response = httpClient.execute(postRequest); 49 | 50 | //convert httpresponse to string 51 | String jsonString = EntityUtils.toString(response.getEntity()); 52 | 53 | //convert sring to Json 54 | JSONParser parser = new JSONParser(); 55 | JSONObject json = (JSONObject) parser.parse(jsonString); 56 | 57 | //extract issuekey from Json 58 | issueId = (String) json.get("key"); 59 | 60 | return issueId; 61 | 62 | } 63 | 64 | //Add attachment to already created bug / issue in JIRA 65 | public void addAttachmentToJiraIssue(String issueId, String filePath) throws ClientProtocolException, IOException 66 | { 67 | String pathname= filePath; 68 | File fileUpload = new File(pathname); 69 | 70 | HttpClient httpClient = HttpClientBuilder.create().build(); 71 | String url = jiraURL+"/rest/api/3/issue/"+issueId+"/attachments"; 72 | HttpPost postRequest = new HttpPost(url); 73 | 74 | //BASE64Encoder base=new BASE64Encoder(); 75 | //String encoding = base.encode((jiraUserName+":"+jiraAccessKey).getBytes()); 76 | String encoding = Base64.getEncoder().encodeToString((jiraUserName+":"+jiraAccessKey).getBytes()); 77 | 78 | postRequest.setHeader("Authorization", "Basic " + encoding); 79 | postRequest.setHeader("X-Atlassian-Token","nocheck"); 80 | 81 | MultipartEntityBuilder entity=MultipartEntityBuilder.create(); 82 | entity.addPart("file", new FileBody(fileUpload)); 83 | postRequest.setEntity( entity.build()); 84 | HttpResponse response = httpClient.execute(postRequest); 85 | System.out.println(response.getStatusLine()); 86 | 87 | if(response.getStatusLine().toString().contains("200 OK")){ 88 | System.out.println("Attachment uploaded"); 89 | } else{ 90 | System.out.println("Attachment not uploaded"); 91 | } 92 | } 93 | 94 | //creates payload for create issue post request 95 | private static String createPayloadForCreateJiraIssue(String ProjectName, String issueSummary, String issueDescription, String componentId, String priority, String label, String env, String assigneeId) { 96 | return "{\r\n" + 97 | " \"fields\": {\r\n" + 98 | " \"project\":\r\n" + 99 | " {\r\n" + 100 | " \"key\": \""+ProjectName+"\"\r\n" + 101 | " },\r\n" + 102 | " \"summary\": \""+issueSummary+"\",\r\n" + 103 | " \"description\": {\r\n" + 104 | " \"type\": \"doc\",\r\n" + 105 | " \"version\": 1,\r\n" + 106 | " \"content\": [\r\n" + 107 | " {\r\n" + 108 | " \"type\": \"paragraph\",\r\n" + 109 | " \"content\": [\r\n" + 110 | " {\r\n" + 111 | " \"text\": \""+issueDescription+"\",\r\n" + 112 | " \"type\": \"text\"\r\n" + 113 | " }\r\n" + 114 | " ]\r\n" + 115 | " }\r\n" + 116 | " ]\r\n" + 117 | " }, \r\n" + 118 | " \"issuetype\": {\r\n" + 119 | " \"name\": \"Bug\"\r\n" + 120 | " },\r\n" + 121 | " \"components\": [\r\n" + 122 | " {\r\n" + 123 | " \"id\": \""+componentId+"\"\r\n" + 124 | " }\r\n" + 125 | " ],\r\n" + 126 | " \"priority\": {\r\n" + 127 | " \"id\": \""+priority+"\"\r\n" + 128 | " },\r\n" + 129 | " \"labels\": [\r\n" + 130 | " \""+label+"\"\r\n" + 131 | " ],\r\n" + 132 | " \"environment\": {\r\n" + 133 | " \"type\": \"doc\",\r\n" + 134 | " \"version\": 1,\r\n" + 135 | " \"content\": [\r\n" + 136 | " {\r\n" + 137 | " \"type\": \"paragraph\",\r\n" + 138 | " \"content\": [\r\n" + 139 | " {\r\n" + 140 | " \"text\": \""+env+"\",\r\n" + 141 | " \"type\": \"text\"\r\n" + 142 | " }\r\n" + 143 | " ]\r\n" + 144 | " }\r\n" + 145 | " ]\r\n" + 146 | " },\r\n" + 147 | " \"assignee\": {\r\n" + 148 | " \"id\": \""+assigneeId+"\"\r\n" + 149 | " }\r\n" + 150 | "}\r\n" + 151 | "}"; 152 | } 153 | 154 | 155 | } 156 | 157 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/ListenersImplementation.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | 8 | import org.apache.commons.io.FileUtils; 9 | import org.apache.http.client.ClientProtocolException; 10 | import org.json.simple.parser.ParseException; 11 | import org.openqa.selenium.OutputType; 12 | import org.openqa.selenium.TakesScreenshot; 13 | import org.testng.ITestContext; 14 | import org.testng.ITestListener; 15 | import org.testng.ITestResult; 16 | 17 | import com.aventstack.extentreports.ExtentReports; 18 | import com.aventstack.extentreports.ExtentTest; 19 | import com.aventstack.extentreports.Status; 20 | 21 | import testBase.DriverFactory; 22 | import testBase.ExtentFactory; 23 | import testBase.ExtentReportNG; 24 | 25 | /** 26 | * @author: Prakash Narkhede 27 | * @Youtube: https://www.youtube.com/automationtalks 28 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 29 | */ 30 | public class ListenersImplementation implements ITestListener{ 31 | JiraOperations jiraOps = new JiraOperations(); 32 | static ExtentReports report; 33 | ExtentTest test; 34 | 35 | public void onTestStart(ITestResult result) { 36 | //before each test case 37 | test = report.createTest(result.getMethod().getMethodName()); 38 | ExtentFactory.getInstance().setExtent(test); 39 | } 40 | 41 | public void onTestSuccess(ITestResult result) { 42 | ExtentFactory.getInstance().getExtent().log(Status.PASS, "Test Case: "+result.getMethod().getMethodName()+ " is Passed."); 43 | ExtentFactory.getInstance().removeExtentObject(); 44 | } 45 | 46 | public void onTestFailure(ITestResult result) { 47 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, "Test Case: "+result.getMethod().getMethodName()+ " is Failed."); 48 | ExtentFactory.getInstance().getExtent().log(Status.FAIL, result.getThrowable()); 49 | 50 | //add screenshot for failed test. 51 | File src = ((TakesScreenshot)DriverFactory.getInstance().getDriver()).getScreenshotAs(OutputType.FILE); 52 | SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyy HH-mm-ss"); 53 | Date date = new Date(); 54 | String actualDate = format.format(date); 55 | 56 | String screenshotPath = System.getProperty("user.dir")+ 57 | "/Reports/Screenshots/"+actualDate+".jpeg"; 58 | File dest = new File(screenshotPath); 59 | 60 | try { 61 | FileUtils.copyFile(src, dest); 62 | } catch (IOException e) { 63 | e.printStackTrace(); 64 | } 65 | try { 66 | ExtentFactory.getInstance().getExtent().addScreenCaptureFromPath(screenshotPath, "Test case failure screenshot"); 67 | ExtentFactory.getInstance().removeExtentObject(); 68 | 69 | } catch (IOException e) { 70 | e.printStackTrace(); 71 | } 72 | ///////JIRA defect creation part 73 | String automaticJIRAcreation = PropertiesOperations.getPropertyValueByKey("automatic_Issue_Creation_In_JIRA"); 74 | if(automaticJIRAcreation.trim().equalsIgnoreCase("ON")) { 75 | String issueS = "Automation Test Failed - "+result.getMethod().getMethodName(); 76 | String issueD = "Test Data to be passed here."; 77 | String issueNumber = null; 78 | try { 79 | issueNumber = jiraOps.createJiraIssue("QDPM", issueS, issueD, "10000", "5", "QDPM", "SIT", "5f782c4b95fe8e0069705791"); 80 | } catch (Exception e1) { 81 | e1.printStackTrace(); 82 | } 83 | try { 84 | jiraOps.addAttachmentToJiraIssue(issueNumber, screenshotPath); 85 | } catch (Exception e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | 90 | } 91 | 92 | public void onTestSkipped(ITestResult result) { 93 | ExtentFactory.getInstance().getExtent().log(Status.SKIP, "Test Case: "+result.getMethod().getMethodName()+ " is skipped."); 94 | ExtentFactory.getInstance().removeExtentObject(); 95 | } 96 | 97 | public void onTestFailedButWithinSuccessPercentage(ITestResult result) { 98 | } 99 | 100 | public void onTestFailedWithTimeout(ITestResult result) { 101 | } 102 | 103 | public void onStart(ITestContext context) { 104 | try { 105 | report = ExtentReportNG.setupExtentReport(); 106 | } catch (Exception e) { 107 | e.printStackTrace(); 108 | } 109 | } 110 | 111 | public void onFinish(ITestContext context) { 112 | //close extent 113 | report.flush(); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/PropertiesOperations.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | /** 4 | * @author: Prakash Narkhede 5 | * @Youtube: https://www.youtube.com/automationtalks 6 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 7 | */ 8 | 9 | import java.io.FileInputStream; 10 | import java.util.Properties; 11 | 12 | import org.apache.commons.lang3.StringUtils; 13 | 14 | public class PropertiesOperations { 15 | 16 | 17 | static Properties prop = new Properties(); 18 | 19 | public static String getPropertyValueByKey(String key) { 20 | //1. load data from properties file 21 | String propFilePath = System.getProperty("user.dir")+"/src/test/resources/config.properties"; 22 | FileInputStream fis; 23 | try { 24 | fis = new FileInputStream(propFilePath); 25 | prop.load(fis); 26 | } catch (Exception e) { 27 | e.printStackTrace(); 28 | } 29 | 30 | //2. read data 31 | String value = prop.get(key).toString(); 32 | 33 | if(StringUtils.isEmpty(value)) { 34 | try { 35 | throw new Exception("Value is not specified for key: "+key + " in properties file."); 36 | }catch(Exception e) {} 37 | } 38 | 39 | return value; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/reusableComponents/TestRetryAnalyzer.java: -------------------------------------------------------------------------------- 1 | package reusableComponents; 2 | 3 | import org.testng.IRetryAnalyzer; 4 | import org.testng.ITestResult; 5 | 6 | /** 7 | * @author: Prakash Narkhede 8 | * @Youtube: https://www.youtube.com/automationtalks 9 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 10 | */ 11 | public class TestRetryAnalyzer implements IRetryAnalyzer { 12 | 13 | int counter = 1; 14 | int retryMaxLimit = Integer.valueOf(PropertiesOperations.getPropertyValueByKey("retryCount")); 15 | 16 | @Override 17 | public boolean retry(ITestResult result) { 18 | if(counter define separate factory methods for creating objects and create objects by calling that methods 26 | ThreadLocal driver = new ThreadLocal(); 27 | 28 | public WebDriver getDriver() { 29 | return driver.get(); 30 | } 31 | 32 | public void setDriver(WebDriver driverParm) { 33 | driver.set(driverParm); 34 | } 35 | 36 | 37 | public void closeBrowser() { 38 | driver.get().quit(); 39 | driver.remove(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/testBase/ExtentFactory.java: -------------------------------------------------------------------------------- 1 | package testBase; 2 | 3 | import com.aventstack.extentreports.ExtentTest; 4 | 5 | /** 6 | * @author: Prakash Narkhede 7 | * @Youtube: https://www.youtube.com/automationtalks 8 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 9 | */ 10 | public class ExtentFactory { 11 | //Singleton design Pattern 12 | //private constructor so that no one else can create object of this class 13 | private ExtentFactory() { 14 | 15 | } 16 | 17 | private static ExtentFactory instance = new ExtentFactory(); 18 | 19 | public static ExtentFactory getInstance() { 20 | return instance; 21 | } 22 | 23 | 24 | //factory design pattern --> define separate factory methods for creating objects and create objects by calling that methods 25 | ThreadLocal extent = new ThreadLocal(); 26 | 27 | public ExtentTest getExtent() { 28 | return extent.get(); 29 | } 30 | 31 | public void setExtent(ExtentTest extentTestObject) { 32 | extent.set(extentTestObject); 33 | } 34 | 35 | public void removeExtentObject() { 36 | extent.remove(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/testBase/ExtentReportNG.java: -------------------------------------------------------------------------------- 1 | package testBase; 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.Theme; 9 | 10 | import reusableComponents.PropertiesOperations; 11 | 12 | /** 13 | * @author: Prakash Narkhede 14 | * @Youtube: https://www.youtube.com/automationtalks 15 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 16 | */ 17 | public class ExtentReportNG { 18 | 19 | static ExtentReports extent; 20 | 21 | public static ExtentReports setupExtentReport() throws Exception { 22 | SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyy HH-mm-ss"); 23 | Date date = new Date(); 24 | String actualDate = format.format(date); 25 | 26 | String reportPath = System.getProperty("user.dir")+ 27 | "/Reports/ExecutionReport_"+actualDate+".html"; 28 | 29 | ExtentSparkReporter sparkReport = new ExtentSparkReporter(reportPath); 30 | 31 | extent = new ExtentReports(); 32 | extent.attachReporter(sparkReport); 33 | 34 | sparkReport.config().setDocumentTitle("DocumentTitle"); 35 | sparkReport.config().setTheme(Theme.DARK); 36 | sparkReport.config().setReportName("ReportName"); 37 | 38 | extent.setSystemInfo("Executed on Environment: ", PropertiesOperations.getPropertyValueByKey("url")); 39 | extent.setSystemInfo("Executed on Browser: ", PropertiesOperations.getPropertyValueByKey("browser")); 40 | extent.setSystemInfo("Executed on OS: ", System.getProperty("os.name")); 41 | extent.setSystemInfo("Executed by User: ", System.getProperty("user.name")); 42 | 43 | return extent; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/testBase/MyLogger.java: -------------------------------------------------------------------------------- 1 | package testBase; 2 | 3 | import java.io.File; 4 | 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.apache.logging.log4j.ThreadContext; 8 | 9 | /** 10 | * @author: Prakash Narkhede 11 | * @Youtube: https://www.youtube.com/automationtalks 12 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 13 | */ 14 | public class MyLogger { 15 | 16 | private static Logger logger = LogManager.getLogger(); 17 | 18 | public static synchronized void startTestCase(String sTestCaseName) { 19 | sTestCaseName = sTestCaseName.replaceAll("[^a-zA-Z0-9]", "_").replaceAll("_+", "_"); 20 | startLog(System.getProperty("user.dir"), sTestCaseName); 21 | info("\n\n************** Execution Started : " + sTestCaseName + "**************\n"); 22 | } 23 | 24 | public static void endTestCase(String sTestCaseName) { 25 | info("\n\n************** Execution End : " + sTestCaseName + "**************\n"); 26 | } 27 | 28 | private static void startLog(String dirPath, String testCaseName) { 29 | 30 | int noOfFiles = 0; 31 | 32 | File dir = new File(dirPath); 33 | if (dir.exists()) { 34 | int count = 0; 35 | for (File file : dir.listFiles()) { 36 | if (file.isFile() && file.getName().endsWith(".log") && file.getName().contains(testCaseName)) { 37 | count++; 38 | } 39 | } 40 | noOfFiles = count; 41 | } 42 | 43 | noOfFiles++; 44 | String logFileName = testCaseName + "_" + noOfFiles; 45 | 46 | ThreadContext.put("logFilename", logFileName); 47 | } 48 | 49 | public static Logger getCurrentLog() { 50 | return logger; 51 | } 52 | 53 | public static String getCallInfo() { 54 | 55 | String callInfo; 56 | String className = Thread.currentThread().getStackTrace()[3].getClassName(); 57 | String methodName = Thread.currentThread().getStackTrace()[3].getMethodName(); 58 | int lineNumber = Thread.currentThread().getStackTrace()[3].getLineNumber(); 59 | 60 | callInfo = className + ":" + methodName + " " + lineNumber+ "==> "; 61 | return callInfo; 62 | 63 | } 64 | 65 | public static void trace(Object message) { 66 | getCurrentLog().trace(message); 67 | } 68 | 69 | public static void trace(Object message, Throwable t) { 70 | getCurrentLog().trace(message, t); 71 | } 72 | 73 | public static void debug(Object message) { 74 | 75 | getCurrentLog().debug(getCallInfo() + message); 76 | } 77 | 78 | public static void debug(Object message, Throwable t) { 79 | getCurrentLog().debug(getCallInfo() + message, t); 80 | } 81 | 82 | public static void error(Object message) { 83 | 84 | getCurrentLog().error(getCallInfo() + message); 85 | } 86 | 87 | public static void error(Object message, Throwable t) { 88 | getCurrentLog().error(getCallInfo() + message, t); 89 | } 90 | 91 | public static void fatal(Object message) { 92 | getCurrentLog().fatal(getCallInfo() + message); 93 | } 94 | 95 | public static void fatal(Object message, Throwable t) { 96 | getCurrentLog().fatal(getCallInfo() + message, t); 97 | } 98 | 99 | public static void info(Object message) { 100 | 101 | getCurrentLog().info(getCallInfo() + message); 102 | } 103 | 104 | public static void info(Object message, Throwable t) { 105 | getCurrentLog().info(getCallInfo() + message, t); 106 | } 107 | 108 | public static void warn(Object message) { 109 | getCurrentLog().warn(getCallInfo() + message); 110 | } 111 | 112 | public static void warn(Object message, Throwable t) { 113 | getCurrentLog().warn(getCallInfo() + message, t); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/testBase/TestBase.java: -------------------------------------------------------------------------------- 1 | package testBase; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import org.testng.annotations.AfterMethod; 6 | import org.testng.annotations.BeforeMethod; 7 | 8 | import reusableComponents.ActionEngine; 9 | import reusableComponents.PropertiesOperations; 10 | 11 | /** 12 | * @author: Prakash Narkhede 13 | * @Youtube: https://www.youtube.com/automationtalks 14 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 15 | */ 16 | public class TestBase extends ActionEngine { 17 | BrowserFactory bf = new BrowserFactory(); 18 | 19 | @BeforeMethod 20 | public void LaunchApplication() throws Exception { 21 | String browser = PropertiesOperations.getPropertyValueByKey("browser"); 22 | String url = PropertiesOperations.getPropertyValueByKey("url"); 23 | 24 | DriverFactory.getInstance().setDriver(bf.createBrowserInstance(browser)); 25 | 26 | DriverFactory.getInstance().getDriver().manage().window().maximize(); 27 | DriverFactory.getInstance().getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 28 | DriverFactory.getInstance().getDriver().navigate().to(url); 29 | 30 | } 31 | 32 | @AfterMethod 33 | public void tearDown() { 34 | DriverFactory.getInstance().closeBrowser(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/test/java/Tests/TestCase.java: -------------------------------------------------------------------------------- 1 | package Tests; 2 | 3 | import java.util.HashMap; 4 | 5 | import org.testng.annotations.DataProvider; 6 | import org.testng.annotations.Test; 7 | import pageObjects.HomePageObjects; 8 | import pageObjects.LoginPageObjects; 9 | import pageObjects.TaskPageObjects; 10 | import reusableComponents.DB_Operations; 11 | import reusableComponents.ExcelOperations; 12 | import testBase.ExtentFactory; 13 | import testBase.TestBase; 14 | 15 | /** 16 | * @author: Prakash Narkhede 17 | * @Youtube: https://www.youtube.com/automationtalks 18 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 19 | */ 20 | 21 | public class TestCase extends TestBase{ 22 | LoginPageObjects loginPage = new LoginPageObjects(); 23 | HomePageObjects homePage = new HomePageObjects(); 24 | TaskPageObjects taskPage = new TaskPageObjects(); 25 | DB_Operations dbOps = new DB_Operations(); 26 | 27 | ExcelOperations excel = new ExcelOperations("TaskCreationData"); 28 | 29 | @Test(dataProvider = "taskCreationData") 30 | public void TaskCreationTest(Object obj1) throws Throwable { 31 | @SuppressWarnings("unchecked") 32 | HashMap testData = (HashMap) obj1; 33 | 34 | ExtentFactory.getInstance().getExtent().info("Test Data for this execution run is: "+ testData); 35 | 36 | loginPage.login(testData.get("UserName"), testData.get("Password")); 37 | //check if dashboard page opens 38 | homePage.checkIfDashBoardPageIsOpened(); 39 | homePage.clickOnSideSubMenu("Tasks", "Add Task"); 40 | //add task 41 | taskPage.createTask(testData); 42 | //verify task on UI 43 | taskPage.Search_Verify_TaskCreationOnUI(testData); 44 | 45 | //verify DB 46 | String sql = "SELECT * FROM `tasks` where name = '"+testData.get("TaskName")+"'"; 47 | HashMap dbData = dbOps.getSqlResultInMap(sql); 48 | String TaskName = dbData.get("name"); 49 | assertEqualsString_custom("taskFailureName", TaskName, "DB_Task_Name"); 50 | 51 | 52 | } 53 | 54 | //Dataprovider method --> return object array 55 | @DataProvider (name = "taskCreationData") 56 | public Object[][] testDataSupplier() throws Exception { 57 | Object[][] obj = new Object[excel.getRowCount()][1]; 58 | for (int i = 1; i <= excel.getRowCount(); i++) { 59 | HashMap testData = excel.getTestDataInMap(i); 60 | obj[i-1][0] = testData; 61 | } 62 | return obj; 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/Tests/UserLoginTests.java: -------------------------------------------------------------------------------- 1 | package Tests; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import pageObjects.LoginPageObjects; 6 | import testBase.TestBase; 7 | 8 | /** 9 | * @author: Prakash Narkhede 10 | * @Youtube: https://www.youtube.com/automationtalks 11 | * @LinkedIn: https://www.linkedin.com/in/panarkhede89/ 12 | */ 13 | @Test 14 | public class UserLoginTests extends TestBase{ 15 | LoginPageObjects loginPage = new LoginPageObjects(); 16 | 17 | 18 | public void ManagerLoginTest() throws Throwable { 19 | 20 | loginPage.login("manager@localhost.com", "admin@123"); 21 | Thread.sleep(2000); ////// not required, adding just to see tests are running in parallel 22 | 23 | 24 | } 25 | public void ClientLoginTest() throws Throwable { 26 | 27 | loginPage.login("client@localhost.com", "admin@123"); 28 | Thread.sleep(2000); ////// not required, adding just to see tests are running in parallel 29 | 30 | } 31 | public void DesignerLoginTest() throws Throwable { 32 | 33 | loginPage.login("designer@localhost.com", "admin@123"); 34 | Thread.sleep(2000); ////// not required, adding just to see tests are running in parallel 35 | assertEqualsString_custom("ExpectedTest", "ActualText", "LoginPageHomePage"); 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/resources/config.properties: -------------------------------------------------------------------------------- 1 | browser= firefox 2 | url=http://192.168.225.219:8090/index.php/login 3 | testDataLocation = //src//test//resources//testData//TaskCreationTestData.xlsx 4 | 5 | 6 | retryCount=0 7 | 8 | ### ON or OFF 9 | automatic_Issue_Creation_In_JIRA=OFF 10 | 11 | ##### jira issues creation Credentials 12 | jiraURL=https://automationtalks.atlassian.net 13 | jiraUserName=prakashnarkhede89@gmail.com 14 | jiraSecretKey=1axLRL9dNZvN0R3FIzGh6354 -------------------------------------------------------------------------------- /src/test/resources/testData/TaskCreationTestData.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prakashnarkhede/Advanced_Selenium_Test_Automation_Framework/87ffe6e3b1a08da28e95fa950a7b5b48c7ba8d7f/src/test/resources/testData/TaskCreationTestData.xlsx -------------------------------------------------------------------------------- /testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------