Possible to create a 'Master Step' within Cucumber (java)?
For example I have created many steps files which use repeated code, the repeated code initialises the browser etc within each of the step files.
Is it even possible to create a master step file which will which will house the driver setup etc and therefore execute the setup using 'Cucumber Before' before each of the steps.
My Code:
public class LoginStep {
WebDriver driver;
LoginPage loginPage;
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver",
"C:\\Users\\deltaUser\\Desktop\\CucumberFramework\\PimCucumberFramework\\src\\test\\java\\resources\\other\\chromedriver.exe");
this.driver = new ChromeDriver();
this.driver.manage().window().maximize();
this.driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
loginPage = PageFactory.initElements(driver, LoginPage.class);
}
#Given("^User is on the PIM login page$")
public void user_is_on_the_PIM_login_page() throws Throwable {
loginPage.loginIntoAccount();
// loginPage.test();
}
#And("^enters the correct username$")
public void enters_the_correct_username() throws Throwable {
System.out.println("User neters the correct password inside the password textefield");
// loginPage.test2();
}
#And("^enters the correct password$")
public void enters_the_correct_password() throws Throwable {
System.out.println("Entered the correct password");
}
#When("^clicks on the login button$")
public void clicks_on_the_login_button() throws Throwable {
System.out.println("Clicked on the login button");
}
#Then("^user should be taken to the successful login page$")
public void user_should_be_taken_to_the_successful_login_page() throws Throwable {
System.out.println("Succesffully taken to the login page.");
}
}
I have tried the following code listed below, but the code dosnt work it seems to open the browser but then the other steps dont work (As if it has created a separate instance of the driver):
public class MasterStep {
WebDriver driver;
LoginPage loginPage;
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver",
"C:\\Users\\gianni.bruno\\Desktop\\BuyAGiftCucumberFramework\\PimCucumberFramework\\src\\test\\java\\resources\\other\\chromedriver.exe");
this.driver = new ChromeDriver();
this.driver.manage().window().maximize();
this.driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
loginPage = PageFactory.initElements(driver, LoginPage.class);
}
}
Yes, it is possible. Use the concept of Inheritance.
Step 1: Create a Base Class
package com.base;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class TestBase2 {
public static WebDriver driver = null;
public void initialize() {
System.setProperty("webdriver.chrome.driver", "src/com/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get("https://www.google.co.in");
}
}
Step 2: Inherit this class using the extends keyword and call the initialize() method whenever you need.
Cucumber provides Before and After hooks you could use for this.
Hooks are blocks of code that can run at various points in the Cucumber execution cycle. They are typically used for setup and teardown of the environment before and after each scenario.
Before hooks run before the first step of each scenario.
Annotated method style:
#Before
public void doSomethingBefore() {
}
Lambda style:
Before(() -> {
});
After hooks run after the last step of each scenario, even when steps are failed, undefined, pending, or skipped.
Annotated method style:
#After
public void doSomethingAfter(Scenario scenario){
// Do something after after scenario
}
Lambda style:
After((Scenario scenario) -> {
});
The scenario parameter is optional, but if you use it, you can inspect the status of the scenario.
Related
I'm trying to check login page control by using dataprovider but i don't want to initialize webdriver again and again for each username password control. Once i come into login page, checking all concerned scenarios on login page in single time without starting another driver seems more convenient to me but i couldn't figure it out. When running following code, data[0][0] and data[0][1] is being correctly checked but it gives no such element on Login method having second priority test annotation when being tried to be typed data[1][0] and data[1][1]. Probably, it causes because driver is not looking at that page on that time. How can I handle this issue ?
error:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//div[#class='q-input-wrapper email-input']//input[#class='q-input']"}
code:
public class TestCaseFirst {
public WebDriver driver;
#BeforeTest
public void Start() throws InterruptedException {
WebDriverManager.chromedriver().setup();
driver= new ChromeDriver();
driver.get("https://www.faxzas.com/");
driver.manage().window().maximize();
Thread.sleep(2000);}
#Test(priority=1)
public void RoadtoLogin() throws InterruptedException {
driver.findElement(By.xpath("//a[#title='Close']")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//div[#class='login-container']//span[#id='not-logged-in-container']")).click();;
Thread.sleep(1000);
}
#Test(dataProvider="loginInfos", priority=2)
public void Login(String mail, String password) throws InterruptedException {
driver.findElement(By.xpath("//div[#class='q-input-wrapper email-input']//input[#class='q-input']")).sendKeys(mail);
Thread.sleep(1000);
driver.findElement(By.xpath("//div[#class='q-input-wrapper']//input[#class='q-input']")).sendKeys(password);
Thread.sleep(1000);
driver.findElement(By.xpath("//button[#type='submit']")).click();
Thread.sleep(1000);
String description = driver.findElement(By.xpath("//div[#id='error-box-wrapper']//span[#class='message']")).getText();
System.out.println(description);
}
#DataProvider(name="loginInfos")
public Object[][] getData(){
Object[][] data = new Object[6][2];
data[0][0]="blackkfredo#gmail.com";
data[0][1]="";
data[1][0]="blackkfredo#gmail.com";
data[1][1]="443242";
data[2][0]="";
data[2][1]="1a2b3c4d";
data[3][0]="";
data[3][1]="";
data[4][0]="blackkfredogmail.com";
data[4][1]="1a2b3c4d";
data[5][0]="blackkfredo#gmail.com";
data[5][1]="1a2b3c4d";
return data;
}
}
You need to reset your page to the login page where you are expecting the element to be. Either put an #AfterMethod and go back to the page you are trying to test or put an #BeforeMethod for the same. You may even want to wrap up your find element calls and handle the exceptions by going back to the main page.
I have one test case contains two methods. When trying the two test methods in two browser instance, only one browser instance can open the website but the rest of the steps can't execute. Another browser instance can't even open the website (blank page).
I've tried the suggested solution on Stackoverflow. Those solutions do not work in my case.
public class RunSimpleTest{
private String baseUrl = "https://mywebsite";
public WebDriver driver;
GlobalFunctions objGlobalFunc;
#BeforeMethod(alwaysRun = true)
public void setup() {
try{
// declaration and instantiation of objects/variables
System.setProperty("webdriver.chrome.driver", "C:/ChromeDriver/chromedriver.exe");
// Disable Chrome Developer Mode Extension
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-extensions");
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
objGlobalFunc = new GlobalFunctions(driver);
driver.get(baseUrl);
objGlobalFunc = new GlobalFunctions(driver);
objGlobalFunc.selectEnglishLanguage();
}
catch (Exception e){
e.printStackTrace();
}
}
#Test
public void BTRun1() {
objGlobalFunc.setUserNameValue("ABC");
objGlobalFunc.clickOKBtnOnMEXLoginForm();
}
#Test
public void BTRun2() {
objGlobalFunc.setUserNameValue("ABC");
objGlobalFunc.clickOKBtnOnMEXLoginForm();
}
}
BTRun1 is opened in a chrome browser. And, the user can login.
BTRun2 is opened in another chrome browser. And, the user can login.
The core problem of your code is the usage of global WebDriver object.
When running in parallel, TestNG is creating just one instance of RunSimpleTest, therefore one instance of WebDriver object. That's causing the two test override each other when communicating with the WebDriver object.
One solution would be using ThreadLocalDriver and ThreadLocalGlobalFunctions:
protected ThreadLocalDriver threadLocalDriver;
protected ThreadLocalGlobalFunctions threadLocalGlobalFunctions;
public void setup() {
try{
// declaration and instantiation of objects/variables
System.setProperty("webdriver.chrome.driver", "C:/ChromeDriver/chromedriver.exe");
// Disable Chrome Developer Mode Extension
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-extensions");
options.addArguments("--start-maximized");
threadLocalDriver = new ThreadLocalDriver(options);
threadLocalDriver.getDriver().manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
objGlobalFunc = new ThreadLocalGlobalFunctions(threadLocalDriver.getDriver());
threadLocalDriver.getDriver().get(baseUrl);
objGlobalFunc.getGlobalFunc().selectEnglishLanguage();
}
catch (Exception e){
e.printStackTrace();
}
}
#Test
public void BTRun1() {
objGlobalFunc.getGlobalFunc().setUserNameValue("ABC");
objGlobalFunc.getGlobalFunc().clickOKBtnOnMEXLoginForm();
}
#Test
public void BTRun2() {
objGlobalFunc.getGlobalFunc().setUserNameValue("ABC");
objGlobalFunc.getGlobalFunc().clickOKBtnOnMEXLoginForm();
}
To learn more about using ThreadLocal with WebDriver, check: http://seleniumautomationhelper.blogspot.com/2014/02/initializing-webdriver-object-as-thread.html
I have totally four methods in my class
I have created a static WebDriver object
static WebDriver driver;
Method 1: Log-in to site ( Here I initialize the WebDriver driver=new new FirefoxDriver();)
Method 2: Click a link in site ( Using WebDriver driver)
On click, the link gets opened in new tab in same browser
Method 3:
Now in Method 3, I switch to new tab and perform some actions with web element in the new tab
Below code is used to switch to new tab
ArrayList<String> tabss = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(tabss.get(1));
Method 4: Again I want to perform some more action in the new tab
Now I need the same driver instance (tab) used in Method 3 in Method 4.
How do I get that
If I use "driver" in Method 4, it's null.
public class download {
static WebDriver driver;
#Test
public static void login() throws InterruptedException
{
driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("__site__");
driver.findElement(By.id("login-email")).sendKeys("__username__");
driver.findElement(By.id("login-password")).sendKeys("__password__");
driver.findElement(By.id("login-submit")).click();
Thread.sleep(3000);
}
#Test
public static void navigatetolearningpage() throws InterruptedException
{
driver.findElement(By.xpath("//div[#class='relative ember-view']")).click();
Thread.sleep(3000);
}
#Test
public static void search() throws InterruptedException, AWTException
{
ArrayList<String> tabss = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(tabss.get(1));
driver.findElement(By.xpath("//input[#type='text']")).sendKeys("__searchkeyword__");
Thread.sleep(3000);
driver.findElement(By.xpath("//input[#type='text']")).sendKeys(Keys.RETURN);
Thread.sleep(3000);
driver.findElement(By.xpath("//div[#class='search-facet__label']")).click();
}
#Test
public static void course_list() throws InterruptedException
{
//This driver will print as NULL
System.out.println("last method:"+driver);
}
}
The order of the tests isn't guaranteed, so you need to initialize driver at start of the tests
Move the initialization code to the declaration of driver:
static WebDriver driver = new FirefoxDriver();
EDIT
Following #Laazo comment,
I think it's better than add it to #BeforeClass Because if you switch to TestNG framework you will need to change or upgrade to JUnit5 to #BeforeAll
Hi guys I want to quit the page afte I type "Hello World" in google search using firefox browser and selenium
WebDriver driver = null;
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowser();
ss.getPage();
ss.quitPage();
}
private void openBrowser() {
System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");
driver = new FirefoxDriver();
}
private void quitPage() {
driver.quit();
}
private void getPage() {
driver.get("http://www.google.com");
}
1) Create a Junit test class
2) Initialize the driver in your setup method like
ChromeDriver driver = new ChromeDriver();//Download chromeDriver.exe file and point to location where you have installed the like as you mentioned. `driver.System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");`
3) Create a test method with your business logic to type hello world
3) Create After and Before Class annotations for the methods .In After class annotation method you can write driver.quit.
You can refer to following link for more clarity
https://www.guru99.com/selenium-tutorial.html
I am Added sample format which is written Using java and testNG..Here Every time First before method will run then 1st test case will execute then after method will work then again before method work then next test case......In this way you can manage your test case and it will also generate Report also.Here you will get better explanation.
public class GoogleTest {
FirefoxDriver driver;
#BeforeMethod
public void setUp1() throws Exception {
System.setProperty("webdriver.gecko.driver", "D:\\\\ToolsQA\\trunk\\Library\\drivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.google.com");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void GoogleInputField() throws InterruptedException {
System.out.println("Hello world");
System.out.println("Hello world");
//Write Your test case for test case 1
}
#Test
public void google suggestion() throws InterruptedException {
//Write Your test case for test case 1
}
#AfterMethod
public void getResult(ITestResult result) throws IOException {
driver.quit();
}
}
Dont forget to add Firefox driver on gecko.driver path
I am assuming that you want to open the browser using selenium, load google and then listen till you MANUALLY enter "hello world" in the input box. The method listenForHelloWorld() will do that.
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowser();
ss.getPage();
ss.listenForHelloWorld();
ss.quitPage();
}
private void listenForHelloWorld() {
// Get the search field
WebElement searchField = driver.findElement(By.name("q"));
int count = 1;
while (count++ < 20) {
// if search field value is "hellwo world" break loop which will eventallu lead to `quit()` as it is the next method to exit.
if (searchField.getAttribute("value").equalsIgnoreCase("hello world")) {
break;
}
Thread.sleep(5000)
}
}
If you are asking how to enter "hello world" in browser automatically use below.
driver.findElement(By.name("q")).sendKeys("hello world");
I have abstract class, where initialize webdriver. All classes with the implementation of the tests are inherited from him. I want to reduce the time of test, open a browser for all tests.
class AbstractClassCase {
public static WebDriver driver;
#BeforeClass
#Parameters({"webDriver", "applicationHost", "applicationPort", "driverHost", "driverPort", "username", "password"})
public void setUp(
String webDriverIdentifier,
String applicationHost,
#Optional String applicationPort,
#Optional String driverHost,
#Optional String driverPort,
#Optional String username,
#Optional String password){
driver = new FirefoxDriver();
driver.get("localhost");
login(username, password)
}
#AfterСlass
public void tearDown() {
driver.quite();
}
}
public class TestButton extends AbstractClassCase {
#Test
public void testClickButtonNo() {
WebElement button = driver.findElement(By.id("button-no"));
button.click();
WebElement status = driver.findElement(By.id("button-status"));
Assert.assertEqual("Cancel", status.getText());
}
}
and other test class in the same spirit.
How can I reconfigure this class, so that the browser opened once?
If you want to Open Browser at the start once and run all the methods and then close it.
There are 2 steps i would recommend to follow.
Step 1:
Include browser invocation code in methods with #BeforeSuite && #AfterSuite for closing the browser/driversession. This makes sure these tests are run once before and after test suite.
protected static WebDriver Browser_Session;
#BeforeSuite
public void beforeSuite() {
Browser_Session=new FirefoxDriver();
Browser_Session.manage().timeouts().implicitlyWait(30000, TimeUnit.MILLISECONDS);
}
#AfterSuite
public void afterSuite() {
Browser_Session.quit();
}
Step2 : Open testng.xml and include all such classes (test methods) under a single Suite, Thus making sure the browser (via Selenium) is invoked first and then rest all methods are run in the same browser.
Here "Class Init" contains Browser Initiating code and ClassA & ClassB are subclassess of Init.
Hope this helps
If you want to run all test in one instance, i wrote my own WebDriverFactory so here is some examples for help:
public static WebDriver getDriver(){
if (driver == null) {
return new FireFoxDriver();
} else {
return driver;
}
}
Now remove AfterClass and add this to your class it will shutdown your browser in the end
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
dismissDriver();
} catch (Exception e) {
}
}
});
}
public static void dismissDriver() {
if (driver != null) {
try {
driver.quit();
driver = null;
} catch (Throwable t) {
}
}
}