Category Archives: WebDriver

Upgrade to Selenium WebDriver 2.53.0 and ChromeDriver 2.21

Selenium WebDriver 2.53.0 is available
Selenium WebDriver 2.53.0 is available

Upgrade to Selenium WebDriver 2.53.0

I’ve just updated my online Selenium 2 WebDriver with Java course to use version 2.53.0 of Selenium WebDriver. Change Log

I mainly update due to browser changes but this update required a code fix.

Selenium WebDriver 2.53.0

Minor code fix in the pom.xml to add a dependency on the new Htmlunit driver project.

github.com/SeleniumHQ/htmlunit-driver

The package structure in the htmlunit driver was left the same so all I had to amend was the pom file

<webdriver.version>2.53.0</webdriver.version>
<junit.version>4.11</junit.version>
<hamcrest.version>1.3</hamcrest.version>
<htmlunitdriver.version>2.20</htmlunitdriver.version>

And the include for HTMLUnit became:

<!-- from WebDriver 2.53.0 HTMLUnit is no longer buy propranolol online in uk distributed with Selenium WebDriver -->
<!-- https://github.com/SeleniumHQ/htmlunit-driver -->
<!-- need to bring in the htmlunit driver on its own -->
<!-- https://github.com/SeleniumHQ/selenium/blob/master/java/CHANGELOG -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>htmlunit-driver</artifactId>
    <version>${htmlunitdriver.version}</version>
</dependency>

ChromeDriver 2.21

I also had to update my build machine to use 2.21 ChromeDriver.

When I did this I discovered that this version has fixed some Cookie bugs when working against Google Chrome.

code.google.com/p/selenium/issues/detail?id=7499

So I amended my tests to cater for this as well.

I’ve uploaded the code to my online training course existing students can download the amended code from the course materials section.

Posted in Selenium Simplified Blog, Training Courses, WebDriver | Leave a comment

Can I use Selenium WebDriver to automate a Windows Desktop Application?

A question posted on the forum of my Selenium WebDriver course. “Can I use Selenium WebDriver to automate a Windows Desktop Application?”

I have updated and expanded the answer I provided on the course forum into this blog post.

Answer:  No. WebDriver is Web only. But…

Since WebDriver has a RemoteWebDriver architecture, people have created RemoteWebDriver implementations which aim to automate Windows Applications:

Some options that I have not tried, based around WebDriver:

AutoIt

I have not had to automate windows for a long time.

When I last automated Windows I used AutoIt:

I started work on my own Java Windows Automation API, but I haven’t kept that up to date since I haven’t had to automate windows. JWinAuto on sourceforge.

Andrew Davis has created a similar implementation called JAU.​

Also available is the AutoIt4Java implementation:

You might also consider AutoHotKey, a simple language like AutoIt and widely used.

I have heard of…

I have heard of people successfully using White:

I have also heard people successfully use Sikuli:

Other standalone tools:

Posted in Selenium Simplified Blog, WebDriver | 10 Comments

Generic Selenium WebDriver Grid Configuration Handling to use BrowserStack, Saucelabs and TestingBot

Image taken from page 103 of ‘Der Beobachter. Allgemeine Anleitung zu Beobachtungen u?ber Land und Leute.

In my Selenium WebDriver with Java course I have a Driver.java abstraction class.

I use an abstraction class so that in the @Test methods we make a call to Driver.get rather than individual firefox or chrome drivers, or RemoteDrivers

And the configuration of this is adjusted via the actual code, or a mix of environment variables and properties.

I was looking at some Mac Grid issues that I was helping Brian Long investigate. And I realised that my Generic Grid handling wasn’t as Generic as it needed to be to support my debugging.

I amended my code so that I could configure my Driver.java with either environment variables or properties:

  • Environment Variables are handy because they are system wide and you can configure them on the machine, but they are a bit of a pain to work with because you have to restart the console and IDE when you change them.
  • Properties are handy because you can pass them into mvn test jobs with -D parameters e.g. mvn test -Dparam=value and this makes it very easy to use them in CI

I primarily use IntelliJ and in the Run \ Edit Configuration section you can override environment variables, and pass in -D params so it is possible to work with these in the IDE.

I find it easier to override environment variables in the IDE because the GUI makes it easy to amend them in a list.

I find it easier to configure the CI jobs through properties by passing them in as -D to mvn test

Therefore I amended my Driver.java code to not care if its configuration comes from environment variables or properties

e.g.

String gridBrowser = getPropertyOrEnv("WEBDRIVER_GRID_BROWSER", "firefox");
String gridBrowserVersion = getPropertyOrEnv("WEBDRIVER_GRID_BROWSER_VERSION", "");
String gridBrowserPlatform = getPropertyOrEnv("WEBDRIVER_GRID_BROWSER_PLATFORM", "");

DesiredCapabilities gridCapabilities = new DesiredCapabilities();
gridCapabilities.setBrowserName(gridBrowser);
if(gridBrowserVersion.length()>0)
    gridCapabilities.setVersion(gridBrowserVersion);
if(gridBrowserPlatform.length()>0)
    gridCapabilities.setPlatform(Platform.fromString(gridBrowserPlatform));

And getPropertyOrEnv looks as follows


/**
 * Allow setting the controls via property or environment variable
 * property takes precedence, then environment variable, then default
 */
private static String getPropertyOrEnv(String name, String theDefault){

    String theValue = System.getProperty(name);
    if(theValue == null){

        System.out.println("Could not find Property " + name);
        theValue = System.getenv(name);

        if(theValue==null){

            System.out.println("Could not find Environment Variable " + name + " using default value " + theDefault);
            theValue = theDefault;

        }else{
            System.out.println("Using Environment Variable " + name + " with value " + theValue);
        }
    }else{
        System.out.println("Using Property " + name + " with value " + theValue);
    }

    return theValue;
}

This supported my local debugging, CI and console mvn test triggering.

But as with most tasks related to automating systems, I should expect to encounter additional maintenance and workarounds. And such was the case when I tried to execute the tests against BrowserStack in addition to Saucelabs and my local grid.

Basic Saucelabs configuration uses the capabilities:

  • browser
  • platform
  • browser_version

Basic BrowserStack configuration uses the capabilities

  • os
  • os_version
  • browser
  • browser_version

And of course, with BrowserStack we want it to take screenshots to track the @Test method execution so we need to set

  • browserstack.debug=true

Since I have a ‘generic’ grid config in my Driver.java I wanted to support the extra capabilities in a more generic way.

And I still wanted to allow them to be configured via environment variables or properties.

So, I run through all the environment variables and properties looking for any name prefixed with WEBDRIVER_GRID_CAP_X_

// Allow adding any capability defined as an environment variable
// extra environment capabilities start with "WEBDRIVER_GRID_CAP_X_"

// e.g. WEBDRIVER_GRID_CAP_X_os_version XP
// e.g. WEBDRIVER_GRID_CAP_X_browserstack.debug true
Map<String, String> anyExtraCapabilities = System.getenv();
addAnyValidExtraCapabilityTo(gridCapabilities, anyExtraCapabilities.keySet());

// Now check properties for extra capabilities
Properties anyExtraCapabilityProperties = System.getProperties();
addAnyValidExtraCapabilityTo(gridCapabilities, anyExtraCapabilityProperties.stringPropertyNames());

And the magic addAnyValidExtraCapabilityTo method, looks as follows:

private static void addAnyValidExtraCapabilityTo(DesiredCapabilities gridCapabilities, Set<String> possibleCapabilityKeys) {

    String extraCapabilityPrefix = "WEBDRIVER_GRID_CAP_X_";

    for(String capabilityName : possibleCapabilityKeys){

        if(capabilityName.startsWith(extraCapabilityPrefix)){

            String capabilityValue = getPropertyOrEnv(capabilityName, "");

            if(capabilityValue.length()>0){
                String capability = capabilityName.replaceFirst(extraCapabilityPrefix,"");
                System.out.println("To Set Capability " + capability + " with value " + capabilityValue);
                gridCapabilities.setCapability(capability, capabilityValue);
            }
        }
    }
}

Nothing earth shattering there, but it allowed me to add flexibility into the config without adding too much extra code into the Driver.java class.

If I was doing this in the real world. I would have created a new configuration reader type object, rather than adding the getPropertyOrEnv into the Driver.java code, but currently, the only config I use relates to the Driver.java code and I try to avoid too many radical code changes to the course if I can avoid it.

Also, in the real world, you tend not to need to add such a large amount of flexibility. You tend to stick to one grid provider, or refactor your code into more specific abstractions.

So don’t take this code as an exemplar of how to configure your remote driver, instead look upon it as a set of quick, but pragmatic changes to add more flexibility into the code base, and perhaps you’ll see something you can re-use here.

I’ve added additional lectures into my course to explain the config I used for Saucelabs, BrowserStack and TestingBot. And uploaded all the code changes extracted here to the code in the Selenium WebDriver with Java course.

