GlobTAAU4 eng-US
GlobTAAU4 eng-US
GlobTAAU4 eng-US
Selenium Webdriver
4.1 - Introduction and Locators
There is a driver for each of the browsers, whether it is Firefox, Chrome, IE, Safari,
etc.
The way in which the communication between Selenium Webdriver and the
browsers is carried out is the following:
4.2 - Getting Started with WebDriver
Locators
Imagine a scenario where we have to automate a web application with Selenium
Webdriver, where we have to simulate a user using the application to be able to
validate certain result, whether it is data entered, the existence of an element, a
message on the screen, etc.
As users, we browse the applications by clicking on links, we also fill out forms by
selecting data from combo boxes or text fields. Selenium Webdriver allows us to
identify each of these elements in different ways, and then do something with
them.
Let’s see then what the element locators supported by Selenium Webdriver are:
To identify elements in a website, we will use a tool that makes it easy to inspect
them, in this case, firebug, a Firefox add-on that helps with the task. It should be
noted that it is not necessary to use it, and that we can do the same by looking at
the source code of the page, but it helps a lot.
https://www.wikipedia.org/.
ID: The ID is a type of locator that should be unique per element. In case of
having elements with an ID, this is the recommended way to locate them.
By analyzing the HTML code of a website, we can find the locators. For example,
let’s see Wikipedia’s home page:
Going back to our previous example, we will see that we can identify the field
using the name search.
Link: This identifier allows us to identify elements of link type (a), using its text.
In Wikipedia’s home, we have a list of links with country names, each can be
identified by the text. Let’s see this example:
Let’s see how we can locate the search field we obtained by name and ID using
Xpath:
Xpath= //*[@id-search Input']
• DOM.
• CSS.
• Ill-element.
Recommended Locators
Therefore, it is good practice to use more stable locators, which last over time,
as a good automation strategy.
The recommended order of preference is then, the following:
1. ID
2. Name
3. CSS
4. XPATH
The ID is unique, and even if an element changes, if we have it identified it its ID,
it will keep working.
The name may not be unique, but it usually is, therefore it is our second option.
CSS and xpath are useful when we do not have the previous options, but they are
less stable and slower.
When to Use Xpath?
As we mentioned earlier, we can use xpath when we do not have other elements,
such as ID or name, but it is not the only occasion where we can use it.
As an example, suppose we have an HTML table, if you are not familiar with the
structure of a table, we can think of it as a list of rows containing cells.
Let’s see the table we have as example in:
http://www.w3schools.com/html/html tables.asp.
If we wanted to identify cell 1:1 through xpath, we will see that it is:
.//*[@id-customers']/tbody/tr[2]/td[1]
If we wanted to have a function that adds values to a table, we could use this to
iterate cells in a column in a table, get the values, add them and return the result.
Advanced Xpath
//*[@id=,customers,]/tbody/tr/td[contains(text(),"'Roland")]
Basically, this function returns the cell (TD) containing “Roland”, and inside an
element with ID = customers.
//*[@id=,customers,]/tbody/tr[last()-1]/td[last()]
Starts-With: This command allows us to locate an element with a text, ID, name,
etc. that starts with certain text, for example, to select Roland Mendel’s column,
using starts-with, we could say:
//*[@id=,customers,]/tbody/tr[4]/td[starts-with(text(),"Roland")]
4.3 - The Page Object Model (POM) Pattern
The PageObject pattern allows us to organize the elements that we are going to
use in our tests. If we define and declare the elements within our test cases, we
will have a high cost of maintenance, as well as little code reusability.
For this, there is this pattern based on declaring our pages, whether they are
complete or only fragments, in a code class, which we can then use in our tests.
We will then define, using the Wikipedia example, a page. For that, we will use
wikipedia.org’s home page:
The first thing we will do is create a new package to keep our code organized, we
will call it: com.automation.training.pages.
Within it, we will create a class called BasePage, and a class called
WikiHomePage, and we will define the elements that we are going to use.
The BasePage class will contain every method common to all pages, as well as
who will access the selenium driver. Let’s see its content:
It receives in its constructor an object of the Webdriver type, which has already
been created, but we will see in more detail later. Basically, that object is an
instance of the driver we are using.
Then, in its constructor, it calls PageFactory, which is the method responsible for
initializing the elements defined in the page.
This class also has a dispose method, which is responsible for closing the driver;
this closes the open instance of the browser as well as all the open sessions.
Returning to our WikiHomePage, we will implement the elements that we are
going to use, in this case, the search field and the search button:
As we can see, Selenium allows us to use a very simple syntax for declaring the
elements of a page, in this case we use the annotation @FindBy and declare
them by ID and xpath.
We declare them always as private, since the page is responsible for using them
and exposing only the functionalities that we are interested in. For this example,
we are going to implement a search, which should be defined in the page. Since
the search returns a new page, in this case, one with an article, we will create a
class, for now empty, called ArticlePage. It is good practice to have each action of
a page returning another one return the other page ready to be used in the tests.
As we can see, this function receives a search string and then calls searchInput -
> SendKeys (in charge of writing in the field) with the string. Then, it clicks the
search button, returning a new page called ArticlePage.
Let’s now create the ArticlePage, which is the page that will contain the elements
of the article. Suppose we want to do a couple of validations in that page, for
example, that the title appears according to the search, and that it has a link to
Wikipedia’s privacy policies at the bottom.
For this, we need to define those two elements, the title and the link, to be able to
do a validation in our tests. We should also create a method to return the content
of the title, to validate that it is according to the Search string:
We already have two pages, and we can create our first test, as we will see later.
}
4.3.1 - Legacy between Pages
It is worth mentioning that one page can inherit from another one, to make our
code more reusable and understandable.
In the Wikipedia example, we will see that many pages maintain the left column
and the header; therefore, it is a good practice when designing our pages to
create a page with that content and make the others, such as ArticlePage, inherit
from that, in this way, we can access all the menu items from any page, without
re-declaring the element in each of them.
4.4 - Our First Test Case
A test case is a set of actions with a validation, which serves to verify that a
functionality does what it is expected to do.
The actions are those that we have previously defined in the created pages,
that is, in the example we have so far, we could create a test that does a
search on Wikipedia, and then validate the result page.
Before writing the test case, let’s see how we can structure our classes to have a
secure framework.
}
>
public WebDriver getDriver() {
return this.driver;
>
As we can see, the constructor receives a Browser parameter and based on it, it
initializes one or the other. It is a very simple class that also adds a getDriver
method that allows us to access it.
Going back to our BaseTests class:
This class handles three important things:
@BeforeSuite:
It is responsible for initializing the myDriver variable with the corresponding
browser; in turn, it initializes the wikiHomePage page, which in its constructor, as
we saw earlier, initializes the browser and goes to wikipedia.org.
@AfterSuite
This method is responsible for calling the Dispose method, which as we saw
previously, it is responsible for closing the browser.
getWikiHomePage
This method returns the instance of the homePage that we are going to use.
Having then our BaseTests class, which includes all the methods that we will use
in our tests, we can create our specific class for test cases, which we will call
WikiTests, and which will extend from BasePage.
It will contain a method called testWikiSearch, which will be our test case; for this
reason we will write it with the annotation @Test.
As we see, it is very simple to understand:
In this example, we see how we ask WebDriver to wait 10 seconds for the
element to be clickable: if it is clickable before, the action will be executed before,
if the 10 seconds pass, an error will be returned.
Example
We will create an explicit wait in our BasePage, for that we will add the following
lines to it:
Example
Then, from our pages, we can call the getWait() function to wait for an
item, for example, the search button:
Which Wait Strategy should we Use?
We strongly suggest to always use explicit waits, we even suggest that the implicit
should always equal 0.
4.6 - iFrames - Alerts - Popups
When we have iFrames or Alerts that we want to manage, we need to change the
context in which Selenium WebDriver works.
driver.switchTo().frame(,,id-del-iframe");
Once this is done, we are inside the iFrame and we can continue working as we have
been doing.
An alert is a browser popup with certain message, it is usually a message with
options like accept or cancel. In order for selenium to be able to handle them, we
have to somehow tell it to do something with it, for that, we can use the following
commands:
driver.switchTo().alert();
driver.switchTo().alert().accept();
When we have a popup that is a new page opening, we need to know the window
handles. A handle is a unique identifier of each window, and we can obtain the list of
them through:
driver.getWindowHandles()
This, if for example we have the original window and a popup, will return two handles,
on which we can iterate to make the switch: