Selenium Tutorial: Learn Selenium WebDriver

banner_WebDriver

 

By Alan Richardson for Udemy

Interested in more than just a guide? Check out Alan’s full Selenium WebDriver course.

TABLE OF CONTENTS: CLICK TO JUMP TO A SPECIFIC SECTION

Background

What WebDriver ‘is’
What WebDriver ‘does’

Installing the Tools

Installing Java JDK
Installing Maven
Installing IntelliJ
Installing Firefox
Installing WebDriver

Create a New Project in IntelliJ

Add dependencies to the Maven pom.xml file

Our First WebDriver Test

Create a Test Class
Create a JUnit Test Method
Let’s Open Firefox
Code Explained
Now let’s click on something

WebDriver and WebElement

Using Code Completion to Learn
WebDriver methods
WebElement methods

Synchronization

Implicit Wait
Explicit Wait

Summary


Modern software development processes want to develop software quickly and reliably. To reduce the risk of regression defects, they automate the application to allow fast and reliable checking of test conditions after each change.

If you are working on web applications, then the first automation tool you’ll want to get familiar with is Selenium WebDriver. Fortunately, Selenium WebDriver is open source and supports multiple programming languages, making it easy to introduce into your development project.

This tutorial will help you get started with Selenium WebDriver and provide a short introduction to the WebDriver API. All examples are provided in Java.

Completely new to software testing? Learn the basics of technical web testing in this course.

By the end of this tutorial, you will have installed all the tools need to run the following code, which will open the seleniumhq.org website, navigate to the downloads and check that the title of the page is “Downloads”.

WebDriver driver = new FirefoxDriver();
driver.get("http://seleniumhq.org");
 
WebElement downloadTab = driver.findElement(By.id("menu_download"));
WebElement downloadLink = downloadTab.findElement(By.tagName("a"));
downloadLink.click();
 
Assert.assertEquals("Downloads", driver.getTitle());
 
driver.quit();

Background

First, a little background so you understand what Selenium WebDriver is and what it does.

What WebDriver ‘is’

“Selenium” is the name of the project and includes a number of tools and APIs: Selenium IDE, Selenium RC, Selenium WebDriver, and Selenium Grid. You can find the homepage for the Selenium Project at seleniumhq.org

  • Selenium IDE is a Firefox plugin which allows users to record and play back actions in the browser.
  • Selenium-RC was the first tool in the Selenium project that allowed automation of web applications in browsers. This has been deprecated, although it is still functional in the project, and WebDriver is now the recommended tool for browser automation.
  • Selenium WebDriver is the Selenium project supported browser automation tool. It consists of a set of libraries for different programming languages and ‘drivers’ (small applications) which can automate actions in browsers.
  • Selenium Grid allows you to run automation remotely on multiple browsers, and on other machines.

For the rest of this tutorial, we will refer to Selenium WebDriver as simply  WebDriver.

WebDriver has libraries (or language bindings) for multiple programming languages: Java, C#, Ruby, JavaScript, Python, PHP, Perl, and others. This allows software development teams to use WebDriver with the language they are most familiar with. You do not have to learn a proprietary scripting language unique to WebDriver. You use WebDriver like any other library you add to your project.

WebDriver uses ‘drivers’ to control different browsers. At the moment drivers exist for Firefox, Chrome, Safari and Internet Explorer. Microsoft is working on a driver for Microsoft Edge. The Firefox driver is built in to WebDriver, so Firefox is often the default browser used for automation by most projects. Other drivers are small applications that you install separately.

WebDriver communicates to the ‘driver’ using a JSON protocol that has a become a W3C standard. This means that browser vendors are more likely to support WebDriver and create their own drivers. The hope is that Microsoft will take ownership of an IE driver and that Apple will take ownership of the Safari driver.

WebDriver also has a mobile driver called Appium which allows test code to run on mobile devices and tablets.

Because WebDriver has the Selenium Grid, this has allowed cloud vendors to create ‘grids’ of browsers so you can run your tests on multiple versions of Firefox, Chrome, IE, and on multiple operating system combinations. These cloud services cost money, but are much more affordable, in terms of the time it would take, than setting up your own internal grid with lots of machines and browser combinations.

Essentially the Selenium ecosystem is very wide, and allows you to test on local desktops, local mobile devices, cross platform so you don’t have to use Windows, or Mac – you can use both – or Linux. You can choose the programming language that suits your team and project best. You can also run your tests in parallel and on remote machines. All you have to do is put in the time to learn how to use WebDriver.

To learn more about Selenium and automated testing, check out this course on web application testing with Selenium.

What WebDriver ‘does’

WebDriver automates browsers. Essentially WebDriver lets you open URLs and interact with the rendered pages, e.g.:

  • start new instances of a browser
  • open URLs in the browser
  • click on links on the rendered page
  • type into the fields in the rendered page
  • execute JavaScript in the rendered page

