PageOne and PageTwo both need to make use of MasterPage methods (eg click Ok). I'm trying to initialize both pages within the constructor of MasterPage.
IntelliJ tells me to either add super(driver) to the Page1/Page2 constructors, or to add a no arg constructor to master. In both cases, the tests can't run. with a super(driver) constructor, the pages fail to initialize, and in the no arg constructor, the clickOk() method fails when called from the Page1/Page2 method.
MasterPage:
public class MasterPage {
private WebDriver driver;
public Page1 p1;
public Page2 p2;
public MasterPage(WebDriver driver) {
this.driver = driver;
p1 = new Page1(driver);
p2 = new Page2(driver);
PageFactory.initElements(driver, this);
}
#FindBy(id = "OkBtn")
private WebElement okBtn;
public void clickOk() {
okBtn.click();
}
}
Page1:
public class Page1 extends MasterPage {
private WebDriver driver;
public Page1(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
#FindBy(id="field")
private WebElement elementOne;
public void completePage() {
elementOne.click();
clickOk();
}
}
Page2:
public class Page2 extends MasterPage {
private WebDriver driver;
public Page2(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
#FindBy (id="field")
private WebElement elementTwo;
public void completePageTwo() {
elementTwo.click();
clickOk();
}
}
My intention is to utilise them like this:
public class Page1Steps {
MasterPage master;
WebDriver driver;
public void testMethod() {
master = new MasterPage(driver);
master.p1.completePage();
master.p2.completePageTwo();
}
}
You may be able to tell, I'm not 100% sure of the best way to approach this problem, so any guidance would be really appreciated.
First of all, MasterPage shouldn't know about page1 and page2, it's their base class. You also don't need driver in each one of the derived Page, you can hold it in the parent MasterPage.
The problem is MasterPage constructor receives WebDriver parameter, but you don't have call to super(driver) in the derived classes constructors.
I also suggest each method which navigates the test to the another page will return this new page
MasterPage:
public class MasterPage { // can be abstract
protected WebDriver driver;
public MasterPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
#FindBy(id = "OkBtn")
private WebElement okBtn;
protected void clickOk() {
okBtn.click();
}
}
Page1:
public class Page1 extends MasterPage {
public Page1(WebDriver driver) {
super(driver);
}
#FindBy(id="field")
private WebElement elementOne;
public Page2 completePageAndGoToPageTwo() {
elementOne.click();
clickOk();
return new Page2(driver);
}
}
Page2:
public class Page2 extends MasterPage {
public Page2(WebDriver driver) {
super(driver);
}
#FindBy (id="field")
private WebElement elementTwo;
public void completePageTwo() {
elementTwo.click();
clickOk();
}
}
Page1Steps:
public class Page1Steps {
public void testMethod() {
Page1 pageOne = new Page1(driver);
pageOne
.completePageAndGoToPageTwo()
.completePageTwo();
}
}
Related
I have a situation- I want to write a test when a particular User Logs in, he should not see Budget Icon. Budget icon is obviously not available when he's logged in. So I want to make sure that its working right though assertion. I am confused how should I do it ..I am using Page Object Model and I am trying below: using isDisplayed method
Below is my Base class:
public class LaydownHomePage extends TestBase {
#FindBy(xpath="//nav[#id=\"mainnav-container\"]/div[2]/a[2]")
WebElement budgeticon;
public LaydownHomePage () {
PageFactory.initElements(driver, this);
}
public boolean CheckIfBudgetIconIsAvailable ()
{
return budgeticon.isDisplayed();
}
}
And this is my Test class:
public class VerifyLaydownBudgeticon extends TestBase
{
LoginPage loginpage;
LaydownHomePage homepage;
public VerifyLaydownBudgeticon()
{
super();
}
#Test(priority=1)
public void setUp()
{
//TestBase base= new TestBase();
initialization();
loginpage= new LoginPage();
loginpage.loginToBase(prop.getProperty("username"),prop.getProperty(
"password"));
homepage=loginpage.changeLogin();
}
#Test(priority=2)
public void BudgetIconDisplayed (){
// Assert.assertTrue(false);
Assert.assertEquals(true, homepage.CheckIfBudgetIconIsAvailable());
}
}
I tried to Create a Simple Program in Selenium Using PageObjectModel. While Running the Program it throws Null Pointer Exception. Don't Know what i am doing wrong.Is my initialization of Variable is Wrong. I know i am making mistake in initializing the By locator but don't know what i am doing wrong.
public class main extends Base{
private static final int TIMEOUT = 5;
private static final int POLLING = 100;
protected WebDriverWait wait;
protected static WebElement ele;
protected By locator;
public void Base() {
wait = new WebDriverWait(driver, TIMEOUT, POLLING);
}
public WebElement waitForElementToAppear(By locator) {
wait.until(ExpectedConditions.presenceOfElementLocated(locator));//Line which Throws Null
return ele;
}
protected void waitForElementToDisappear(By locator) {
wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
}
protected void waitForTextToDisappear(By locator, String text) {
wait.until(ExpectedConditions.not(ExpectedConditions.textToBe(locator, text)));
}
#Test()
public void getURL() {
driver.get("https://www.google.com");
waitForElementToAppear(By.name("q")).sendKeys("Pom");// Line Which Throws Null.
}
And My Base Class Code where i have saved the properties of the driver.
public class Base {
protected WebDriver driver;
public WebDriver getDriver() {
return driver;
}
public void setDriver(WebDriver driver) {
this.driver = driver;
}
#BeforeSuite
public void beforeSuite() {
System.setProperty("webdriver.chrome.driver", "D:\\Selenium\\chromedriver.exe"); // You can set this property elsewhere
driver=new ChromeDriver();
driver.manage().window().maximize();
}
}
The problem lies in the way in which you are initialising the WebDriverWait object.
Your WebDriver object will get instantiated only when the #BeforeSuite method runs in your Base class.
The logic of initialising the WebDriverWait is part of the method public void Base() in your main class.
But your #Test annotated getURL() method does not invoke Base() method. So your wait object is always null.
To fix this, invoke Base() within your #Test method or have your Base() method annotated with #BeforeClass annotation, so that it gets automatically called by TestNG.
There are multiple problems in your code
Probably you do not need global variable declarations. Of course you can do it like that but make sure you initialize them.
Do not put test methods in your page object
ele will always be null
Call the constructor
Probably you need something like following:
public class MyPageObject extends Base{
private static final int TIMEOUT = 5;
private static final int POLLING = 100;
protected WebDriverWait wait;
public void MyPageObject() {
super(); //Call constructor of Base if needed
wait = new WebDriverWait(driver, TIMEOUT, POLLING); //init wait
}
public WebElement waitForElementToAppear(By locator) {
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
return driver.findElement(locator); //return WebElement
}
protected void waitForElementToDisappear(By locator) {
wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
}
protected void waitForTextToDisappear(By locator, String text) {
wait.until(ExpectedConditions.not(ExpectedConditions.textToBe(locator, text)));
}
}
public class MyTestClass {
#Test()
public void getURL() {
MyPageObject myPageObject = new MyPageObject(); //Initialize your page object
driver.get("https://www.google.com");
myPageObject.waitForElementToAppear(By.name("q")).sendKeys("Pom");
}
I am new in Selenium and Java and I need help with base class. I have I base where I set methods for driver browsers and for its close. Problem is that when I call these method from main always web driver is called and browser is open many times. What is best practice if I don't want to have code duplication
and I want a good structure of project.
Main:
public class Main extends TestBase {
public static void main(String[] args) throws InterruptedException, ClassNotFoundException, SQLException {
LoginTest LoginTest = new LoginTest();
LogofTest LogofTest = new LogofTest();
TestBase TestBase = new TestBase();
LoginTest.setUpBeforeTestMethod();
LoginTest.loginAsAdmin();
LogofTest.logofAsAdmin();
LoginTest.tearDownAfterTestClass();
}
}
TestBase:
public class TestBase {
String a = System.setProperty("webdriver.chrome.driver",
"path");
WebDriver driver = new ChromeDriver();
protected WebDriver setUpBeforeTestClass() {
return driver;
}
protected void setUpBeforeTestMethod() {
driver.get("website");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void tearDownAfterTestClass() {
driver.close();
}}
LoginTest:
public class LoginTest extends TestBase {
public void login() throws InterruptedException {
WebElement username = driver.findElement(By.name("username"));
username.sendKeys("username");
}
}
The main focus is that I don't want to write again
WebDriver driver = new ChromeDriver();
driver.get("website"); System.setProperty("webdriver.chrome,"path");
for each test in function or class. So I want to create base class and inherit from it.
Example Selenium Test with JUnit using the Page Object Model
TestBase
public class TestBase
{
private String a = System.setProperty("webdriver.chrome.driver", "path");
protected WebDriver driver;
#Before //Before each test case, use BeforeClass for before each test class
public static void setUpBeforeTestCase() {
driver = new ChromeDriver();
driver.get("website");
}
#After
public static void tearDownAfterTestCase() {
driver.Quit(); //driver.Close() closes the window, but doesn't properly dispose of the driver
}
}
LoginTest:
public class LoginTest extends TestBase {
#Test
public void loginAndOutAsAdmin(){
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
LandingPage landingPage = loginPage.login("adminUser", "adminPassword");
landingPage.logout();
//Do some sort of assert here that you are logged out
}
}
BasePage
public class BasePage
{
protected WebDriver driver;
//Other common stuff your Page Objects will do, like wait for an element
}
LoginPage
public class LoginPage extends BasePage
{
#FindBy(how = How.NAME, using = "username")
private WebElement usernameBox;
//something for passwordBox and loginButton
public LoginPage(WebDriver currentDriver)
{
driver = currentDriver;
}
public LandingPage login(String username, String password)
{
usernameBox.sendKeys(username);
passwordBox.sendKeys(password);
loginButton.click();
return PageFactory.initElements(driver, LandingPage.class);
}
}
I haven't tried to compile this, but that's the basic idea. I'll let you fill in the details.
I need to be login in to start my tests. So in my test class I make #BeforeClass method where I login to my application. Then I start simply test but it did not work. When I remove my login from #BeforeClass and put it to my test it works fine. But I do not want to login in in all my test before I can start them. I think there is problem with that my object are static but i do not have clue why.
Here is my not working code:
public class ModulesTests extends FunctionalTest {
static LoginPage loginPage;
static LoginPageReceipt loginPageReceipt;
#BeforeClass
public static void login() {
FunctionalTest.driver.get(GlobalVariables.URL);
loginPage = new LoginPage(FunctionalTest.driver);
loginPageReceipt = loginPage.login(GlobalVariables.USER_NAME, GlobalVariables.PASSWORD);
}
#Test
public void products() {
ProductsPage productsPage = loginPageReceipt.productsPage();
}
}
Here is when it works:
public class ModulesTests extends FunctionalTest {
#BeforeClass
public static void login() {
FunctionalTest.driver.get(GlobalVariables.URL);
}
#Test
public void products() {
LoginPage loginPage = new LoginPage(FunctionalTest.driver);
LoginPageReceipt loginPageReceipt = loginPage.login(GlobalVariables.USER_NAME, GlobalVariables.PASSWORD);
ProductsPage productsPage = loginPageReceipt.productsPage();
}
}
And rest of my classes:
public class FunctionalTest {
protected static WebDriver driver;
#BeforeClass
public static void setUp() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
System.setProperty("webdriver.chrome.driver", "src\\main\\resources\\chromedriver.exe");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#After
public void cleanUp() {
driver.manage().deleteAllCookies();
}
#AfterClass
public static void tearDown() {
driver.close();
}
}
public class LoginPage extends PageObject {
#FindBy(id = "UserName")
private WebElement userName;
#FindBy(id = "Password")
private WebElement password;
#FindBy(id = "loginButton")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
super(driver);
assertTrue(userName.isDisplayed());
assertTrue(password.isDisplayed());
assertTrue(loginButton.isDisplayed());
}
public void enterUserName(String userName) {
this.userName.clear();
this.userName.sendKeys(userName);
}
public void enterUserPassword(String password) {
this.password.clear();
this.password.sendKeys(password);
}
public LoginPageReceipt login(String userName, String password) {
enterUserName(userName);
enterUserPassword(password);
loginButton.click();
return new LoginPageReceipt(driver);
}
}
public class LoginPageReceipt extends PageObject {
public NavigationModules mainNav;
#FindBy(xpath = "//*[#id=\"loginPartial\"]")
private WebElement userNamePanel;
#FindBy(id = "products-menuitem")
private WebElement goToProductsPage;
public LoginPageReceipt(WebDriver driver) {
super(driver);
}
public String loginConfirmation() {
return userNamePanel.getText();
}
public ProductsPage productsPage() {
System.out.println(goToProductsPage.getText());
goToProductsPage.click();
return new ProductsPage(driver);
}
public NavigationModules initModuleNav() {
return new NavigationModules(driver);
}
}
public class ProductsPage extends PageObject {
#FindBy(id = "products-content-navigation")
private WebElement productMenu;
public ProductsPage(WebDriver driver) {
super(driver);
assertTrue(productMenu.isDisplayed());
}
}
public class PageObject {
protected WebDriver driver;
public PageObject(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
System.out.println(getClass().getName());
}
}
Edit. I just saw that when I use #BeforeClass method I get also java.lang.reflect.constructor.newinstance(unknown source) exception.
You should use #Before so that all your tests have to login before proceeding, meanwhile, #BeforeClass runs one time, and it's usefull just in case multiple tests will share same objects.
Please take a look on this link.
I am running this class as testNG and getting error either make it static or add a no-args constructor. If I add no arg constructor, I get error: "implicit super constructor BaseClass() is undefined."
public class testmaven extends BaseClass{
public testmaven(WebDriver driver) {
super(driver);
// TODO Auto-generated constructor stub
}
#Test
public void myMethod() throws Exception {
logInPage.openApp("Chrome","http://url.com");
}
Here is the Base Class:
public class BaseClass {
public WebDriver driver;
public boolean isDisplay;
public LogInPage logInPage;
public WaitForObj wait;
public DashboardPage dashboardPage;
public Actions action;
public Util util;
public BaseClass(WebDriver driver){
this.driver = driver;
this.isDisplay = false;
logInPage = new LogInPage(driver);
wait = new WaitForObj(driver);
dashboardPage = new DashboardPage(driver);
util = new Util (driver);
action = new Actions(driver);
}
Here is the Login class
public class LogInPage extends BaseClass {
BrowserFactory browserfactory = new BrowserFactory();
public LogInPage(WebDriver driver){
super(driver);
}
public void openApp(String browserName, String env) throws Exception{
driver = browserfactory.getBrowser(browserName);
Log.info("Browser:" + browserName);
driver.manage().window().maximize();
driver.get(env);
Log.info("Env: " + env);
wait.wait(1);
}
You have to explain to TestNG how it is supposed to instanciate your test class.
A solution is using a #Factory.
Another solution, which is a more common pattern, is having an empty constructor and using #BeforeX and/or #AfterX methods for the initialisation of attributes.