• No results found

4.Which Implementation of WebDriver Should I Use?

In document Selenium (Java) (Page 119-130)

WebDriver is the name of the key interface against which tests should be written, but there are several implementations. These are:

Name of driver Operating

System

Class to instantiate

HtmlUnit Driver Firefox Driver

Internet Explorer Driver Windows Chrome Driver All

All

You can find out more information about each of these by following the links in the table. Which you use depends on what you want to do. For sheer speed, the HtmlUnit Driver is great, but it’s not graphical, which means that you can’t watch what’s

happening. As a developer you may be comfortable with this, but sometimes it’s good to be able to test using a real browser, especially when you’re showing a demo of

your application (or running the tests) for an audience. Often, this idea is referred to as “safety”, and it falls into two parts. Firstly, there’s “actual safety”, which refers to whether or not the tests works as they should. This can be measured and

quantified. Secondly, there’s “perceived safety”, which refers to whether or not an observer believes the tests work as they should. This varies from person to person, and will depend on their familiarity with the application under test, WebDriver, and your testing framework.

To support higher “perceived safety”, you may wish to choose a driver such as the Firefox Driver. This has the added advantage that this driver actually renders content to a screen, and so can be used to detect information such as the position of an element on a page, or the CSS properties that apply to

it. However, this additional flexibility comes at the cost of slower overall speed. By writing your tests against the WebDriver interface, it is possible to pick the most appropriate driver for a given test. To keep things simple, let’s start with the

4.1 HtmlUnit Driver:

WebDriver driver = new HtmlUnitDriver();

4.2 Navigating

The first thing you’ll want to do with WebDriver is navigate to a page. The normal way to do this is bycalling “get”:

driver.get( "http://www.google.com" );

WebDriver will wait until the page has fully loaded (that is, the “onload” event has fired) before returning control to your test or script. It’s worth noting that if your

page uses a lot of AJAX on load then WebDriver may not know when it has completely loaded. If you need to ensure such pages are fully loaded then you can use “waits”.

4.3 Interacting With the Page

Just being able to go to places isn’t terribly useful. What we’d really like to do is to interact with the pages, or, more specifically, the HTML elements within a page. First of all, we need to find one.

WebDriver offers a number of ways of finding elements. For example, given an element defined as:

<input type= "text" name= "passwd" id= "passwd-id" />

you could find it using any of:

WebElement element;

element = driver.findElement(By.id( "passwd-id" ));

element = driver.findElement(By.name( "passwd" ));

element = driver.findElement(By.xpath( "//input[@id=’passwd-id’]" ));

You can also look for a link by its text, but be careful! The text must be an exact match! You should also be careful when using XPATH in WebDriver. If there’s more than one element that matches the query, then only the first will be returned. If nothing can be found, a NoSuchElementException will be thrown. WebDriver has an

“Object-based” API; we represent all types of elements using the same interface:

Web Element. This means that although you may see a lot of possible methods you could invoke when you hit your IDE’s auto-complete key combination, not all of them will make sense or be valid. Don’t worry! WebDriver will attempt to do the Right Thing, and if you call a method that makes no sense (“setSelected()” on a “meta”

tag, for example) an exception will be thrown.

So, you’ve got an element. What can you do with it? First of all, you may want to enter some text into a

text field:

element.sendKeys( "some text" );

You can simulate pressing the arrow keys by using the “Keys” class:

element.sendKeys( " and some" , Keys.ARROW_DOWN);

It is possible to call sendKeys on any element, which makes it possible to test keyboard shortcuts such as those used on GMail. A side-effect of this is that typing something into a text field won’t automatically clear it. Instead, what you type will be appended to what’s already there. You can easily clear the contents of a text field or textarea:

element.clear();

Filling In Forms -~~~~~~~~~~~~~~~

We’ve already seen how to enter text into a textarea or text field, but what about the other elements? You can “toggle” the state of checkboxes, and you can use

“setSelected” to set something like an OPTION tag selected. Dealing with SELECT tags isn’t too bad:

WebElement select = driver.findElement(By.xpath( "//select" ));

List<WebElement> allOptions = select.findElements(By.tagName( "option" ));

for (WebElement option : allOptions) {

System.out.println(String.format( "Value is: %s" , option.getValue()));

option.setSelected();

}

This will find the first “SELECT” element on the page, and cycle through each of it’s OPTIONs in turn, printing out their values, and selecting each in turn. As you can see, this isn’t the most efficient way of dealing with SELECT elements. WebDriver’s

support classes include one called “Select”, which provides useful methods for interacting with these.

Select select = new Select(driver.findElement(By.xpath( "//select" )));

select.deselectAll();

select.selectByVisibleText( "Edam" );

This will deselect all OPTIONs from the first SELECT on the page, and then select the OPTION with the displayed text of “Edam”. Once you’ve finished filling out the form, you probably want to submit it. One way to do this would be to find the “submit”

button and click it:

driver.findElement(By.id( "submit" )).click();

// Assume the button has the ID "submit" :)

Alternatively, WebDriver has the convenience method “submit” on every element. If you call this on an element within a form, WebDriver will walk up the DOM until it finds the enclosing form and then calls submit on that. If the element isn’t in a form, then the NoSuchElementException will be thrown:

element.submit();

4.4 Getting Visual Information And Drag And Drop

Sometimes you want to extract some visual information out of an element, perhaps to see if it’s visible or where it is on screen. You can find out this information by casting the element to a RenderedWebElement:

WebElement plain = driver.findElement(By.name( "q" ));

RenderedWebElement element = (RenderedWebElement) element;

Not all drivers render their content to the screen (such as the HtmlUnit Driver), so it’s not safe to assume that the cast will work, but if it does you can gather additional information such as the size and location