Posted in Grid, Java, Selenium Simplified Blog, WebDriver | 2 Comments

Recent course source code changes for WebDriver 2.46.0

I just finished updating my course source code for WebDriver 2.46.0

I removed some of the code to github:

I had to make a few other minor changes which I summarise below.

Chrome and Firefox

Chrome and ChromeDriver 2.16 now seem to work as well as the Firefox driver. I used to have some issues with Frames and Window management but that has all gone away. Now I have a single set of tests for Chrome and Firefox with no ‘fails on Chrome’ and ‘fails on Firefox’ suites.

I did have to add some additional synchronisation when creating new windows in Firefox. Firefox used to block before returning control to the code when creating new windows, but now it doesn’t so I simple ‘wait’ for the element I need to be available before clicking on it. General synchronisation goodness that we all know and love.

Cookies

I did have to make changes for cookies though. I assume buy inderal 10mg online most people don’t mess much with cookies when using WebDriver, but it is handy functionality when you need it.

ChromeDriver still has a bug where it creates 2 cookies. And now, when ChromeDriver creates a cookie it prefixes the ‘domain’ with a ‘.’. This means you have to be careful working with cookies through ChromeDriver as you might have to work around the browser creating a duplicate cookie after you amend it.

Firefox updates have meant that I now have to append a ‘/’ to my cookie paths.

Minor Things

  • The Select support class gave me a string padded text, so I had to ‘trim’ the output. I suspect this was a browser compatibility thing with my app code.
  • On Mac, my window positioning code didn’t work because I set the Y value to 20, but Mac wanted more space for its top menu bar, so I changed the position to 40.

 

Posted in Courses, Selenium Simplified Blog, WebDriver | 1 Comment

OperaDriver is now officially deprecated in my code

Anyone remember Opera?

For a while it had the best developer tools and the best JavaScript debugger. It also had ‘good, not great’ WebDriver support, but an easy to add driver via maven.

That stopped when Opera went from version 12.17 and the Opera Driver didn’t work on most recent versions of Opera when they moved to webkit and then blink. But if you still wanted to, you could still use the driver and run tests with the older version of Opera.

But no longer.

The OperaDriver hasn’t been updated so it now compile clashes with Selenium WebDriver 2.46.0

You can exclude the conflicting apache.commons code if you want:

<dependency>
    <groupId>com.opera</groupId>
    <artifactId>operadriver</artifactId>
    <version>1.3</version>
    <exclusions>
        <!-- changes to Selenium 2.46.0 mean that the operadriver
            now conflicts with Selenium WebDriver. I excluded the
            apache.commons commons-exec from operadriver to allow
            the driver to retain buy inderal propranolol compile time compatibility 
            with webdriver
        -->
        <exclusion>
            <groupId> org.apache.commons</groupId>
            <artifactId>commons-exec</artifactId>
        </exclusion>
    </exclusions>
</dependency>

That will get you compiled, but won’t help you execute.

In fact OperaDriver hasn’t executed since WebDriver version 2.34.0

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-server</artifactId>
    <version>2.34.0</version>
</dependency>

The OperaDriver depends on code that moved in WebDriver 2.35.0.

Possibly just as well since Opera always had some issues:

  • Alert Handling
  • Did not refresh reliably
  • Window Management – did not maximise
  • JavaScript Executor and Asyn execution
  • File handling
  • Cookies – did not return the correct expiry date

I have now ‘officially’ removed OperaDriver from my course code base, and moved the basic Opera stuff, just as a legacy example, off to github.

https://github.com/eviltester/operaWebDriverExample

Posted in Selenium Simplified Blog, WebDriver | 1 Comment

WebDriverBackedSelenium example on github now

I had a small WebDriverBackedSelenium example in my Selenium 2 WebDriver API Course codebase.

Since the Selenium API has been deprecated by the main WebDriver project, although it can still be found in the current versions of Selenium WebDriver, I have moved the example to a separate github project.

https://github.com/eviltester/webDriverBackedExample

It isn’t much. It just shows how to get started with the API.

But I’m making the split now, so that:

  • students no longer see the deprecation messages when the compile the code source and think they have a problem
  • my main code won’t break badly on the future version of WebDriver which removes the Selenium API

 

Posted in Migrating to WebDriver, Selenium Simplified Blog, Selenium-RC, WebDriver | Leave a comment

Speedrun install for WebDriver 2.43.1 on Mac OS X 10 Mavericks