WebDriver is not a tool for testing REST APIs, or SOAP APIs, or databases.

WebDriver is a tool for automating browsers.

Because WebDriver is essentially a ‘library’ and you use a normal programming language, you can use any other library that your programming language supports to call other APIs or databases.

I frequently use other Java libraries in combination with WebDriver to let me access the database to check results and use REST libraries to make API calls, and then check results on the web pages with WebDriver.

Using a library instead of a framework gives you more flexibility in how you approach your automation.

Installing the Tools

To work with WebDriver with Java we need to install some tools:

  • Java JDK

the Java compiler and libraries

  • Maven

a dependency management tool for Java

  • IntelliJ

an IDE for programming Java

  • Firefox

the default browser used by WebDriver

  • JUnit

A Unit testing framework for Java that we will use to execute our test code

  • WebDriver

The Selenium WebDriver

Installing Java JDK

You can tell if you have the Java JDK installed by issuing the command javac -version at the command line.

C:\Users\Alan>javac -version
 javac 1.8.0_40

On Mac, if you type the above command, and don’t have Java installed then you will be asked if you want to install it.

On Windows and Mac, you can install the Java JDK by following the instructions on the Oracle website:

Installing Maven

You can find instructions to install Maven on the ‘Apache Maven Project’ homepage:

Installing IntelliJ

Download the ‘Community Edition’ of IntelliJ from jetbrains.com:

The ‘Community Edition’ is free and open source. On all the Enterprise Java projects I’ve worked on, IntelliJ has been the most popular IDE due to its ease of installation and productivity features, including built-in refactoring.

You can use other IDEs, e.g., Eclipse. But I’ve found that IntelliJ works out of the box far more easily than Eclipse, and when you are learning, you want to minimize the amount of installation issues you might face. And since IntelliJ is the choice of the best Java developer I know, it will grow with you as you improve your automation and development skills.

When you start IntelliJ for the first time, you may be given the opportunity to customise it. Instead, choose the button marked “Skip All and Set Defaults”.
image00

You can close IntelliJ down now until we need it to install WebDriver.

Installing Firefox

You can install Firefox by visiting:

And downloading and following the install instructions for your platform.

Installing WebDriver

We don’t actually install WebDriver. Instead we use Maven to manage our project dependencies and we add WebDriver as a dependency in our project.

Create a New Project in IntelliJ

To do this, we startup IntelliJ and create a new project using the “Create New Project” on the “Welcome to IntelliJ IDEA” dialog.
image02

You will then see the “New Project” dialog where you will select “Maven” as the Project type.

If the Project SDK is not automatically shown in the drop-down then use the [New…] button to find the location of your Java SDK; on Windows this is usually C:\Program Files\Java\ and then the folder of the JDK you are using, e.g., if you are using JDK 8u40 then it would be in the subfolder jdk1.8.0_40

image01

After selecting [Next] you will type in the Maven GroupId and ArtifactId values. For this tutorial you can simply write myFirstWebDriverTest as both the GroupId and the ArtifactId.

image04

Then click [Next] and choose the name and location for your project.

I’m using the name myFirstWebDriverProject and stored it in location C:\Users\Alan\IdeaProjects\myFirstWebDriverProject.

IntelliJ will then open the project for us.

In the top right of the screen you may see a dialog prompting you to enable auto import for Maven. I suggest you click “Enable Auto Import” as it will allow you to make changes to the project and IntelliJ will automatically import and refresh the project contents.

image03

IntelliJ will now show you the IDE with the Project view on the left side of the screen, and it will have opened the project’s pom.xml file on the right.

image06

The Project pane shows you the source code for your project, and you can see IntelliJ has created a src\main\java hierarchy and a src\test\java folder hierarchy. All of our test code will be added to the src\test\java hierarchy.

You can also see a myFirstWebDriverProject.iml file and .idea folder. These are IntelliJ project files storing the configuration details.

The important file here is the pom.xml file, which you can see at the root of your project folder, and can see the contents of, on the right-hand side.

Add dependencies to the Maven pom.xml file

A pom.xml file is a file that Maven uses to build and configure a project. We will add our dependencies into this pom.xml file and Maven will download them for us, compile and build our Java project, and run our tests.

We will add a dependencies section to this file to allow us to use JUnit and WebDriver in our project.

At the time of writing, I can see that the current versions of JUnit and WebDriver are:

JUnit 4.12

from JUnit Download and Install page

WebDriver 2.47.1

from Selenium Maven Information page

To add these as dependencies in the project, I add a <dependencies> section in my pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>myFirstWebDriverTest</groupId>
 <artifactId>myFirstWebDriverTest</artifactId>
 <version>1.0-SNAPSHOT</version>

 <dependencies>
 
 </dependencies>
</project>

Within the dependencies xml block, I copy and paste the information from the JUnit install page and the WebDriver install page so that my pom.xml file looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>myFirstWebDriverTest</groupId>
    <artifactId>myFirstWebDriverTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.47.1</version>
        </dependency>
    </dependencies>
