I need to implement one thing: Every time when I start my tests I have to Login into the system. I created a class that should run this Login procedure. I'm able to send proper values to this class and it is able to login, but after that, I'm receiving NullPointerException on my second class (which is running tests itself). It looks like it is not able to see browser window at all. Help me please to write this classes in a way that would allow my to re-use the Login class in as many classes as I want.
One for Login:
public class Login {
private static WebDriver driver;
public static void Find_Fields (String path,String login, String password) {
driver = Driver.get(path);
WebElement login_field = driver.findElement(By.id("abc"));
login_field.sendKeys(login);
//Find Password Field on Start page
WebElement password_field = driver.findElement(By.id("abc"));
password_field.sendKeys(password);
//Find Login Button
WebElement login_button = driver.findElement(By.xpath("abc"));
login_button.click();
}
}
public class Testing {
private static WebDriver driver;
#BeforeClass
public static void a_setup(){
//here I'm trying to run Login with parameters
Login fields = new Login();
fields.Find_Fields(LOGIN_PATH, LOGIN, PASSWORD);
}
#Test
public void b_Press_Login_Button(){
//Here I'm trying to start testing in session started from a_setup()
WebElement keyword = driver.findElement("..."));
keyword.sendKeys("...");
}
#AfterClass
public static void Close(){
driver.quit();
driver.close();
}
}
You have two independent WebDriver fields, one for each class. You've initialized the one in Login, but you didn't pass the reference back to Testing class. One of the solutions would be to simply pass WebDriver as parameter to Login constructor:
public class Login {
private WebDriver driver;
public void Find_Fields (String path,String login, String password) {
driver.get(path);
//(...) rest of this method is unchanged
}
public Login(WebDriver driver) {
this.driver = driver;
}
}
public class Testing {
private static WebDriver driver;
#BeforeClass
public static void a_setup(){
driver = new FirefoxDriver(); //initialize the driver
Login fields = new Login(driver); //pass the instance of WebDriver to login class
fields.Find_Fields(LOGIN_PATH, LOGIN, PASSWORD);
}
//(...) rest of the class remains unchanged
}
You need to initialize your driver with a browser object. Something like this should work:
public static void Find_Fields (String path,String login, String password)
{
driver = new FirefoxDriver();
driver.get(path);
WebElement login_field = driver.findElement(By.id("abc"));
login_field.sendKeys(login);
//Find Password Field on Start page
WebElement password_field = driver.findElement(By.id("abc"));
password_field.sendKeys(password);
//Find Login Button
WebElement login_button = driver.findElement(By.xpath("abc"));
login_button.click();
}
Related
I need help with creating Java automation with Selenium Webdriver to Pom or Pomm factory.
I've read how to create pom without any success.
Please help.
I need help on how to create java automation in pom. strong textHow to conver it?
String baseUrl = "https:amazon.com/";
WebDriver driver;
NavigationPom navigationPom;
private final boolean useFirefoxbrowser = false;
#BeforeClass
public static void setupClass() {
WebDriverManager.chromedriver().setup();
WebDriverManager.firefoxdriver().setup();
}
#Before
public void setUp() {
if (useFirefoxbrowser == false) {
FirefoxOptions firefoxOptions = new FirefoxOptions();
firefoxOptions.addArguments("--width=1240", "--height=720");
driver = new FirefoxDriver(firefoxOptions);
} else {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--window-size=1920,1080");
driver = new ChromeDriver(chromeOptions);
}
}
#Test
public void MacbookTest1() {
driver.get(baseUrl);
driver.manage().window().maximize();
driver.findElement(By.xpath("//input[#id='twotabsearchtextbox']")).click();
driver.findElement(By.xpath("//input[#id='twotabsearchtextbox']")).sendKeys("macbook");
driver.findElement(By.xpath("//input[#id='nav-search-submit-button']")).click();
driver.findElement(By.xpath("//input[#id='nav-search-submit-button']")).click();
driver.findElement(By.xpath("//li[#id='p_89/Lenovo']/span/a/div/label/i")).click();
//Checkboxes
boolean enabled = driver.findElement(By.xpath("//li[#id='p_89/Lenovo']/span/a/div/label/i")).isEnabled();
Start from creating a simple implementation:
How the Page class might look:
class Page {
private WebDriver driver;
public Page(WebDriver driver) {
this.driver.driver = driver;
}
//Define locators
//Keep elements as By on the top of the class
private By someElement1 = By.xpath("...");
private By someElement2 = By.xpath("...");
//Define page methods
// Examples:
// public void clickSomeElement()
// public void fillSomeInput()
public void doSomeAction() {
WebElement element = driver.findElement(someElement1);
// do something with the element
// optionaly wait for something after action
}
// Examples:
// public boolean isPageLoaded()
// public boolean isSomeElementDisplayed()
// public String getSomeElementText()
// public int getSomeElementsCount()
public Object getSomeData() {
WebElement element = driver.findElement(someElement2);
// do something with the element and return
}
}
Use pages in your tests, do not work with WebDriver directly.
#Test
public void someTest() {
Page page = new Page(driver);
page.doStep1();
page.doStep2();
assertEquals(page.getSomeData(), "Some expected result", "Optional Error message");
}
And..
Start from creating a test scenario code, create test steps, which you like to have (methods, which will be underlined in IDE as non-existing), and think about the data, which you like to check.
Then just implement all the non-existing methods you need in Page classes.
Maybe it sounds complicated, but try to start from simple test scenarios and it should become more clear after some practice.
I had the same issue. If this is a Java project, with Eclipse and Intellij IDEA, you can right click the project and select Convert to Maven. From there, it's fine adjustments (versions) in the POM file.
im trying to make test in Eclipse, using Selenium and Firefox webdriver. I wrote next class:
public class Selenium {
FirefoxDriver driver;
#BeforeTest
public void setup(){
driver = new FirefoxDriver();
}
#Test
public void go_to(String url){
driver.get(url);
}
Now in my main class im trying do that:
String url = JOptionPane.showInputDialog("Please input where do you want to go");
selenium.setup();
report.start_report();
selenium.go_to(url);
But also, i want to write
if(selenium.driver.getStatus)
Is there any command, to take boolean value, from my driver.get(url)? For example, if successful go to web page, then true, and if error, then false?
I`m trying to implement cucumber with Page Object Model and i faced couple problems and have lots of questions.
My iOS app is not that complex, but i still want to orginize all stepdefs and features to correspond with pages from POM. So i will have multiple stepdefs and runners. What is best practice to organize all of it ? I tried Pico DI, but wasn`t even able to pass my driver instance through it.( If you can, please provide structure solution)
Since its native iOS - Im not going to close app after every scenario( it will take forever). But I still want to keep features DRY for re-usability
What would be the best way to create one appium driver instance and never create another until feature is executed? I understand i just need to add driver.quit in the last step. What i`m straggling with is to use same driver throughout all project(Pages, Stepdefs) (see code)
Im going to run tests with TestNg and wonder if #Before #After annotations still work in stepdefs or it`s better to avoid them ?
The MAIN question : Dependency Injection with pico. Since all my tests are acceptance (end to end feature tests) i wonder if it is good idea to create one InjectionSetUp class which will contain all my pages AND driver
Driver manager
public class IOSDriverManager {
public static ThreadLocal<IOSDriver<IOSElement>> webDriver = new ThreadLocal<IOSDriver<IOSElement>>();
public static DesiredCapabilities getIOSCapsLocal() {
DesiredCapabilities caps = new DesiredCapabilities();
//My caps
return caps;
public static void createThreadLocalWebDriver() {
IOSDriver<IOSElement> driver = null;
//try catch
driver = new IOSDriver<IOSElement>(new URL(APPIUM_SERVER_URL), getIOSCapsLocal());
//try catch
webDriver.set(driver);
}
public static IOSDriver<IOSElement> getThreadLocalDriver() {
IOSDriver<IOSElement> driver = webDriver.get();
if (driver == null) {
createThreadLocalWebDriver();
driver = webDriver.get();
}
return driver;
}
BasePage
public class BasePage {
IOSDriver<IOSElement> Driver;
public BasePage(IOSDriver<IOSElement> driver) {
initElements();
Driver = driver;
}
private void initElements() {
PageFactory.initElements(new AppiumFieldDecorator(getDriver()),this);
}
protected IOSDriver<IOSElement> getDriver() {
return IOSDriverManager.getThreadLocalDriver();
}
}
AnyPage
public class BiosurveyPage extends BasePage {
public BiosurveyPage(IOSDriver<IOSElement> driver) {
super(driver); // Appiumfield decorator is applied by BasePage constructor
//Is it better to just use getDriver() method throughout all pages instead of declaring driver again ?
}
Finaly StepDefs
public class newSignUpFlowTest{
protected IOSDriver<IOSElement> getDriver() {
return IOSDriverManager.getThreadLocalDriver();
}
LoginPage poLogin = new LoginPage(getDriver());
SignUpPage poSignup = new SignUpPage(getDriver());
// 10+ pages
#Given("I am on Login Page")
public void iAmOnLoginPage() {
assertThat("ON LOGIN PAGE",poLogin.isLoginScreen(),equalTo(true));
}
#When("I tap on Sign Up Link")
public void iTapsOnSignUpLink() {
poLogin.clickSignUp();
}
// 20+ methods for this feature
UPDATE
I fixed everything and able to run tests. Now my question is - does my framework look decent ? I dont have any real life experience prior to this. So can someone just approve me and suggest enhancements to keep up with best industry practices ? I know this post might piss some people off, but i dont know where else to communicate this as i don`t have any friends in the QA field and working remotely
When using dependency injection you want to let your DI system do all the heavy lifting. So your step definitions have a constructor dependency on your page objects.
public class NewSignUpFlowStepDefinitions {
private final LoginPage poLogin;
private final SignUpPage poSignup;
NewSignUpFlowStepDefinitions(LoginPage poLogin, SignUpPage poSignup) {
this.poLogin = poLogin;
this.poSignup = poSignup;
}
#Given("I am on Login Page")
public void iAmOnLoginPage() {
assertThat("ON LOGIN PAGE", poLogin.isLoginScreen(), equalTo(true));
}
#When("I tap on Sign Up Link")
public void iTapsOnSignUpLink() {
poLogin.clickSignUp();
}
}
You page objects can't have a constructor dependency on IOSDriver<IOSElement> because PicoContainer can only create dependency chains that don't end with empty constructors. So instead we use the IOSDriverManager here.
public class BiosurveyPage extends BasePage {
public BiosurveyPage(IOSDriverManager driverManager) {
super(driverManager);
}
}
In your BasePage you then unpack the webdriver from the driver manager.
public abstract class BasePage {
private IOSDriverManager driverManager;
public BasePage(IOSDriverManager driverManager) {
this.driverManager = driverManager;
initElements();
}
private void initElements() {
PageFactory.initElements(new AppiumFieldDecorator(driverManager.getDriver()), this);
}
protected IOSDriver<IOSElement> getDriver() {
return driverManager.getDriver();
}
}
Then in the IOSDriverManager you can keep a reference to the webdriver and create it as needed. If you are certain it is safe to share your webdriver between scenarios you can still use a ThreadLocal here.
public class IOSDriverManager implements Disposable{
private IOSDriver<IOSElement> webDriver;
private DesiredCapabilities getIOSCapsLocal() {
DesiredCapabilities caps = new DesiredCapabilities();
return caps;
}
private void createWebDriver() {
webDriver = new IOSDriver<IOSElement>(new URL(APPIUM_SERVER_URL), getIOSCapsLocal());
}
public IOSDriver<IOSElement> getDriver() {
if (webDriver == null) {
createThreadLocalWebDriver();
}
return webDriver;
}
#Override
public void dispose() {
// Stop webdriver ehre
}
}
Note that Disposable adds the dispose method which will let you clean up your driver a after each scenario. Either to dispose it entirely or to reset it to some known state.
http://picocontainer.com/lifecycle.html
I don't know why I am getting 2 firefox browsers opened for the follwoing example. Can some one please tell me what is wrong in below code. I am new to cucumber and I am trying to develop cucumber poc with page object model.
Feature file:
Scenario: Smoke test for application
Given I am on home page
Step Defination file:
public class HomePageSteps {
CustomerDetails customerDetails;
HomePage homePage=new HomePage();
public HomePageSteps(CustomerDetails customerDetails){
this.customerDetails=customerDetails;
}
#Before
public void environmentSteup(){
homePage.envSetup();
}
#Given("^I am on home page$")
public void i_am_on_home_page() throws Throwable {
homePage.openURL();
}
}
Actual implementation of Step definition file:(HomePage.java)
public class HomePage extends BasePage{
public void openURL() {
driver.get("https://applicationURL.aspx");
System.out.println("I am on home page executed");
}
public void envSetup() {
driver=new FirefoxDriver();
driver.manage().window().maximize();
}
}
BasePage.java
public abstract class BasePage {
protected WebDriver driver=new FirefoxDriver();
}
CustomerDetails.java
public class CustomerDetails {
private String mdn=null;
private String Fname=null;
private String Lname=null;
public String getMdn() {
return mdn;
}
public void setMdn(String mdn) {
this.mdn = mdn;
}
}
2 firefox browsers are opened:
First it opens a blank browser. Later it opens another browser and in this browser it opens the application URL.
You have two calls to open browser windows...
Once in the sub-class in envSetup() - driver=new FirefoxDriver();
And in the super class driver variable declaration with initialization - protected WebDriver driver=new FirefoxDriver();
You have to remove one of them, no need for the super class one... This is the one giving you the blank window
Refer to this page. Your maximize() call in envSetup() might be doing more than you think
In selenium webdriver what is manage() [driver.manage()]
edit:
You also do not need to instantiate a new FirefoxDriver() outside of BasePage as you have already instantiated a driver field with that object. Anything extending BasePage will have access to that driver field. It is not a problem that you're doing this, it is just extraneous code that doesn't need to be there
I am fairly new to Selenium WebDriver and JUnit, I am testing a web app and was wondering is my class design correct in Junit for testing the UI?
As I have seen instances of where people have used composition.
Any advice would be greatly appreciated
Java Class
public class OverviewPage {
private WebDriver driver;
private String URL = "http://www.google.com";
public String searchQuery = "BBC";
OverviewPage(WebDriver driver){
this.driver = driver;
driver.get(URL);
if(!"Login".equals(driver.getTitle())){
throw new IllegalStateException("Wrong site");
}
}
By searchBox = By.id("siteSearchField");
By submitSearch = By.cssSelector("button.btn.searchIco");
public OverviewPage searchBox(String findADealer){
driver.findElement(searchBox).sendKeys(findADealer);
return this;
}
public OverviewPage searchBoxDisplayed(){
driver.findElement(searchBox);
return this;
}
public FindADealerPage searchResults(){
driver.findElement(searchBox).sendKeys(searchQuery);
driver.findElement(submitSearch).click();
String search = driver.getPageSource();
boolean searchResults = search.contains(searchQuery);
return new FindADealerPage(driver);
}
}
Junit
public class OverviewPageTest {
private WebDriver driver;
public String searchQuery = "find a dealer";
By searchBox = By.id("siteSearchField");
By submitSearch = By.cssSelector("button.btn.searchIco");
#Before
public void setUp(){
driver = new HtmlUnitDriver();
driver.get("http://www.google.com");
}
#After
public void tearDown(){
driver.quit();
}
#Test
public void checkTitle(){
Assert.assertEquals("product edit", driver.getTitle());
}
#Test
public void checkSearchBoxExists(){
boolean searchBoxes = driver.findElement(searchBox).isDisplayed();
Assert.assertTrue(searchBoxes);
}
#Test
public void searchResults(){
driver.findElement(searchBox).sendKeys(searchQuery);
driver.findElement(submitSearch).click();
String search = driver.getPageSource();
boolean searchResults = search.contains(searchQuery);
Assert.assertTrue(searchResults);
}
}
Your Java class OverviewPage suggests to me that you are wanting to use the PageObject model.
If you want to follow Google's example (https://code.google.com/p/selenium/wiki/PageObjects), you could put all the fields and methods pertaining to a particular page in the PageObject rather than the TestClass.
For example, in your TestClass, instantiate the PageObject:
OverviewPage page = new OverViewPage(driver);
and throughout your TestCalss, replace things like driver.get("http://www.google.com"); with driver.get(page.URL);
Basically what it boils down to is - you shouldn't have anything in quotes in your TestClass. The benefit of this pattern is when you have multiple tests referring to the same field in the PageObject, then when you need to update that field - you can do so easily in one place, rather than refactoring multiple lines of duplicate code throughout your tests.
Also, any given test needn't have more than two lines - a method call and an assertion.
So using your test searchResults() as an example, you could move the following lines into a method within the page object:
driver.findElement(searchBox).sendKeys(searchQuery);
driver.findElement(submitSearch).click();
String search = driver.getPageSource();
boolean searchResults = search.contains(searchQuery);
return searchResults; // added this one...
And your test becomes:
#Test
public void searchResults(){
boolean searchResults = page.searchResults();
Assert.assertTrue(searchResults);
}
That's my interpretation. Hope it helps!