I added the notes and video for my ‘speedrun’ install of WebDriver 2.43.1 with Java, Maven and IntelliJ on the speedrun page.

I used VM Fusion to create a VM on my Mac with a clean install of OS X 10 Mavericks, then went through the process of installing on the Mac.

I updated the speedrun checklist to account for the Mac OS differences, and made notes on the install.

For some reason, when I installed on my ‘proper’ mac, I didn’t have to set the JAVA_HOME variable, but I did on the VM, so the video shows a full environment setup for JAVA_HOME, M2_HOME, M2 and updating PATH.

I found it interesting how Mac prompted me to the correct buy propranolol 40mg location a few times – ie. the install of JDK 1.8, so I did this earlier in the process than I did with Windows XP.

Also, since Mac OS X 10 Mavericks is slightly more ‘modern’ than Windows XP, I didn’t have to install an alternate browser to download the files, or an alternate text editor to amend the pom.xml file and update it to version 2.43.1 of WebDriver.

I edited the video down to 13 minutes, although the elapsed time (if I exclude the Wifi failure I had in the middle, was about 45 minutes).

You can find the speedrun video and installation notes on the speedrun page.

Posted in Selenium Simplified Blog, WebDriver | Leave a comment

Selenium WebDriver getAttribute nuance

I used to have an exercise on my course with the aim of recreating the ‘getTitle’ command using different mechanisms.

It was a fun exercise, you can try it for yourself. I’ll wait while you do it…

*Spoilers*

When I first created the exercise, it was pretty easy since you could just grab the title element and do a getText on it.

But… in later versions of WebDriver, getText stopped working on title and I dropped the exercise.

You could still complete the exercise by parsing the full page text, and of course executing JavaScript to get the innerHtml of the element (but we would not have covered JavaScript execution at that point on the course).

And now…

I noticed, in 2.42.2, that I can use getAttribute(“text”) to get the text from the title element.

I haven’t reinstated the exercise but I thought it would be interesting to compare getText() and getAttribute(“text”) on different tags.

I found it interesting that:

  • getText() on
    • html returns the text for the page (minus tags)
    • body, div, strong, ul (as per html)
  • getAttribute(“text”) on
    • title returns the title (getText does not)
    • script returns the inline script details
    • option returns the text, as does getText
  • sometimes getAttribute(“text”) worked on some a tags, where getText did not

I don’t think I’ll rely on this nuance as WebDriver may not always do this, but I thought it interesting enough to note.

Feel free to repeat the exercise on your pages if you want. The code I used is in my WebDriverExperiments project on github

TagInvestigationTest.java

And as a side note, you can see the type of investigation process I go through when I find an oddity or something I don’t understand – I write code to check and explore combinations that would take too much time to investigate by hand.

As you can see from the code, sometimes I write hacky code, because it is essentially throw away for my learning purpose, and I ignore the simple defects in it.

 

 

 

 

Posted in Selenium Simplified Blog, WebDriver | Leave a comment

A quick WebDriver 2.42.2 retrospective

I spent a fair few hours working through all the tests and examples on my Selenium WebDriver Course to check compatibility with WebDriver 2.42.2 and the most recent browsers.

I used…

  • Chrome Version 35.0.1916.153 m
  • IE Version 11.0.9600.17126
  • Firefox version 30.0
  • HTMLUnit 2.14 (included with WebDriver 2.42.2)

Let’s get opera out of the way quickly – since operadriver only supports Opera up to version 12.16, and the current version is 22 – I didn’t run the tests against this. Pity, since Opera still feels like a fast browser.

And let’s get IE out of the way quickly, but not dismiss it. IE 11 still awaits the official driver from Microsoft, so we should expect the current driver to have issues with it. There were a whole bunch of tests I was able to reinstate against IE because the driver functionality has moved on since I last checked it. But sadly, the speed of sendtext kills tests in IE11. I didn’t spend a lot of time debugging the tests against IE 11 – hopefully Microsoft will get an official driver out soon.

Pity, as the IE driver has improved a lot for 8,9, and 10. Previously I had failing tests for user interactions, alerts, input alerts, and these no longer occur.

HTMLUnit driver impressed me the most. I haven’t given it much love and attention over the years, but since I saw that WebDriver has recently upgraded the version of HTMLUnit that it uses, I thought I’d give it a shot. Out of my basic “All” browsers test suite, it only failed 12 tests, (out of 155) so I’m going to spend a bit more time investigating the limits of HTMLUnit driver. I was very impressed. Remember, start HTMLunitDriver with ‘true’ to get the JavaScript support.

