Here is my code:
public class BasePage extends PageObject {
#Managed
WebDriver driver;
public Alert waitingForAlert() throws InterruptedException {
Alert al = driver.switchTo().alert();
return al;
}
I'm getting the error
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.switchTo()" because "this.driver" is null
You get this error only because of using driver before creating an instance of it.
Let's suppose you want to run this test case on Chrome and your PageObject class doesn't have Chrome Driver instance (if yes it will create new chrome driver instance again which is not supposed to do)
WebDriver driver;
public Alert waitingForAlert() throws InterruptedException {
Alert al = driver.switchTo().alert();
return al;
}
The nullPointer exception comes from this line: driver.switchTo().alert();
in order to use driver you should create an instance of it. Meaning you can do it by typing:
class BasePage extends PageObject {
#Managed
WebDriver driver;
public void setDriver()
{
System.setProperty("webdriver.chrome.driver","<Path of ChromeDriver.exe here>");
driver = new ChromeDriver(); // Creating new 'ChromeDriver' instance
}
public Alert waitingForAlert() throws InterruptedException {
setDriver();
Alert al = driver.switchTo().alert();
return al;
}
}
What you're seeing is that driver is still null because BasePage has not yet been instantiated. You will have to override the navigateTo method in some way to create a driver.
class BasePage extends PageObject {
#Managed
WebDriver driver;
public Alert waitingForAlert() throws InterruptedException {
Alert al = driver.switchTo().alert();
return al;
}
public void navigateTo() { // your code here ... }
}
Related
I want to define a WindowsElement so I can reuse it , but if I run it , it throws java.lang.ClassCastException: org.openqa.selenium.remote.RemoteWebElement cannot be cast to io.appium.java_client.windows.WindowsElement
I went though some WinAppDriver bugs ,but all were closed without any useful information.
public class WinAppDriverWaitsExample {
private static WindowsDriver<WebElement> driver = null;
private static WebElement alarm = null;
#BeforeClass
public static void setup() {
try {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("app", "Microsoft.WindowsAlarms_8wekyb3d8bbwe!App");
driver = new WindowsDriver<WebElement>(new URL("http://127.0.0.1:4723"), capabilities);
driver.manage().timeouts().implicitlyWait(12, TimeUnit.SECONDS);
//To make sure app is launched
alarm = driver.findElementByName("Alarm tab");
Assert.assertNotNull(alarm);
}catch(Exception e){
e.printStackTrace();
} finally {
}
}
#Test
public void timer() {
System.out.println("Start and stop the alarm clock");
//It is AutomationID
driver.findElementByAccessibilityId("TimerPivotItem").click();
WindowsElement startBtn= (WindowsElement) driver.findElementByName("Start");
WindowsElement pasueBtn=(WindowsElement) driver.findElementByName("Pause");
startBtn.click();
pasueBtn.click();
}
Change the element type to a WebElement had solved my issue .
#Test
public void timer() {
System.out.println("Start and stop the alarm clock");
//It is AutomationID
driver.findElementByAccessibilityId("TimerPivotItem").click();
WebElement startBtn= driver.findElementByName("Start");
WebElement pasueBtn=driver.findElementByName("Pause");
startBtn.click();
pasueBtn.click();
}
I want to use PageFactory initElements in the same java class and also use it only once.
It gives me an NullPointerException error.
However if I use it in each class while entering username and password I do not get an error.
import org.openqa.selenium.support.PageFactory;
public class LoginFeature {
#FindBy(how=How.XPATH,using="//input[#placeholder='Username']")
WebElement objUserName;
#FindBy(how=How.XPATH,using="//input[#placeholder='Password']")
WebElement objPwd;
#FindBy(how=How.XPATH,using="//a[#onclick='return ValidateLogin()']")
WebElement objLoginButton;
public LoginFeature(){
PageFactory.initElements(config.driver, this);
}
public void EnterURL(String enterURL) throws InterruptedException{
config.driver.get(enterURL);
Thread.sleep(2000);
}
public void Enterusername(String uname)
{
//PageFactory.initElements(config.driver, this); This does not give an error. But I do not want to use it in each class separately
objUserName.sendKeys(uname);
}
public void EnterPwd(String pwd)
{
//PageFactory.initElements(config.driver, this);
objPwd.sendKeys(pwd);
}
#FindBy(how=How.XPATH,using="//input[#placeholder='Username']")
WebElement objUserName;
The above code is equivalent to below code
WebElement objUserName = driver.findElement(By.xpath("//input[#placeholder='Username']"));
Now when you initialize page using object of LoginFeature class
PageFactory.initElements(config.driver, this);
and if your driver is not initialized then anything you access using driver will throw NullPointerException. e.g. your first page object is initialized and as soon as you use it exception happens.
Try initializing browser like this
public class LoginFeature {
public LoginFeature(){
initializeDriver();
PageFactory.initElements(config.driver, this);
}
public void initializeDriver(){
config.driver=new ChromeDriver;
}
}
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
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.
I am trying to run Selenium Webdriver tests in parallel on a single machine, using TestNG. I have 3 #Test methods, where 3 different users log in to the same application and reach the home page. I need #Test methods to run in parallel, and write to an ExtentReports report.
My problem is, despite 3 completely different methods in different classes, one of the users will be logged into 2 out of 3 of the browsers, leaving a user out.
The login method is located in a PageFactory page object class.
Here are my 3 test methods:
#Test(enabled = true, priority = 0)
public void JohnLogin() throws Exception {
ExtentTest t = ClientReportFactory.getTest();
try {
Login objLogin = new Login(getDriver());
String username = "John";
String password = "Password";
objLogin.SignIn(username, password);
HomePage objHomePage = new HomePage(getDriver());
assertTrue(objHomePage.clientName.getText().contains("John"));
} catch (Exception e) {
}
}
#Test(enabled = true, priority = 1)
public void BobLogin() throws Exception {
ExtentTest t = ClientReportFactory.getTest();
try {
Login objLogin = new Login(getDriver());
String username = "Bob";
String password = "Password";
objLogin.SignIn(username, password);
HomePage objHomePage = new HomePage(getDriver());
assertTrue(objHomePage.clientName.getText().contains("Bob"));
} catch (Exception e) {
}
}
#Test(enabled = true, priority = 2)
public void SamLogin() throws Exception {
ExtentTest t = ClientReportFactory.getTest();
try {
Login objLogin = new Login(getDriver());
String username = "Sam";
String password = "Password";
objLogin.SignIn(username, password);
HomePage objHomePage = new HomePage(getDriver());
assertTrue(objHomePage.clientName.getText().contains("Sam"));
} catch (Exception e) {
}
}
So, if I pause the tests on the Homepage. I will have 2 browser windows opened as "John", one "Bob" and no "Sam"... Causing failures.
Here's the PageFactory Object's login method.
public void SignIn(String strUsername, String strPassword) throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, 15);
username.clear();
username.sendKeys(strUsername);
password.clear();
password.sendKeys(strPassword);
submit.click();
wait.until(ExpectedConditions.visibilityOf(homePagePanel));
}
At first I was sure the problem was in the #BeforeMethod threading (As in, the tests were in a different thread than the #Before and #After). But I don't see how that could be the case. The Base Test method successfully opens and closes 3 browsers. It just seems like the #Test methods use each other's data! But just in case, here's my #Before and #After, with my Threading code.
public class BaseTest {
public String browser;
private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
#BeforeMethod(alwaysRun = true)
#Parameters({ "browser"})
public void setup(String browser)throws MalformedURLException,
InterruptedException {
WebDriver driver = null;
if (browser.equalsIgnoreCase("Internet Explorer")) {
System.setProperty("webdriver.ie.driver", "C:\\Selenium\\IEDriverServer.exe");
driver = new InternetExplorerDriver();
} else if (browser.equalsIgnoreCase("Firefox")) {
System.setProperty("webdriver.gecko.driver", "C:\\Selenium\\geckodriver.exe");
driver = new FirefoxDriver();
} else if (browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", "C:\\Selenium\\chromedriver.exe");
driver = new ChromeDriver();
} else if (browser.equalsIgnoreCase("MicrosoftEdge")) {
System.setProperty("webdriver.edge.driver", "C:\\Selenium\\MicrosoftWebDriver.exe");
driver = new EdgeDriver();
}
setWebDriver(driver);
this.browser = browser;
ClientReportFactory.getTest(ExtentTestName, ExtentTestDescription);
baseURL = "testApp.com";
driver.get(baseURL);
driver.manage().window().maximize();
}
public WebDriver getDriver(){
return threadedDriver.get();
}
public void setWebDriver(WebDriver driver) {
threadedDriver.set(driver);
}
#AfterMethod
public void afterMethod() {
ClientReportFactory.closeTest(ExtentTestName, ExtentTestDescription);
getDriver().quit();
threadedDriver.set(null);
}
#AfterSuite
public void afterSuite() {
ClientReportFactory.closeReport();
if (getDriver() != null) {
getDriver().quit();
} else {
System.out.println("Drivers already closed");
}
}
Assuming that all of your #Test methods are in different classes, I am guessing that the problem is perhaps due to the fact that your ThreadLocal variable is NOT STATIC but is an instance variable. This causes the behaviour to be per thread per instance rather than the desired behaviour viz., per thread across all instances. You can refer to this StackOverFlow thread for a better explanation on this.
You would resort to using an instance variant of ThreadLocal if and only if all your #Test methods belong to the same test class (Because now you are only trying to ensure that the class level data member WebDriver is shared in a thread safe manner across all the test methods that belong to the same test class)
So if each of your #Test methods reside in its own Test class, then please try changing:
private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
to
private static ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
You could try this.
public class DriverFactory(){
private static ThreadLocal<WebDriver> driverThread;
public WebDriver driver;
#Parameters("browser")
public WebDriver instantiateDriverObject(String browser) {
DriverFactory factory = new DriverFactory();
driver = factory.createInstance(browser); //Driver instantiation goes here
driverThread = new ThreadLocal<WebDriver>() {
#Override
protected WebDriver initialValue() {
webDriverPool.add(driver);
return driver;
}
};
return driver;
}
public WebDriver getDriver() {
return driverThread.get();
}
}