Cucumber #Before hook runs twice #After once - selenium-webdriver

to all.
Curently writing a little BDD Test automation framework, using Java11+Junit5+Cucumber+Selenium, build tool: Graddle. Created a little test for validating Google title. When starting test, using Test task in Graddle or running CucumberRunner class, in both cases getting the same result: two times #Before method is executed, once #After method is executed and one browser windows is staying open. After added one more test, the same situation, only 4 browsers are opened, 2 of them are closing. Can anyone help with this situation?
Link to repository
After some watching of logs saw, that, seems, #Before is not executed twice, but Driver class is initialized twice, but why it happens no idea for now...
My code for now:
CucumberRunner.java:
#RunWith(Cucumber.class )
#CucumberOptions(
features = "src\\test\\java\\features",
glue = {"steps", "utils"},
tags = "#smoke")
public class CucumberRunner {
}
Driver.java:
public class Driver {
private WebDriver driver;
public Driver(){
driverInitialization();
}
private void driverInitialization(){
System.setProperty("webdriver.chrome.driver", "D:\\Soft\\selenium-drivers\\chromedriver.exe");
System.out.println("Starting driver.");
var browserName = "chrome";
switch (browserName.toLowerCase()){
case "chrome":
System.out.println("Starting chrome");
driver = new ChromeDriver();
System.out.println("Before break.");
break;
case "firefox":
driver = new FirefoxDriver();
break;
default:
throw new NotFoundException("Browser not found: " + browserName);
}
}
public WebDriver getDriver(){
return driver;
}
public WebDriverWait getWebDriverWait(){
return new WebDriverWait(driver, 120);
}
public void terminateDriver(){
System.out.println("Terminating driver.");
if (driver != null) {
driver.close();
driver.quit();
}
}
}
Hooks.java:
public class Hooks {
private Driver driver;
#Before
public void setup(){
System.out.println("In the Setup method.");
driver = new Driver();
}
#After
public void tearDown(){
System.out.println("In the TearDown method.");
driver.terminateDriver();
}
}

I think your Hook Class should be like this As You Are Using selenium-picocontainer DI.
public class Hooks {
private Driver driver;
public Hooks(Driver driver) {
this.driver = driver;
}
#Before
public void setup(){
System.out.println("In the Setup method.");
}
#After
public void tearDown(){
System.out.println("In the TearDown method.");
driver.terminateDriver();
}
}

Related

Getting InstantiationException when creating factory for a page using appium

I am running a test case using pagefactory method and have created an appium driver. I'm trying to initialising a page using pagefactory class like this:
The test class:
public class VerifyValidLogin {
#Test
public void CheckValidUser() throws MalformedURLException {
AppiumDriver driver = DeviceFactory.CreateDriver();
login login_page = PageFactory.initElements(driver, login.class);
}
}
DeviceFactory class:
public class DeviceFactory {
public static AppiumDriver<MobileElement> driver;
public static AppiumDriver CreateDriver() throws MalformedURLException {
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability( capabilityName: 'deviceName', value: 'Something');
...
URL url = new URL("http://127.0.0.1:4723/wd/hub");
driver = new AppiumDriver<MobileElement>(url,cap);
System.out.print("Application started");
return driver;
}
}
Login class has element locators:
public class login {
AppiumDriver driver;
public login(AppiumDriver ldriver)
{
this.driver=ldriver;
}
#FindBy(how = How.XPATH,using ="xpath");
MobileElement SignInButton;
}
But i'm not sure where i am doing wrong.
The error is
java.lang.RuntimeException: java.lang.InstantiationException: com.Demo.pages.login
at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:134)
at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:64)
at com.Demo.Testcases.VerifyValidLogin.CheckValidUser(VerifyValidLogin.java:18)
...
I am new to the automation testing so i'm not able to properly understand the error. Let me know if you need more details.
Initialise elements in constructor
public login(AppiumDriver ldriver)
{
this.driver=ldriver;
PageFactory.initElements(ldriver,this);
}