Firefox trundled along happily with no changes to my codebase to keep the tests running due to the driver, just one change to the codebase and it was my fault:

  • I found a bug in one of my tests because Firefox was no longer tolerant of my mistakes
    • I had left a release in after a drag and drop, and now I receive an exception about “can’t release button when not clicked”, so I fixed my code
    • actions.dragAndDrop(draggable2,droppable1).release().perform();
    • don’t do that, do this
    • actions.dragAndDrop(draggable2,droppable1).perform();

Chrome required a few changes:

  • I had to deal with the “–ignore-certificate-errors” reporting by adding a chrome option when starting the driver “options.addArguments(“test-type”);”
  • Chrome seems to create rogue cookies when you add a cookie with the domain in it (I raised this as an issue 7499 (now moved to ChromeDriver issue 824) but I suspect most people will never encounter this issue). And the workaround – just don’t add the domain, the cookie will still be created fine.
  • Chrome now supports submitting forms with a keypress on the submit button (which it didn’t last time I checked) so I re-enabled that test for Chrome

Always remember to double check issues with your automation manually kids.

I found an issue with Chrome – that had nothing to do with WebDriver.

One of my tests uses sendkeys to select items from a dropdown by typing in the text of the dropdown option. This has previously worked, and still works on Firefox. But it doesn’t work on Chrome through WebDriver. And it doesn’t work on Chrome when I repeat the test manually, so I’m putting this down to a Chrome nuance, rather than a WebDriver nuance.

I also found an interesting side-effect of getAttribute, that I’ll blog about separately.

Posted in Selenium Simplified Blog, WebDriver | 2 Comments

An Odd Approach for Browser Specific Tests for WebDriver

I think I’m allowed to call the approach I document in this post as ‘odd’, because it is an approach I use, and I won’t be offending anyone.

Very often we want tests that only run on specific browsers.

The obvious way to do this is have some sort of ‘tagging’ facility for tests and suite creation, or manually exclude certain test methods or classes from suites.

An ‘odd’ way, which I have used as part of my course, but not in production, is the following:

@Test
public void driverGetTitleWithCSSAbsoluteFromRoot(){

  WebDriver driver;
  pageTitle = "Welcome to the Find By Playground";
  driver = Driver.get("http://www.compendiumdev.co.uk" +
                      "/selenium/find_by_playground.php");

  // try catch block added for IE which 
  // does not like starting css at html
  try{
      WebElement element;

      element = driver.findElement(
                    By.cssSelector("html > head > title"));

      // getTextNow returns "" for head elements
      //assertThat(pageTitle, is(element.getText()));
      assertThat(pageTitle,is(element.getAttribute("text")));

      if(Driver.currentDriver == Driver.BrowserName.IE){
          throw new RuntimeException(
                       "IE now allows CSS starting at html");
      }

  }catch(NoSuchElementException e){
      if(Driver.currentDriver != Driver.BrowserName.IE){
          throw new RuntimeException(
              "Expected only IE to fail on CSS starting at html");
      }
  }
}

In the above code, ‘Driver’ is a factory buy inderal online canada class I use which provides me with the current driver, and it knows what type to use from a property, so I can check what type of browser I’m using, e.g. IE, Firefox etc.

That isn’t odd though.

The ‘odd’ part is that I expect the test to fail under IE, for a condition unrelated to the assert, so I wrap the body of the test in a try/catch block. And the try/catch block is there to alert me if the behaviour of the test changes.

If the catch block is entered then I throw an exception when the browser is not IE, because I only expect IE to enter the catch block, so if any other browser does then it is a change in behaviour of Selenium WebDriver that I want to be informed about (hence the exception to fail the test).

If the try block carries on, after the assert then I have thrown an exception when the browser is IS, to alert me that the behaviour in IE has changed. In the version of IE that the test was written against, IE would always enter the catch block.

The actual test code itself is the assert in the middle, which would still ‘fail’ or ‘pass’ for different browsers.

As a sideeffect, the test doesn’t throw an error on IE, for the conditions that I’ve coded for (I expect it to fail on IE). Really it was a workaround for a limitation in the IE driver at the time, and the try/catch block was there to alert me when the IE Driver changed to allow access to elements in the <head> of the page using CSS selectors. (Which it now does, by the way).

Hope that makes sense. Even if I can’t imagine many people having the use case it handles:

  • Run the test, don’t report errors for a certain driver, unless the driver changes to allow the test to run on it.
Posted in Selenium Simplified Blog, WebDriver | Leave a comment