I am writing a login function, I want this function to exit gracefully in case of an error/unexpected condition.example: when I enter the password, if the text field has changed/not present I want the function to exit with the message saying that password field is not present. the function status should be "Fail" and the exact failure message. same way it should handle any other exception that might occur. What is the right way to right this function, so that I can follow this practice in the future functions that I write that deals with web objects?
public boolean Login(String userName, String password, String url)
{
_driver= new FirefoxDriver();
_driver.manage().window().maximize();
_driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
_driver.get(url);
_driver.findElement(By.Xpath(".//*[id='usename']")).sendKeys(userName);
_driver.findElement(By.Xpath(".//*[id='pword']")).sendKeys(password);
_driver.findElement(By.Xpath(".//*[id='btn']")).click();
String title = _driver.getTitle();
boolean pass;
if (title.toLowerCase().contains("homepage"))
{
pass=true;
}
else
{
Assert.fail("Manager home page not opened after login");
pass=false;
}
return pass;
}
You would want to remove the driver setup and navigating to the initial URL from your function. Your function should only log in... to match the name, Login(). If you want to use the page object model, you would do something like
The main script would look like
_driver = new FirefoxDriver();
_driver.manage().window().maximize();
_driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
_driver.get(url);
LoginPage loginPage = new LoginPage(_driver);
loginPage.Login(userName, password);
Assert.assertTrue(_driver.getTitle().contains("homepage"), "Log in successful");
While the LoginPage class would look like
public class LoginPage
{
WebDriver _driver;
public LoginPage(WebDriver driver)
{
_driver = driver;
}
public void Login(String userName, String password)
{
_driver.findElement(By.id("usename")).sendKeys(userName);
_driver.findElement(By.id("pword]")).sendKeys(password);
_driver.findElement(By.id("btn")).click();
}
}
BTW, I changed your locators to use By.id() instead of XPath. You should avoid using XPath unless it's absolutely necessary... finding an element by containing text, etc. Start with By.id() then use By.cssSelector()... if those two won't work, then fall back to XPath. XPath is slower, more likely to be brittle, and has inconsistent support in browsers.
Related
I am setting up test cases for practice and trying to feed the parameters from an XML file for the website url, and the desired browser if available. The Switch logic, and webdriver commands look solid, but maybe i missed something that makes it skip them entirely. Should output that login was successful on both occasions.
In the past I've simply fed the data in as variables, this is my first try with xml handling the data injection.
public class NewTest {
WebDriver driver;
#Test(dataProvider="getData")
public void login(String username,String password)
{
//Code to Login to the application
driver.findElement(By.xpath("//*[#id=\'myNavbar\']/ul/li[4]/a")).click();
driver.findElement(By.id("usernameLogin")).sendKeys(username);
driver.findElement(By.id("passwordLogin")).sendKeys(password);
driver.findElement(By.id("login")).click();
try
{
//verifying the presence of webelement
````````````````````````````````````````````
new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.id("topMenu2")));
System.out.println("login success");
}
catch(Exception e)
{
System.out.println("Login failure");
}
driver.findElement(By.id("topMenu2")).click();
}
#DataProvider
public Object[][]getData() {
Object[][]data=new Object[2][2];
data[0][0]="pgGru";
data[0][1]="freezeray";
data[1][0]="pgAlmacho";
data[1][1]="freezeray";
return data;
}
#BeforeSuite
#Parameters({ "browsername", "url" })
public void setup(#Optional("Firefox")String browsername,String url) {
switch (browsername) {
case "IE":
WebDriver driver1;
driver1 = new InternetExplorerDriver();
System.setProperty("webdriver.IEDriverServer.driver", "D:\\Jarrrs\\Drivers\\IEDriverServer_win32");
driver1.get(url);
break;
case "Firefox":
WebDriver driver2;
driver2 = new FirefoxDriver();
System.setProperty("webdriver.geckodriver.driver","D:\\Jarrrs\\Drivers\\gecfkoDriver_win32");
driver2.get(url);
break;
case "chrome":
WebDriver driver3;
driver3 = new ChromeDriver();
System.setProperty("webdriver.chrome.driver, ","D:\\Jarrrs\\Drivers\\chromedriver_win32\\chromedriver.exe");
driver3.get(url);
break;
}
}
#AfterSuite
public void tearDown() {
driver.quit();
}
}
Right now the output is it is skipping the test cases for login and password
Expecting two passed or failed tests. Either one would be nice.
Newbie here. What do you mean by test is skipping? Are the actions within login() not being executed? I would put sys.out statements withing login() to check if the code is getting executed. How about adding a pause after page load? How about adding hardcoded value to username and password field to check if it is working fine?
Some times certain fields cannot be set by using Selenium's sendkeys. Need to use JavascriptExecutor to set the field values
I'm new in Selenium learning. I'm getting null pointer exception when I try to use web element - Milestone_Tile_Text.click; in my code but it works fine when I use
LoginTestScript.fd.findElement(By.linkText("Milestone")).click();
Please see below code I have used PageFactory.initElements as well but not sure how to solve this error.
public class MilestoneTileModel
{
GenerateTestData objtestdata = new GenerateTestData() ;
public MilestoneTileModel() //constructor
{
PageFactory.initElements(LoginTestScript.fd, this);
}
#FindBy(xpath="//a[text()='Milestone']")
WebElement Milestone_Tile_Text;
public void Milestone_Tile_Click()
{
Milestone_Tile_Text.click();
LoginTestScript.fd.findElement(By.linkText("Milestone")).click();
LoginTestScript.fd.findElement(By.xpath("//*#id='CPH_btnAddNewMilestoneTop']")).click();
}
}
Timing issues might occur more often when you use an init method.
The timing issue is when you init an element the driver immediately try to find the elements, on failure you will get no warning but the elements will refer null.
The above can occur for example because the page was not fully rendered or the driver see an older version of the page.
A fix can be to define the elements as a property and on the get of the property use the driver to get the element from the page
Please note that selenium does not promise the driver sees the latest version of the page so even this might break and on some situations a retry will work.
First problem what I see: You didn't set LoginTestScript
Following documentation at first you need to set PageObject variable:
GoogleSearchPage page = PageFactory.initElements(driver, GoogleSearchPage.class);
The best way to rich that point is separate Page Object Model and scenario scipt
You fist file POM should contain:
LoginTestPOM
public class LoginTestPOM {
#FindBy(xpath="//a[text()='Milestone']")
WebElement MilestoneTileText;
public void clickMilestoneTitleText(){
MilestoneTitleText.click();
}
}
TestScript
import LoginTestPOM
public class TestLogin {
public static void main(String[] args) {
// Create a new instance of a driver
WebDriver driver = new HtmlUnitDriver();
// Navigate to the right place
driver.get("http://www.loginPage.com/");
// Create a new instance of the login page class
// and initialise any WebElement fields in it.
LoginTestPOM page = PageFactory.initElements(driver, LoginTestPOM.class);
// And now do the page action.
page.clickMilestoneTitleText();
}
}
This is basis of Page Object Pattern.
NOTE: I'm writing that code only in browser so it could contain some mistakes.
LINK: https://github.com/SeleniumHQ/selenium/wiki/PageFactory
The "ugly" solution without page object pattern is:
UglyTestScript
public class UglyTestLogin {
public static void main(String[] args) {
// Create a new instance of a driver
WebDriver driver = new HtmlUnitDriver();
// Navigate to the right place
driver.get("http://www.loginPage.com/");
// DON'T create a new instance of the login page class
// and DON'T initialise any WebElement fields in it.
// And do the page action.
driver.findElement(By.xpath("//a[text()='Milestone']").click()
}
}
I have a question on how the PageFactory.initElements method of Selenium webdriver works when I use FindBy annotation
I have a snippet of code like this
Class PageObject {
#FindBy(id = "username")
private WebElement userName;
#FindBy(id = "password")
private WebElement passWord;
private WebDriver driver;
private String url = "http://www.loginpage.com";
public PageObject() {
driver = new FirefoxDriver();
PageFactory.initElements(driver, this);
}
void load() {
this.driver.get(url);
}
}
class TestClass {
public void testMethod() {
PageObject po = new PageObject();
po.load();
}
}
If I read documentation of the PageFactory.initElements method, it says - Instantiate an instance of the given class, and set a lazy proxy for each of the WebElement and List fields that have been declared, assuming that the field name is also the HTML element's "id" or "name".
My question here is when I create the object of the page in the test class, it fires the constructor of the page object and initializes the webelements using PageFactory. But what it would initialize to? I navigate to the page only after I construct the page object, using the load method. What would the PageFactory initialize my WebElements to when the page is not yet available. How does it work. Can somebody please help me understand this
Regards
Gauri
Here's what happens: When you call initElements, the PageObjectFactory scans your PageObject for fields of the type WebElement. For each WebElement field that your page object has, it creates a proxy object. That proxy object stores the locator of the WebElement (the value of the #FindBy annotation). The proxy is then assigned to the field.
Later, when your code actually accesses the field, instead of a WebElement object, you retrieve the proxy. Remember that the proxy object "knows" the locator of the WebElement it represents. Now the proxy actually tries to locate that locator on the current page, and returns the actual WebElement if it was found.
So, in your example, as long as you don't work with the userName or passWord fields, they won't be actually located. That means, that for example you wouldn't get a NoSuchElementException, even if the locators were wrong, unless you actually work with those elements.
So to answer your question: It doesn't matter that at the time when the PageObject is initialized the driver hasn't navigated anywhere yet, as the creation of the proxy objects doesn't actually locate them.
I want to skip the loading of whole web page and just want to check status of URL in selenium webdriver so that the execution can be much faster.
If you just want to check status of a page and don't need to bother about content inside that, you can just get response code and check if it is 200(HTTP_OK). I would suggest you use simple java to verify instead of trying to get it done with selenium webdriver. I just wrote a small program that does just that. See it this works fine for you. This tests if the web page can be successfully reached and didn't send back any 404 or 500 or any other error.
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpTest
{
public static void main(String[] args) throws IOException
{
URL url = new URL ( "http://www.google.com/");
HttpURLConnection conn = ( HttpURLConnection )url.openConnection ();
conn.setRequestMethod ("HEAD"); // GET will fetch the content of the page, which is not needed for your case.
conn.connect () ;
if(conn.getResponseCode() == HttpURLConnection.HTTP_OK)
System.out.println("Success");
}
}
What do you want to do? Do you want to click some links on a page and check whether they are redirecting to right URL? In this case you can try checking for change in URL. See the example below:
int i=0;
do{
try {
Thread.sleep(20);
} catch (InterruptedException e) {
}
i++;
} while(driver.getCurrentUrl().equals("The URL on which the page is originally.")&&i<10); //After URL changes, verify it.
Quick question about page objects in selenium webdriver. our site is very dynamic with lots of ajax and various authentication states. It is tough to figure out how to define each page object BUT lets say I have figured that out and defined several page objects that represent our site.
How do you handle crossing from page to page. So I get a page object for my home page and one for my account page and one for my results page. Then I need to write a test that traverses all my pages to simulate a user performing multiple actions.
How do you say give me a HomePage object to create a new use -> then get a account page object to go perform some user actions - then get a result page object to verify those actions all from a single script.
How are people doing this?
thanks
When you're simulating having the user enter a new URL into the URL bar of the browser, then it's the responsibility of the test class to create the page object it needs.
On the other hand, when you're doing some operation on the page that would cause the browser to point to another page -- for example, clicking a link or submitting a form -- then it's the responsibility of that page object to return the next page object.
Since I don't know enough about the relationships between your home page, account page, and result page to tell you exactly how it'd play out in your site, I'll use an online store app as an example instead.
Let's say you've got a SearchPage. When you submit the form on the SearchPage, it returns a ResultsPage. And when you click on a result, you get a ProductPage. So the classes would look something like this (abbreviated to just the relevant methods):
public class SearchPage {
public void open() {
return driver.get(url);
}
public ResultsPage search(String term) {
// Code to enter the term into the search box goes here
// Code to click the submit button goes here
return new ResultsPage();
}
}
public class ResultsPage {
public ProductPage openResult(int resultNumber) {
// Code to locate the relevant result link and click on it
return new ProductPage();
}
}
The test method to execute this story would look something like this:
#Test
public void testSearch() {
// Here we want to simulate the user going to the search page
// as if opening a browser and entering the URL in the address bar.
// So we instantiate it here in the test code.
SearchPage searchPage = new SearchPage();
searchPage.open(); // calls driver.get() on the correct URL
// Now search for "video games"
ResultsPage videoGameResultsPage = searchPage.search("video games");
// Now open the first result
ProductPage firstProductPage = videoGameResultsPage.openResult(0);
// Some assertion would probably go here
}
So as you can see, there's this "chaining" of Page Objects where each one returns the next one.
The result is that you end up with lots of different page objects instantiating other page objects. So if you've got a site of any considerable size, you could consider using a dependency injection framework for creating those page objects.
Well, I created my own Java classes which represent the pages:
Say, the below is code to represent home page. Here user can login:
public class HomePage{
private WebDriver driver;
private WebElement loginInput;
private WebElement passwordInput;
private WebElement loginSubmit;
public WebDriver getDriver(){
return driver;
}
public HomePage(){
driver = new FirefoxDriver();
}
public CustomerPage login(String username, String password){
driver.get("http://the-test-page.com");
loginInput = driver.findElement(By.id("username"));
loginInput.sendKeys(username);
passwordInput = driver.findElement(By.id("password"));
passwordInput.sendKeys(password);
loginSubmit = driver.findElement(By.id("login"));
loginSubmit.click();
return new CustomerPage(this);
}
}
And the page for Customer can look like this. Here I am demonstrating, how to get, say, logged in user:
public class CustomerPage{
private HomePage homePage;
private WebElement loggedInUserSpan;
public CustomerPage(HomePage hp){
this.homePage = hp;
}
public String getLoggedInUser(){
loggedInUserSpan = homePage.getDriver().findElement(By.id("usrLongName"));
return loggedInUserSpan.getText();
}
}
And the test can go like this:
#Test
public void testLogin(){
HomePage home = new HomePage();
CustomerPage customer = home.login("janipav", "extrasecretpassword");
Assert.assertEquals(customer.getLoggedInUser(), "Pavel Janicek");
}
You generally want to model what a user actually does when using your site. This ends up taking the form of a Domain Specific Language (DSL) when using page objects. It gets confusing with reusable page components though.
Now that Java 8 is out with default methods, reusable page components can be treated as mixins using default methods. I have a blog post with some code samples found here that explains this in more detail: http://blog.jsdevel.me/2015/04/pageobjects-done-right-in-java-8.html
I suggest you use a framework that provides support for these patterns. Geb is one of the best one out there. Below is an example taken from their manual
Browser.drive {
to LoginPage
assert at(LoginPage)
loginForm.with {
username = "admin"
password = "password"
}
loginButton.click()
assert at(AdminPage)
}
class LoginPage extends Page {
static url = "http://myapp.com/login"
static at = { heading.text() == "Please Login" }
static content = {
heading { $("h1") }
loginForm { $("form.login") }
loginButton(to: AdminPage) { loginForm.login() }
}
}
class AdminPage extends Page {
static at = { heading.text() == "Admin Section" }
static content = {
heading { $("h1") }
}
}
I enjoy writing Selenium Webdriver tests using the Page Object pattern. But was personally annoyed at the verbosity and repetition of having to always explicitly instantiate and return the next page or page component. So with the benefit of Python's metaclasses I wrote a library, called Keteparaha, that automatically figures out what should be returned from a selenium page object's method calls.