How to handle multiple step definition file in Cucumber with Selenium

I have two step definition files and in future, there will be multiple, I am unable to execute my code for logout, its working fine for login and one step definition file, and it continuously open chrome browser.
I have created a framework using page factory, below is my code:
Login Page:
public class LoginPage {
WebDriver driver;
public LoginPage(WebDriver driver) {
//this.driver=driver;
PageFactory.initElements(driver, this);
}
#FindBy(how=How.ID,using="username")
public WebElement usernametexbox;
#FindBy(how=How.ID,using="pass")
public WebElement passwordtextbox;
#FindBy(how=How.ID,using="submit")
public WebElement signin;
#FindBy(how=How.XPATH,using="//button[#class='btn']")
public WebElement acceptbutton;
public void enter_username(String username) {
usernametexbox.clear();
usernametexbox.sendKeys(username);
usernametexbox.getText();
}
public void enter_password(String password) {
passwordtextbox.clear();
passwordtextbox.sendKeys(password);
}
public void clickToSigninbutton() {
signin.click();
}
public void clickToAcceptbutton() {
acceptbutton.click();
}
public void fill_LoginDetails() {
enter_username("abc");
enter_password("def45");
}
}
Logout Page:
public class LogoutPage {
WebDriver driver;
public LogoutPage(WebDriver driver) {
//this.driver=driver;
PageFactory.initElements(driver, this);
}
#FindBy(how=How.XPATH,using="//*[#class='icon']")
public WebElement chevron;
#FindBy(how=How.XPATH,using="//a[#class='logout-link']")
public WebElement logoutlink;
public void clickTochevron() {
chevron.click();
}
public void clickToLogoutLink() {
link.click();
}
}
Property file reader:
public class PropertiesFileReader {
public Properties getproperty() throws IOException {
FileInputStream inputstream=null;
Properties properties=new Properties();
try {
properties.load(new FileInputStream("resources/config.properties"));
}catch(Exception e) {
System.out.println("Exception " +e);
}
return properties;
}
}
Browser utility:
public class BrowserUtility {
public static WebDriver openBrowser(WebDriver driver, String browserName, String url) throws InterruptedException {
if(browserName.equals("chrome")) {
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver\\chromedriver.exe");
driver=new ChromeDriver();
driver.manage().window().maximize();
driver.get(url);
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
return driver;
}else if(browserName.equals("IE")) {
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver\\chromedriver.exe");
driver=new ChromeDriver();
driver.manage().window().maximize();
driver.get(url);
Thread.sleep(5000);
return driver;
}else if(browserName.equals("Firefox")) {
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver\\chromedriver.exe");
driver=new ChromeDriver();
driver.manage().window().maximize();
driver.get(url);
Thread.sleep(5000);
return driver;
}
return driver;
}
}
Login Stepdef:
public class StepDefinition {
public static WebDriver driver;
// public LoginPage loginpage;
// Properties properties=new Properties();
PropertiesFileReader obj=new PropertiesFileReader();
#Given("^Open browser and enter url$")
public void open_browser_and_enter_url() throws Throwable {
Properties properties=obj.getproperty();
driver= BrowserUtility.openBrowser(driver, properties.getProperty("browser.Name"), properties.getProperty("URL"));
}
#Then("^Enter username and password$")
public void enter_username_and_password() throws Throwable {
LoginPage loginpage=new LoginPage(driver);
loginpage.fill_LoginDetails();
}
#Then("^click on sign in button$")
public void click_on_sign_in_button() throws Throwable {
new LoginPage(driver).clickToSigninbutton();
System.out.println("Sign-In successfully");
}
#Then("^Terms and conditions page open and click on Accept button$")
public void terms_and_conditions_page_open_and_click_on_Accept_button() throws Throwable {
new LoginPage(driver).clickToAcceptbutton();
}
}
Logout stepdef:
public class Logoutstepdef {
public static WebDriver driver;
PropertiesFileReader obj=new PropertiesFileReader();
#Given("^Chevron near username$")
public void chevron_near_username() throws Throwable {
Properties properties=obj.getproperty();
driver= BrowserUtility.openBrowser(driver,
properties.getProperty("browser.Name"), properties.getProperty("URL"));
LogoutPage logoutpage=new LogoutPage(driver);
logoutpage.clickTochevron();
}
#Then("^click on chevron and it should get expands$")
public void click_on_chevron_and_it_should_get_expands() throws
Throwable {
System.out.println("when user click on checvron it should
further expands a window");
}
#Then("^click on Logout link$")
public void click_on_Logout_link() throws Throwable {
new LogoutPage(driver).clickToLogoutLink();
}
}
Expected Results: Application should get automated successfully for different step definition files and only one browser should get opened at a time.
Actual Results: I have two step definition file and in future there will be multiple, I am unable to execute my code for logout, its working fine for login and one step definition file, and it continuously open chrome browser.
Your Then step is creating another instance of the page, that's why you get multiple browsers open.
Try doing this in your Logoutstepdef class:
public class Logoutstepdef {
public static WebDriver driver;
PropertiesFileReader obj=new PropertiesFileReader();
private LogoutPage logoutpage;
.....//the rest remains the same, until:
#Then("^click on Logout link$")
public void click_on_Logout_link() throws Throwable {
logoutpage.clickToLogoutLink();
}
}
There are similar questions here and here.
i would suggest to try gherkin with qaf. With QAF you don't need to manage driver or don't need to worry about page. All you need to extend WebdriverTestPage to your page class and you are done. You also can have steps in Page class itself. For example, with qaf your logout page may look like below:
public class LogoutPage extends WebDriverBaseTestPage<WebDriverTestPage>{
#FindBy(locator="xpath=//*[#class='icon']")
public WebElement chevron;
#FindBy(locator="xpath=//a[#class='logout-link']")
public WebElement logoutlink;
public void clickTochevron() {
chevron.click();
}
//#Then("^click on Logout link$") //you can use cucumber or qaf step annotation
#QAFTestStep(description="click on Logout link")
public void clickToLogoutLink() {
link.click();
}
}
Browser management (opening/closing browser) is taken care by QAF so depending on your configuration (sequential/parallel) qaf will provide thread safe drive sessions.
Furthermore, with locator repository you can eliminate one layer of page class. There are in-built steps available you can directly use. For example:
logoutpage.propeties
chevron.icon.loc=xpath=//*[#class='icon']
logout.link.loc=xpath=//a[#class='logout-link']
in your BDD you can directly use in-built steps as below:
Scenario: name of scenario
Given ...
When ...
Then verify 'chevron.icon.loc' is present
And click on 'logout.link.loc'
To make your locator self descriptive, you can go one step ahead as below:
logout.link.loc=xpath={"locator":"//a[#class='logout-link']","desc":"logout button"}
The description will be used in reporting to make it more meaningful.
There are lots of other feature that are crucial for functional test automation.

How to solve error: Cannot Focus element - keyword driven framework in Selenium

I am using Keyword driven framework for automate Log in page for one of the site. here I have used Poi for accessing the Excel sheet Data.
Here Below method openBrowser() and openUrl() are working fine. Problem happened for username() method for accessing the username field. I am using Selenium 3.12 and Chrome driver version 2.39 compatible with Chorme
Here is my code :
public class ActionKeywords {
public static WebDriver driver;
public static void openBrowser(){
System.setProperty("webdriver.chrome.driver","E:\\Pratik_BackUP\\Automation Selenium\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
System.out.println("open Browser called");
}
public static void openUrl(){
driver.manage().timeouts().implicitlyWait(100,TimeUnit.SECONDS);
driver.get("correct url");
driver.manage().window().maximize();
System.out.println("open Url called");
}
public static void userName(){
driver.findElement(By.xpath(".//*[#id='ctl00_ContentPlaceHolder1_login1_pan']/div/table/tbody/tr[3]/td[1]")).sendKeys("admin");
System.out.println("user Name called");
}
public static void password(){
driver.findElement(By.xpath(".//*[#id='ctl00_ContentPlaceHolder1_login1_pan']/div/table/tbody/tr[4]/td[1]")).sendKeys("Camlin#357");
System.out.println("password called");
}
public static void click_Login(){
driver.findElement(By.xpath(".//*[#id='ctl00_ContentPlaceHolder1_login1_LoginButton']")).click();
System.out.println("LogIn called");
}
public static void waitFor() throws Exception{
Thread.sleep(5000);
}
public static void closeBrowser(){
driver.quit();
System.out.println("close Browser called.");
}
}
Thanks!!
public static void userName(){
WebElement exelement = driver.findElement(By.xpath(".//*[#id='ctl00_ContentPlaceHolder1_login1_UserName']"));
exelement.clear();
Actions actions = new Actions(driver);
actions.moveToElement(exelement);
actions.click();
actions.sendKeys("admin");
actions.build().perform();
}
Above code works fine. Here have used Actions class for solve Actions class

Page Objects erro (java.lang.NullPointerException)

I did a basic project to training about Page Objects using selenium WebDriver with java and Junit. So, I make a page object class and Junit class too. I Make a call of method and pass the parameters to method but, the eclipse show a message that say: java.lang.NullPointerException
public class LogarBkoMaisPage {
static WebDriver driver;
By campoNome = By.id("matricula_I");
By campoSenha = By.id("senha_I");
By btnLogin = By.id("bt_entrar");
public LogarBkoMaisPage(WebDriver driver) {
this.driver = driver;
}
public void logar(String usuario, String senha) {
driver.findElement(campoNome).sendKeys(usuario);
driver.findElement(campoSenha).sendKeys(senha);
driver.findElement(btnLogin).click();
}
}
public class LogarBkoMaisTest {
static WebDriver driver;
#Before
public void setUp() throws Exception {
SelecionarNavegador nav = new SelecionarNavegador();
nav.iniciarNavegador("ie","http://10.5.9.45/BkoMais_Selenium/");
}
#Test
public void logarAplicacao() {
try {
LogarBkoMaisPage login = new LogarBkoMaisPage(driver);
login.logar("844502","Bcc201707");
}catch(Exception e) {
System.out.println("Mensagem de erro: " +e);
}
}
#After
public void tearDown() throws Exception {
}
}
public class SelecionarNavegador {
static WebDriver driver;
public static WebDriver iniciarNavegador(String nomeNavegador, String url) {
if(nomeNavegador.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.gecko.driver", "E:\\workspace_BCC_QA_BKOMAIS\\"
+ "FireFoxGeckodriver64\\geckodriver.exe");
driver = new FirefoxDriver();
}
else if(nomeNavegador.equalsIgnoreCase("chrome")){
System.setProperty("webdriver.chrome.driver", "E:\\workspace_BCC_QA_BKOMAIS"
+ "\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
}else if(nomeNavegador.equalsIgnoreCase("IE")) {
System.setProperty("webdriver.ie.driver", "E:\\workspace_BCC_QA_BKOMAIS"
+ "\\IE Plugin\\IEDriverServer.exe");
driver = new InternetExplorerDriver();
}
driver.manage().window().maximize();
driver.get(url);
return driver;
}
}
Exception:
You are getting a null pointer exception because iniciarNavegador method inside SelecionarNavegador class is the one which initializes the driver and it returns the driver which has to be assigned to a vairable. You need to do this in your setUp()method
#Before
public void setUp() throws Exception {
SelecionarNavegador nav = new SelecionarNavegador();
driver=nav.iniciarNavegador("ie","http://10.5.9.45/BkoMais_Selenium/");
}

Null pointer exception for Extent Report

It wouldbe silly question but would be great help it you can help me out.
I tried implementing extent report for multple test cases, but report are not getting generated .
Code:
public class SampleTc1
{
static WebDriver driver;
static ExtentReports report;
static ExtentTest logger;
static void testcase1()
{
System.setProperty("webdriver.chrome.driver","chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.google.co.in");
logger.log(LogStatus.PASS, "This step is passed");
driver.close();
}
}
public class SampleTc2
{
static WebDriver driver;
static ExtentReports report;
static ExtentTest logger;
static void testcase2()
{
System.setProperty("webdriver.chrome.driver","chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.google.co.in");
logger.log(LogStatus.PASS, "This step is passed");
driver.close();
}
}
Main Class:
public class Maindriver {
static WebDriver driver;
static ExtentReports report;
static ExtentTest logger;
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
report=new ExtentReports("./Report/ExtentReport/ExecutionResult.html", true);
logger=report.startTest("TC1", "Testc Case1");
SampleTc1.testcase1();
report.endTest(logger);
logger=report.startTest("TC2", "Testc Case2");
SampleTc2.testcase2();
report.endTest(logger);
report.flush();
}
}
After running no reports are getting generated and it is showing null ponter exception:
Exception in thread "main" java.lang.NullPointerException
at SmokeTest.SampleTc1.testcase1(SampleTc1.java:24)
at SmokeTest.Maindriver.main(Maindriver.java:22)
Above exception I am getting.
Thanks in advance.
If you are using testng for running selenium suite, you can implement extent reports as a listener.
Like,
public class ExtentReporterNG implements IReporter
{
public ExtentReports extent;
private void buildTestNodes(IResultMap testMap, LogStatus status)
{
ExtentTest test;
if (testMap.size() > 0)
{
for (ITestResult result : testMap.getAllResults())
{
//test = extent.startTest(result.getInstance().getClass().getSimpleName(),result.getMethod().getMethodName());
test = extent.startTest(result.getMethod().getMethodName().toUpperCase(),result.getInstance().getClass().getSimpleName().toUpperCase());
test.assignCategory(result.getInstance().getClass().getSimpleName().toUpperCase());
test.setStartedTime(getTime(result.getStartMillis()));
for (String group : result.getMethod().getGroups())
test.assignCategory(group);
String message = "Test " + status.toString().toLowerCase() + "ed";
if (result.getThrowable() != null)
message = result.getThrowable().getMessage();
test.setEndedTime(getTime(result.getEndMillis()));
test.log(status, message);
extent.endTest(test);
}
}
}
private Date getTime(long millis)
{
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(millis);
return calendar.getTime();
}
#Override
public void generateReport(List<XmlSuite> xmlsuite, List<ISuite> suites,String file)
{
final String filePath=GlobalSettings.getProperty(GlobalSettings.EXTENTFILE);
extent = new ExtentReports(filePath, true,DisplayOrder.NEWEST_FIRST,NetworkMode.OFFLINE );
extent.loadConfig(new File("./config/extentConfig.xml"));
for (ISuite suite : suites)
{
Map<String, ISuiteResult> result = suite.getResults();
for (ISuiteResult r : result.values())
{
ITestContext context = r.getTestContext();
buildTestNodes(context.getPassedTests(), LogStatus.PASS);
buildTestNodes(context.getFailedTests(), LogStatus.FAIL);
buildTestNodes(context.getSkippedTests(), LogStatus.SKIP);
buildTestNodes(context.getFailedConfigurations(),LogStatus.FAIL);
buildTestNodes(context.getSkippedConfigurations(),LogStatus.SKIP);
}
}
extent.flush();
extent.close();
}}
It is not well organized, hard to say what/where is the problem ...
You can check here a selenium webdriver testng tutorial I used it when I started and it is a good starting point!
You have to change your ExtentReports as static in the base class. I got this idea from Mukesh Otwani, Selenium automation trainer for Learn-Automation.
I created separate class for extent report, hence avoided NULL pointer exception

Resources