</project>

The above basically means that my project is dependent upon:

  • version 4.12 of JUnit
  • version 2.47.1 of Selenium WebDriver

Since these projects are updated frequently, make sure you check the official install pages and use the dependency xml information listed there, and the most up-to-date version numbers.

Once you have added this information into the pom.xml file in IntelliJ, because we enabled auto imports, IntelliJ will download the necessary files to let us use JUnit and IntelliJ. These will be stored in the local Maven folder .m2

  • On Windows in folder %USERPROFILE%\.m2
  • On Linux and Mac, in folder ~\.m2

We can now start writing a test that uses JUnit and WebDriver to automate a web application.

Our First WebDriver Test

To write a JUnit Test which uses WebDriver, we need to create a Java Class.

Create a Test Class

Right-click with the mouse on the java folder in the Project hierarchy and select New \ Java Class.

image05

Using the “Create New Class” dialog, name the class MyFirstWebDriverTest, and press [OK].

image08

IntelliJ will then create a MyFirstWebDriverTest.java file in the project for us, and open it in the IDE to allow us to edit it.

image07

It is important that in Java, the class names start with uppercase letters, and that when we write JUnit test classes, that we add Test in the name of the class. This allows Maven to execute the tests when we type mvn test at the command line, or during Continuous Integration.

You don’t need the comments that IntelliJ has added, so you can delete the lines at the top of the class like:

/**
 * Created by Alan on 14/08/2015.
 */

Create a JUnit Test Method

The tests we write in Java with JUnit are methods annotated with @Test.

E.g.:

@Test
public void checkSeleniumHQinFirefox(){
}

If you add the above method code into your Java class, you will notice that IntelliJ highlights @Test in red, and identifies it as an error.

image11

This is because we haven’t imported the JUnit Test object.

We can do that by clicking on @Test and pressing the keys alt + enter. Then in the menu that appears, select Import Class.

You may be provided with a list of classes at this point. If so, you want to choose org.junit.Test.

IntelliJ will then add the import statement to the code for our @Test method:

import org.junit.Test;

At this point you should see no red text on the screen and IntelliJ should not be reporting any errors.

Let’s Open Firefox

Now, let’s add some code to the body of the method so that our test will open Firefox, and navigate to the official Selenium homepage, and then close the browser.

    @Test
    public void checkSeleniumHQinFirefox(){
        WebDriver driver = new FirefoxDriver();
        driver.get("http://seleniumhq.org");
        driver.quit();
    }

When you add this code, you’ll need to add imports for WebDriver and FirefoxDriver. You can do that by pressing alt + enter.

You should have the following imports added at the top of your code.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

If all has gone well, then you will have no errors in your code and your MyFirstWebDriverTest.java will look as follows:

import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class MyFirstWebDriverTest {
    @Test
    public void checkSeleniumHQinFirefox(){
        WebDriver driver = new FirefoxDriver();
        driver.get("http://seleniumhq.org");
        driver.quit();
    }
}

Now let’s run the test.

We can do this by right-clicking on the method name and selecting Run from the pop-up menu.

image09

You should then see:

  • IntelliJ run the test
  • Firefox should open
  • Firefox will get the URL “http://seleniumhq.org” and load the official Selenium homepage
  • Firefox will then quit and the test will finish

Congratulations – you just used WebDriver to automate a browser.

Want to create more advanced tests? Check out how to use Selenium 2 WebDriver to create powerful automated tests.

Code Explained

Now, let’s look at this code in more detail.

WebDriver driver = new FirefoxDriver();
driver.get("http://seleniumhq.org");
driver.quit();

We create a new instance of Firefox by instantiating a new FirefoxDriver(). This will open Firefox for us.

WebDriver is the Interface that all ‘drivers’ implement. By declaring my driver variable of type WebDriver I can easily amend my code later to use use any instantiated driver – e.g., IE, Chrome, or a remote driver – to execute tests on a browser on another machine.

In this example, you could replace WebDriver with FirefoxDriver and the test will still work the same way. As an exercise, try it for yourself. Change the code to use FirefoxDriver and run the test again.

FirefoxDriver driver = new FirefoxDriver();

Change the code back. Get in the habit of coding to the WebDriver interface when you instantiate a driver.

We then use the get method from the WebDriver interface:

driver.get("http://seleniumhq.org");

get takes a String as an argument, and this is the URL that we wish to open in the browser.

driver.quit();

The quit method closes the browser for us.

WebDriver also has a close method.

The close method closes the last opened browser tab, and if it is the last tab open, will also close the browser.

The quit method closes the browser, no matter how many tabs are open.

Run the test from the command line

Because we are using Maven, we can easily run the test from the command line. This is helpful when we want to add our test code into continuous integration.

To quickly run the test from the command line, you can open a command line in the root directory of your project.