4.5 Moving Between Windows and Frames

It’s rare for a modern web application not to have any frames or to be constrained to a single window. WebDriver supports moving between named windows using the

“switchTo” method:

driver.switchTo().window( "windowName" );

All calls to driver will now be interpreted as being directed to the particular window.

But how do you know the window’s name? Take a look at the javascript or link that opened it:

<a href= "somewhere.html" target= "windowName" >Click here to open a new window</a>

Alternatively, you can pass a “window handle” to the “switchTo().window()” method.

Knowing this, it’s possible to iterate over every open window like so:

for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle);

}

You can also swing from frame to frame (or into iframes):

driver.switchTo().frame( "frameName" );

It’s possible to access subframes by separating the path with a dot, and you can specify the frame by its index too. That is:

driver.switchTo().frame( "frameName.0.child" );

would go to the frame named “child” of the first subframe of the frame called

“frameName”. All frames are evaluated as if from *top*.

4.6 Navigation: History and Location

Earlier, we covered navigating to a page using the “get” command (driver.get("http://www.example.com"))

As you’ve seen, WebDriver has a number

of smaller, task-focused interfaces, and navigation is a useful task. Because loading a page is such a fundamental requirement, the method to do this lives on the main WebDriver interface, but it’s simply a synonym to:

driver.navigate().to( "http://www.example.com" );

To reiterate: “navigate().to()” and “get()” do exactly the same thing. One’s just a lot easier to type than the other! The “navigate” interface also exposes the ability to move backwards and forwards in your browser’s history:

driver.navigate().forward();

driver.navigate().back();

Please be aware that this functionality depends entirely on the underlying browser.

It’s just possible that something unexpected may happen when you call these methods if you’re used to the behaviour of one browser over another.

4.7 Cookies

Before we leave these next steps, you may be interested in understanding how to use cookies. First of all, you need to be on the domain that the cookie will be valid for:

// Go to the correct domain

driver.get( "http://www.example.com" );

// Now set the cookie. This one’s valid for the entire domain Cookie cookie = new Cookie( "key" , "value" );

driver.manage().addCookie(cookie);

// And now output all the available cookies for the current URL Set<Cookie> allCookies = driver.manage().getCookies();

for (Cookie loadedCookie : allCookies) {

System.out.println(String.format( "%s -> %s" , loadedCookie.getName(), loadedCookie.getValue()));

}

6. WebDriver Implementations

5.1 HtmlUnit Driver

This is currently the fastest and most lightweight implementation of WebDriver. As the name suggests, this is based on HtmlUnit.

¾ Fastest implementation of WebDriver

¾ A pure Java solution and so it is platform independent.

¾ Supports JavaScript

¾ Emulates other browser’s JavaScript behavior

JavaScript in the HtmlUnit Driver

None of the popular browsers uses the JavaScript engine used by HtmlUnit (Rhino). If you test JavaScript using HtmlUnit the results may differ significantly from those browsers.

When we say “JavaScript” we actually mean “JavaScript and the DOM”. Although the DOM is defined by the W3C each browser out there has its own quirks and differences in their implementation of the DOM and in how JavaScript interacts with it. HtmlUnit has an impressively complete implementation of the DOM and has good support for using JavaScript, but it is no different from any other browser: it has its own quirks and differences from both the W3C standard and the DOM implementations of the major browsers, despite its ability to mimic other browsers.

With WebDriver, we had to make a choice; do we enable HtmlUnit’s JavaScript capabilities and run the risk of teams running into problems that only manifest themselves there, or do we leave JavaScript disabled, knowing that there are more

and more sites that rely on JavaScript? We took the conservative approach, and by default have disabled support when we use HtmlUnit. With each release of both WebDriver and HtmlUnit, we reassess this decision: we hope to enable JavaScript by default on the HtmlUnit at some point.

5.2 Declaring Browsers in WebDriver

WebDriver Run with Firefox Browser:

WebDriver driver = new FirefoxDriver();

WebDriver Run with InternetExplorer Browser:

WebDriver driver = new InternetExplorerDriver();

Convert Selenium-RC code to WebDriver code:

//First Declare WebDriver:

WebDriver driver = new FirefoxDriver();

// Create the Selenium implementation

Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);

// Perform actions with selenium

selenium.open( "http://www.google.com" );

selenium.type( "name=q" , "cheese" );

selenium.click( "name=btnG" );

//Now you can Execute

5.3 Firefox profile Handling in WebDriver

Suppose that you wanted to modify the user agent string (as above), but you’ve got a tricked out Firefox profile that contains dozens of useful extensions. There are two ways to obtain this profile. Assuming that the profile has been created using Firefox’s profile manager (firefox -ProfileManager):

ProfileIni allProfiles = new ProfilesIni();

FirefoxProfile profile = allProfiles.getProfile( "WebDriver" );

profile.setPreferences( "foo.bar" , 23);

WebDriver driver = new FirefoxDriver(profile);

Alternatively, if the profile isn’t already registered with Firefox:

File profileDir = new File( "path/to/top/level/of/profile" );

FirefoxProfile profile = new FirefoxProfile(profileDir);

profile.addAdditionalPreferences(extraPrefs);

WebDriver driver = new FirefoxDriver(profile);

Enabling features that might not be wise to use in Firefox

As we develop features in the Firefox Driver, we expose the ability to use them. For example, until we feel native events are stable on Firefox for Linux, they are disabled by default. To enable them:

FirefoxProfile profile = new FirefoxProfile();

profile.setEnableNativeEvents(true);

WebDriver driver = new FirefoxDriver(profile);

7. Locators or Properties

1. Id 2. Name

3. Class or classname 4. Linktext

5. Partial link text 6. Normal xpath 7. Absolute xpath

In document Selenium (Java) (Page 119-130)