In my case, I would open a terminal or command prompt and change to C:\Users\Alan\IdeaProjects\myFirstWebDriverProject and then tell Maven to run the tests mvn test

> cd C:\Users\Alan\IdeaProjects\myFirstWebDriverProject
> mvn test

Maven would then compile the project and run the tests:

[INFO] Scanning for projects...
 [INFO]                                                                         
 [INFO] ------------------------------------------------------------------------
 [INFO] Building myFirstWebDriverTest 1.0-SNAPSHOT
 [INFO] ------------------------------------------------------------------------
 [INFO] 
 [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ 
 myFirstWebDriverTest --- 
 [debug] execute contextualize
 [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, 
 i.e. build is platform dependent!
 [INFO] Copying 0 resource
 [INFO] 
 [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ 
 myFirstWebDriverTest ---
 [INFO] Nothing to compile - all classes are up to date
 [INFO] 
 [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) 
 @ myFirstWebDriverTest ---
 [debug] execute contextualize
 [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, 
 i.e. build is platform dependent!
 [INFO] skip non existing resourceDirectory 
 C:\Users\Alan\IdeaProjects\myFirstWebDriverProject\src\test\resources
 [INFO] 
 [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @
  myFirstWebDriverTest ---
 [INFO] Nothing to compile - all classes are up to date
 [INFO] 
 [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ myFirstWebDriverTest ---
 [INFO] Surefire report directory: 
 C:\Users\Alan\IdeaProjects\myFirstWebDriverProject\target\surefire-reports
 
 -------------------------------------------------------
 T E S T S
 -------------------------------------------------------
 Running MyFirstWebDriverTest
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.776 sec
 
 Results :
 
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
 
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESS
 [INFO] ------------------------------------------------------------------------
 [INFO] Total time: 5.409s
 [INFO] Finished at: Fri Aug 21 13:36:43 BST 2015
 [INFO] Final Memory: 8M/245M
 [INFO] ------------------------------------------------------------------------

Now let’s click on something

When we are using WebDriver, there are two very important classes:

  • WebDriver
  • WebElement

You’ve already used WebDriver; that is the main interface that represents our browser.

WebElement is a class that represents an object on the page.

The Selenium homepage has a set of links across the top of its page.

image10

We are going to click on the [Download] tab and navigate to the downloads page.

To do that, we have to find the element on the page.

WebDriver provides a findElement method to help us do this, but we need to know what to tell it to find. So we have to inspect the page in the browser to find out what we can use.

I do this using the built-in development tools for browsers.

Since we are using Firefox, I’ll load up “seleniumhq.org” in Firefox. Then right-click on the [Download] tab and select Inspect Element (Q) from the pop-up menu.

image12

This will show me the Development tools. With the element I right-clicked on, highlighted in the “DOM and Style Inspector”:

image13

The important parts of the HTML for our purpose are:

image14

We can see here that the download link is an anchor with a title of “Get Selenium”, wrapped with an li tag, and the li tag has an id of “menu_download”.

The findElement method takes a By object as parameter. We generally instantiate the By object using static methods on the By class:

  • By.id

find an element by using the id attribute of the element. This is very useful since an id is supposed to be unique in the dom so this can uniquely locate an element on a well-formed page

  • By.linkText

the link text is the text between the <a></a> tags; in the example above, the a tags are empty and have no link text.

  • By.partialLinkText

find an element which contains some text in the anchor tag

  • By.name

if an element has a name attribute, then you can use that to locate the element

  • By.tagName

we can find elements using the tag, e.g., li or a

  • By.className

if the tag has a class attribute, then we can use that to locate the element

  • By.xpath

Xpath is a very powerful language for matching elements in an XML document

  • By.cssSelector

CSS Selectors are used in CSS to locate elements for styling; we can use the same syntax to find elements on the page

By looking at the HTML snippet we have, since the li has an id, we can uniquely find the li dom element.

driver.findElement(By.id("menu_download"))

But we want to click on the a element, i.e., the link.

Fortunately, driver.findElement returns a WebElement object, and the WebElement class has a findElement method so we can ‘chain’ these commands and I can:

  • first find the li element by the id
  • then use the li element to find the a by the tagname

driver.findElement(By.id("menu_download")).findElement(By.tagName("a"))

To make the code easier to read, I will create variables to store the WebElement objects:

WebElement downloadTab = driver.findElement(By.id("menu_download"));
WebElement downloadLink = downloadTab.findElement(By.tagName("a"));

And having found the downloadLink all that remains is to use the WebElement method click to click on the link.

WebElement downloadTab = driver.findElement(By.id("menu_download"));
WebElement downloadLink = downloadTab.findElement(By.tagName("a"));
downloadLink.click();

findElement will only match the first item found. This is important when using anything other than By.id since all of the other approaches can match multiple elements, i.e., there are more than 1 li tags on the page so if I used By.tagName("li") to find the li element, it would match the first one on the page, rather than the one I was looking for.

By.xpath and By.cssSelector are the most powerful selectors available. Most people use CSS Selectors rather than Xpath, because this is supported by every browser. These selectors are beyond the scope of this tutorial, but you can find a lot of useful information online, and in particular I recommend the XPath, CSS Rosetta stone.

Just to demonstrate how powerful a CSS Selector is, I could combine both findElement commands into a single CSS Selector of #menu_download a.

WebElement downloadLink = driver.findElement(By.cssSelector("#menu_download a"));
  downloadLink.click();

It is well worth researching CSS Selectors, but when starting to learn WebDriver, you can do a lot with the basic id, name, linkText and className selectors.

Now that we know how to navigate between pages by clicking on elements, it is important that our @Test method can check that we are on the correct page and that our navigation worked.

We do this by using the Assert class from JUnit, to assert that some condition has been met.

For this test, I’m going to take advantage of the title on the page. For the download page, the title is “Downloads”; we can see that either in the tab on the browser or in the HTML itself when we use the developer tools.

image15

If only WebDriver had a way to access the title of a page…

Fortunately, the WebDriver interface exposes a getTitle method, so I can use that in a JUnit assert to check that we are on the correct page:

Assert.assertEquals("Downloads", driver.getTitle());

This uses the static assertEquals method from the org.junit.Assert class to compare the string “Downloads” with the value returned from the getTitle method.

If they are the same, then the assert will pass and the test will pass.

If they are different, then the assertion will fail and throw an exception. This will be reported in IntelliJ as a failing test.

E.g., if I change the assertion to:

Assert.assertEquals("Uploads", driver.getTitle());

Then this will fail, because the expected value “Uploads” does not equal the Actual value returned by the getTitle method, which is “Downloads”.

image16

The test in full is shown below, in case you made any mistakes typing the code.

import org.junit.Assert;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class MyFirstWebDriverTest {
    @Test
    public void checkSeleniumHQinFirefox(){
        WebDriver driver = new FirefoxDriver();
        driver.get("http://seleniumhq.org");

        WebElement downloadTab = driver.findElement(By.id("menu_download"));
        WebElement downloadLink = downloadTab.findElement(By.tagName("a"));
        downloadLink.click();

        Assert.assertEquals("Downloads", driver.getTitle());

        driver.quit();
    }
}

WebDriver and WebElement

The two main classes that you use for WebDriver testing are WebDriver and WebElement.

WebDriver represents the browser and has general methods for controlling the browser and accessing generic elements or parts of the page.

WebElement represents an element on the page and supports methods related to that element, e.g., click, returning the text in the element, returning attributes, etc.

We will now look at these methods in greater detail, and show you how you can learn more yourself.

Using Code Completion to Learn

We can use the existing code we’ve written to help us see the range of methods available to us on the WebDriver class.

If I put the cursor in IntelliJ, just after driver. and then press ctrl  + space I will see a pop-up menu showing the methods that I can call from WebDriver:

image17

In the pop-up you can see that we can:

  • findElement – find an element on the page
  • get – go to a URL
  • getTitle – return the title of the page as a string
  • close – close the tab
  • findElements – return a List of WebElement objects that match the locator, e.g., find all the anchor elements on the page
  • getCurrentUrl – return the current URL; this might be useful if we have been redirected to another page
  • getPageSource – return the source code of the page
  • etc.

Code completion is a great way to explore the possibilities open to us when we are testing.

In addition, we can look at the JavaDoc help for any of these methods by pressing ctrl + Q in Windows (ctrl + J on Mac) to see the library documentation for the method.

image18

With this little trick you can learn a lot about the API and the methods, from within the IDE.

WebDriver methods

The WebDriver methods tend to be methods you can use at any point in time – i.e., the context is having a page loaded in the browser.

You have already seen some of these methods, so we won’t repeat those here.

  • getWindowHandle – returns a list of handles to all open tabs
  • switchTo – allows to you switch focus to an open tab or a frame
  • manage – allows you to control the current browser details, e.g., view and amend cookies, change the size and location of the browser window
  • navigate – provides an alternative to the get command so you can `navigate().to(aUrl)’

WebElement methods

The WebElement methods tend to be local to a specific element on the page.

You have already seen:

  • click which triggers a mouse click on the element
  • findElement which helps you find a child element

If you use code completion in the IDE, then you will see that we can also:

  • clear – clear the text in an input field
  • findElements – find children of the element
  • getAttribute – get a value of an attribute, e.g., class or id
  • getTagName – the tag name for the element, e.g., li or a
  • getText – get the text in the element, e.g., the link text
  • sendKeys – send keys to type into the field

We can also check the status of the element:

  • isDisplayed – Is the element visible?
  • isEnabled – Can we interact with the element?
  • isSelected – Is it selected?

There are more methods on WebElement but the above list covers those that you would use most often.

Synchronization

The above are the basics that would help you work with many web pages. You would be able to load pages into the browser, find elements on the page, click and interact with them, and retrieve text from the page to check your results.

And for very simple websites, this is probably all you need to know.

For more complicated websites and applications, synchronization becomes important.

This means, rather than:

  • open a page
  • find a link
  • click the link
  • check the title on the new page

Instead, we would:

  • open a page
  • wait for the page to be loaded and ready to use
  • find a link
  • click on the link
  • wait for the page to be loaded and ready to use
  • check the title on the new page

The above approach becomes important when the web application we are testing uses a lot of JavaScript to populate the page, or for a single-page app that is only one page, but the DOM changes via JavaScript based on user actions.

WebDriver provides two main approaches to synchronization.: a built-in synchronization approach called implicit wait, and a more user-controlled approach known as explicit wait.

Implicit Wait

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

The implicit wait is configured by using the manage timeouts functionality from the WebDriver API.

By setting the implicitlyWait value on timeouts I’m basically telling WebDriver that “whenever I try to findElement on a page, I want you to keep trying, and only timeout after 10 seconds”.

For example, if I load a page, and the page makes some AJAX requests to populate part of the DOM, then when I try to findElement it will not have loaded yet, so WebDriver would throw a NoSuchElementException exception and my test would fail.

The implicit wait provides a mechanism for avoiding that. By setting the implicit wait timeout to 10 seconds, if I try to findElement part of the DOM that has not yet finished loading by AJAX, then WebDriver will:

  • try to find it,
  • fail,
  • but instead of throwing a NoSuchElementException exception,
  • WebDriver will wait for 500 milliseconds,
  • then WebDriver will try to find it again

WebDriver will repeat the above loop until:

  • it finds the element, and will then return it, or
  • the timeout time of 10 seconds has been reached, at which point WebDriver will throw a NoSuchElementException

This seems like a very easy way to synchronize with your application and AJAX requests. But, since the implicit wait timeout is set as a global, you can’t wait for some elements for 5 seconds and others for 25 seconds, so you have to set the timeout for the highest value you think you need.

This means that, if a test should fail, because the element really is not on the page, then your test will wait 25 seconds before failing, and when you have a lot of tests, this can cause the test execution to slow down.

Also, sometimes we use findElement to make sure that an element is not present on the page. If you are using implicit waits, then every call to make sure that an element is not present on the page will take the maximum timeout time – again leading to slow tests.

Because of the above reasons, when we work on production code, we prefer to use explicit waits rather than implicit waits. This is why the default implicit wait time in WebDriver is set to 0 seconds, forcing you to think about your synchronization approach.

Explicit Wait

Explicit wait in WebDriver is handled by the WebDriverWait class.

WebDriverWait wait = new WebDriverWait(driver, 10);

The above creates a WebDriverWait object, associated with the current driver, where the timeout time is set to 10 seconds.

You ‘wait’ until a particular ‘expected condition’ is true.

E.g.:

wait.until(ExpectedConditions.elementToBeClickable(downloadLink));

When starting with WebDriverWait, I recommend that you use the built-in ExpectedConditions class to help you.

WebDriverWait and ExpectedConditions are part of the WebDriver support classes:

import org.openqa.selenium.support.ui.ExpectedConditions;
 import org.openqa.selenium.support.ui.WebDriverWait;

ExpectedConditions contains a lot of statically accessible methods which can help us wait for a variety of element states in the DOM.

For example, I could wait for an element to be present in the DOM. This doesn’t mean that it is visible or ready for use, but it means it has been loaded into the DOM:

WebElement downloadLink = wait.until(
   ExpectedConditions.presenceOfElementLocated(
      By.cssSelector("#menu_download a")));

In the above code, I am waiting until the download link is present in the DOM. And you can see that the until method actually returns the WebElement so I don’t need an additional findElement statement.

I can also wait until elements are clickable:

wait.until(ExpectedConditions.elementToBeClickable(downloadLink));

A full list of Expected Conditions is available from code completion within the IDE, but to give you an idea of the supplied synchronization methods, I list the ones I use most often below:

  • presenceOfElementLocated

Waits for an element to be present in the DOM; returns the WebElement

  • visibilityOfElementLocated

Waits for an element to be visible; returns true if the element is visible

  • invisibilityOfElementLocated

Waits for an element to be invisible; returns true if the element is not visible

  • elementToBeClickable

Waits for element to be clickable, i.e., visible and enabled; returns the WebElement

  • alertIsPresent

Waits for an alert to be present; returns the alert if present

  • titleIs

Waits for the title to match a specific value

  • elementSelectionStateToBe

Waits for an element to be selected or not

  • frameToBeAvailableAndSwitchToIt

Waits for a frame to be available and switches to it so we can interact with the contents of the frame

  • titleContains

Waits for the title to contain a String; returns true when title matches

  • urlContains

Waits for the URL to contain a specific String

  • urlMatches

Waits for the URL to match a specific regular expression

  • urlToBe

Waits for the URL to be an exact String

With the WebDriverWait, if the ExpectedCondition is not met then a TimeoutException is thrown.

If the supplied ExpectedConditions does not have an exact match for the condition that you need to wait for, then you can create your own ExpectedCondition and wait for specific conditions related to your application. An explanation of this is beyond the scope of this introductory article, but you can always use ‘ctrl + left-click’ to click through to the source code of any of the ExpectedConditions methods and see how they have been implemented and copy the pattern into your own code.

You can see that in the test we have an assertion that matches on title:

Assert.assertEquals("Downloads", driver.getTitle());

When you start learning about expected conditions, the temptation might be to replace the Assert with an expected condition, e.g.:

wait.until(ExpectedConditions.titleIs("Downloads"));

If the ExpectedCondition check fails, then a TimeoutException would be thrown, which would fail the test, but it may not be as clear to read as an Assertion.

Also, an Assert in the @Test method makes it clear that the method is checking for this particular condition, rather than expecting it in passing.

I try to keep my ‘wait’ code specific for synchronization and have assertions for the conditions that I want to check in the @Test.

Summary

Even though this was a very brief introduction to WebDriver, you have learned the basics needed to get started.

  • You know how to install the tools
  • You’ve seen how to create a basic test
  • You know how to start a new browser and navigate to a URL
  • You know how to interrogate the page with methods on the WebDriver class
  • You know how to findElement on the page and then interrogate it and manipulate it with methods on the WebDriver class
  • You know the importance of synchronizing on specific DOM states, rather than implicitly wait for elements to be accessible
  • You know how to explicitly wait for elements on the page prior to interacting with them to make your tests robust

This should be enough to help you get started writing code against production systems, and create fairly robust tests.

Selenium WebDriver offers you more than this, which we haven’t been able to cover.

When you become more experienced with WebDriver, you’ll want to use the features that let you run your tests on multiple browsers, i.e., Chrome, IE, and Safari, and not just Firefox.

You might want to experiment with the HmlUnitDriver to run your tests ‘headless’, i.e., without creating a browser. For more complicated tests, you might have to add more synchronization or use different browser capabilities. But for the simple test we wrote in this article, you could use HtmlUnitDriver by replacing FirefoxDriver as follows:

WebDriver driver = new HtmlUnitDriver();

You can also run your tests on other machines using the RemoteWebDriver; this allows you to connect to a WebDriver Grid and run your test on different browser and operating system combinations. You can also use this to take advantage of cloud-based grid providers so you don’t have to maintain a lot of physical machines with different operating system and browser combinations.

As you expand your automation, you’ll want to learn how to create your own custom ExpectedCondition methods and synchronize on application-specific conditions; this will help keep your test code simple to maintain, more domain-specific and easier to read.

As you build more tests, you’ll want to move away from having driver. code in your tests, and instead start using a Page Object Model approach, where you create classes that represent your Pages, and you write your tests in terms of Page Object methods, e.g.:

HomePage homePage = new HomePage(driver);
homePage.navigationMenu().clickDownload();

Writing Page Objects and Domain Object abstractions helps keep your tests maintainable and easier to make robust with effective synchronization.

The WebDriver API will also let you automate mobile native applications, hybrid apps and automate the browser on mobile devices by using Appium.

For more complicated websites, you’ll want to learn a little JavaScript and take advantage of WebDriver’s ability to inject and run arbitrary JavaScript on the web page using the JavascriptExecutor.

The future for WebDriver continues to look bright and makes it an excellent investment in terms of time to learn and skill development.

A few hints to help you proceed further:

  • Use code completion to see the methods available.
  • Use the JavaDoc to see what a method does.
  • Read the documentation on the SeleniumHQ.org homepage.
  • If your tests are randomly failing, then it is probably a synchronization problem, so add some WebDriverWait to your code.
  • No matter how tempting it is to increase the implicit wait timeout, don’t. Use WebDriverWait instead.
  • If your test passes when you debug and step through line by line, but fails when your run the test, then assume it is a synchronization problem and you need to add an effective `WebDriverWait’.

Best of luck with your future learning and experimentation with WebDriver.



Selenium IDE Tutorial

BY KASIA MIKOLUK

Selenium IDE is a fully-featured Integrated Development Environment (IDE) that installs as a plugin in Mozilla Firefox and enables developers to test their web applications through Selenium. With the Selenium IDE, you can record user interactions with the web browser and play them back to test for errors. It’s a powerful, robust IDE that radically simplifies and automates the QA testing process.

In this tutorial, we’ll learn the basics of the Selenium IDE, how to use it, and what you can use it for. To learn more about software and web application testing, check out this course on Selenium IDE and WebDriver.

What is Selenium IDE?

Selenium is a web application testing software developed by Jason Huggins in 2004. It’s an open-source software that works on all three major platforms – Windows, Mac and Linux. Selenium supports a wide range of languages, including, but not limited to, Java, Python, Ruby, Perl, C# and PHP. The best part? Selenium enables you to test web applications with zero knowledge of any test scripting language.

This brings us to Selenium IDE. As mentioned above, the Selenium IDE is a Firefox plugin that makes it possible to record, edit and debug tests. It was developed independently of the Selenium project by Shinya Kasatani and was merged with the former in 2006. It was previously known as the Selenium Recorder; don’t be surprised if you stumble upon old tutorials mentioning it by that name!

How to Use Selenium IDE?

The Selenium IDE is currently available only on Firefox. Chrome users might want to look at alternatives like iMacros, Sahi and Scirocco.

First of all, install Selenium IDE in Firefox by grabbing a copy of the software from the Selenium HQ. It’ll install as a set of 5 extensions with separate formatters for Python, Ruby, etc. (language formatters are optional; install formatters only for languages you want to use). Once installed, restart Firefox. If you now go to the main Firefox options menu -> Add Ons -> Extensions, you should see Selenium IDE along with language formatters for Ruby, Python, C# and Java.

1

You are now ready to use Selenium. Below, we’ll learn how to record and play back actions using Selenium.

Using Selenium

To use the Selenium IDE, go to Firefox -> Web Developer -> Selenium IDE.

2

Alternatively, press CTRL + ALT + S to open the Selenium IDE window.

 3

Let’s take a closer look at the Selenium IDE window:

  • The left pane lists all the open test cases.
  • The ‘Base URL’ shows the URL the test is being performed on.
  • The ‘Table’ pane will show a list of actions recorded as part of the test. You can see how this works in the example below.
  • The ‘Fast-Slow’ slider dictates how fast/slow playback for the recorded test should be.
  • The ‘Play’ button plays back the test.
  • The big red button at the rightmost edge is the ‘Record’ toggle switch. Switch it on to record interactions on any website.
  • The bottom pane shows a log of actions and a reference list.

There are a number of other options – Selenium IDE is a fairly powerful tool, after all – but for now, we only need to be concerned with the options listed above.

New to software testing? Learn the basics of technical web testing in this course!

Creating a Simple Test in Selenium IDE

For the purpose of this tutorial, we will create a simple test that will enter a particular query into Google. In essence, this will be more like a macro than an actual ‘test’, but it will demonstrate the power of automated testing using Selenium IDE.

Step 1: Create a new test case by going to File -> New Test Case.

4

A new untitled test should show up in the test case pane to the left.

5

Step 2: We are now going to record our test. To do this, hit the red record switch to the right.

6

Now, perform the following actions in sequence:

1. Type in Google.com into your Firefox address bar:

72. On the Google.com homepage, search for any query. For this example, we used the query ‘automated testing.

3. Once the results page opens, stop the test by clicking the red toggle switch.

Step 3: Now that we’ve recorded the test, let’s play it back.

This is what your ‘Table’ pane should look like now:

8

Click on the ‘Play current test case’ button.

9

This will automatically open Google.com, type in ‘automated testing’ into the query field, and display the search results.

If you take a closer look at the two commands in the Table pane, you’ll see that you can not only change the command, but also alter the values associated with it.

For example, the first command is ‘open’. You can change this to anything else – Selenium IDE offers a huge list of built-in commands. You can also change the ‘Target’ url to anything that you like.

10

The next command is ‘type’. This basically instructs Selenium to type-in the desired query into the search bar. You can change the query to anything you want by changing the ‘value’.

11

For example, if you change it to ‘red and orange widgets’, Selenium IDE will automatically query ‘red and orange widgets’ into Google.

12

This is one of the most basic examples of what Selenium IDE can do. By combining different commands, you can make the IDE run complex tasks and test for bugs automatically.

Want to create more advanced tests? Learn Selenium 2 WebDriver to create powerful automated tests.

Using Selenium IDE Contextual Menu

Besides the Selenium IDE window, the plugin also installs a contextual menu into Firefox that can be accessed by pressing the right mouse button.

Let’s see an example of how it works:

Like the previous example, create a new test case and hit ‘record’. Then go to Google.com, type in a query (‘automated testing’) and wait for the search results page to load.

After the results page opens, right click on the main search field on Google. A contextual menu will pop up with a list of actions you can perform.

13

At the bottom of the menu, you’ll see a ‘verifyValue’ option. If you select this option, Selenium will make sure that there is always a value present in the search bar – a simple test.

14

You can also see a list of all available commands on the same menu. This will give you a huge list of commands to choose from like ‘verifyTitle’, ‘verifyValue’, ‘open’, ‘storeTitle’, etc.

15

Using these different options, you can create automated tests to check different elements in a web app. For this example, if you stop the recording and play back the test, Selenium IDE will first open Google.com, type in the desired query, and finally, verify that the query has been entered into the search bar.

16

Selenium IDE is a very powerful tool for making QA tests. You can combine different commands, use the contextual menu, and even create your own commands through Selenium.

To learn more about Selenium and automated testing, check out this course on web application testing with Selenium.