Introducing The Driver Binary Downloader Maven Plugin For Selenium

This entry was posted by on Tuesday, 7 August, 2012 at

I’m a regular Maven user and one thing that has annoyed me for a while with Selenium is the standalone server binaries.  Not because I think the concept is a bad thing, but because it adds a dependency that has to be manually downloaded, in my mind this kind of defeats the object  of using Maven.  It wasn’t so bad when it was just the googlechrome executable, but recently the IEDriver has gone the same way and from Jim Evans’ presentation at at the Selenium conference  this year, it looks like everybody else will be following the trend at some point.

Well this left me with an itch to scratch and I have finally got around to doing something about it, introducing the driver-binary-downloader-maven-plugin.  It’s a bit of a mouthful but I didn’t want to use server in the name as people would think it was going to download the selenium server binaries, anyway it’s just a name, how bad can it be?

I have released it today (and it’s now available in the central Maven repository) at version 0.9.0 as it’s fully functional, but in my mind still in beta stage.

Basic Usage

The basic configuration is very simple, you tell it where to download things and it will go off and do it.

<plugins>
    <plugin>
        <groupId>com.lazerycode.selenium</groupId>
        <artifactId>driver-binary-downloader-maven-plugin</artifactId>
        <version>0.9.1</version>
        <configuration>
            <!-- root directory that downloaded driver binaries will be stored in -->
            <rootStandaloneServerDirectory>/my/location/for/driver/binaries</rootStandaloneServerDirectory>
            <!-- Where you want to store downloaded zip files -->
            <downloadedZipFileDirectory>/my/location/for/downloaded/zip/files</downloadedZipFileDirectory>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>selenium</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

The way the plugin works is by downloading the zipped binaries into the <downloadedZipFileDirectory>and then performing a hash check on them to ensure that the zip files are valid.  If the files are valid it extracts the contents of the file in a directory structure based upon your &lt;rootStandaloneServerDirectory&gt;.  The file structure will be ${root.server.directory}/${driver.name}/${operating.system}/${bit.rate}/${version}/$driver.binary}.  So for example if you have downloaded the 64bit googlechrome driver binary version 22 for linux and your &lt;rootStandaloneServerDirectory&gt; is “/binaries” the absolute path to it will be “/binaries/googlechrome/linux/64bit/22/googlechrome”.

By default the plugin is run in the ‘test-compile’ phase so binaries will always be downloaded before your tests start to run.

What Do I Do With It?

Your mavenised test suite can now automatically download any required standalone server binaries without you needing to manually download them and place then in a shared area. If you had them checked into your source control repository (it happens) you can now remove them.

Since you now know where the binaries are going to exist once they have been downloaded you can use them in your selenium tests secure in the knowledge that if they don’t exist they will don’t once you have run a mvn verify

Known Problems

This is only a beta and as a result may not be perfect, there is currently one problem that I currently know about

  1. If the latest version of a driver does not have binaries for all the specified operating systems (all are specified by default) it will go back to the previous version and download all of those binaries as well.

Advanced Usage

While the above is useful, it’s not exactly extensible and doesn’t really help if you don’t want to download things from the internet every time. With this in mind there is a more advanced set of configuration options available.

<plugins>
    <plugin>
        <groupId>com.lazerycode.selenium</groupId>
        <artifactId>driver-binary-downloader-maven-plugin</artifactId>
        <version>0.9.1</version>
        <configuration>
            <!-- root directory that downloaded driver binaries will be stored in -->
            <rootStandaloneServerDirectory>/tmp/binaries</rootStandaloneServerDirectory>
            <!-- Where you want to store downloaded zip files -->
            <downloadedZipFileDirectory>/tmp/zips</downloadedZipFileDirectory>
            <!-- Location of a custom repository map -->
            <customRepositoryMap>/tmp/repo.xml</customRepositoryMap>
            <!-- Operating systems you want to download binaries for (Only valid options are: windows, linux, osx) -->
            <operatingSystems>
                <windows>true</windows>
                <linux>true</linux>
                <osx>true</osx>
            </operatingSystems>
            <!-- Download 32bit binaries -->
            <thirtyTwoBitBinaries>true</thirtyTwoBitBinaries>
            <!-- Download 64bit binaries -->
            <sixtyFourBitBinaries>true</sixtyFourBitBinaries>
            <!-- If set to false will download every version available (Other filters will be taken into account -->
            <onlyGetLatestVersions>false</onlyGetLatestVersions>
            <!-- Provide a list of drivers and binary versions to download (this is a map so only one version can be specified per driver) -->
            <getSpecificExecutableVersions>
                <googlechrome>18</googlechrome>
            </getSpecificExecutableVersions>
            <!-- Number of times to attempt to download each file -->
            <fileDownloadRetryAttempts>2</fileDownloadRetryAttempts>
            <!-- Number of ms to wait before timing out when trying to connect to remote server to download file -->
            <fileDownloadConnectTimeout>20000</fileDownloadConnectTimeout>
            <!-- Number of ms to wait before timing out when trying to read file from remote server -->
            <fileDownloadReadTimeout>10000</fileDownloadReadTimeout>
            <!-- Overwrite any existing binaries that have been downloaded and extracted -->
            <overwriteFilesThatExist>true</overwriteFilesThatExist>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>selenium</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

The above options are fairly self explanatory so I’m not going to go into all of them in detail here, the most useful option however is probably <customRepositoryMap>. This option will allow you to specify your own RepositoryMap.xml (the file that specifies the drivers versions and download locations). This can enable you to have a local mirror for the driver binary zip files that you connect to, to download your Selenium server binaries to your local machine.

The repository map is checked using an xsd when it is loaded in so if you are planning on rolling your own you will probably find it useful to look at the current RepositoryMap.xml and the RepositoryMap.xsd that it is checked against.

If you want to have a look at the code for this plugin it is all publicly available here: https://github.com/Ardesco/selenium-standalone-server-plugin

Feedback

The one thing I really want now is feedback. Does it work the way you expect? Can you think of any improvements?

If you find any bugs please raise them on the Issues Page. The only way it will improve is if I know there are problems.

*Edit*

Just pushed out 0.9.1 with a fix for the issue highlighted in the comments below. The plugin now explicitly makes the files it extracts executable. I have updated the example POM files above with the new version number.

20 Responses to “Introducing The Driver Binary Downloader Maven Plugin For Selenium”

  1. Matthias Köster

    Hi,

    We have similiar issues with the webdriver binaries and your maven plugin looks interesting. But we plan to just write a shell script that downloads all drivers and then deploys them to our local nexus server. This way we have exactly one place where all artifacts are stored. Our nexus repository then also acts as a cache because we have much faster access to it via our local network. Did you consider this option too? How do you ensure that the file permissions from the zip archive are restored correctly? We used the plexus ZipArchiver which had some problems with restoring file permissions, looks like you are directly using the java SDK zip support. Does that work properly on all platforms?

    Cheers,
    Matthias

    • Ardesco

      You can supply your own RepositoryMap.xml with custom file paths for the various binaries (see the bottom of the article that links to RepositoryMap.xml and RepositoryMap.xsd). This would enable you to use the plugin to download the files from your local nexus server rather than going over the net to get them.

      Permissions of the extracted files is something I have overlooked and I’ve now raised a bug for it (I normally run my selenium tests on windows for IE support and windows is a bit more liberal). It will be fairly simple change to make each file that is extracted executable.

      I have tested the plugin on Windows and OSX to ensure it downloads files and extracts them properly and have had no issues so far. If you find any please let me know.

      • Ardesco

        Just pushed out version 0.9.1 which will now make all the files it extracts from the zip’s executable. Maven central will sync it within the next 2 hours.

  2. Darragh Grace

    Hi there. This plugin looks great. I have tried to use it with the basic configuration and the Advanced configuration but get the same error.. e.g. For the basic configuration I simply copied and pasted the basic usage snippet at the top of the page into my projects pom.xml, changed the paths for & and tried to rebuild my maven project. The error I get is below.

    [ERROR] Failed to execute goal com.lazerycode.selenium:driver-binary-downloader-maven-plugin:0.9.1:selenium (default) on project testcases: Unable to parse configuration of mojo com.lazerycode.selenium:driver-binary-downloader-maven-plugin:0.9.1:selenium: Cannot assign value ‘null’ (type: class java.lang.String) to protected java.util.Map com.lazerycode.selenium.SeleniumServerMojo.operatingSystems: Can not set java.util.Map field com.lazerycode.selenium.SeleniumServerMojo.operatingSystems to java.lang.String -> [Help 1]

    Any ideas? Thanks again, this is really useful!

    • Ardesco

      It’s saying that you have entered invalid data into the operating systems tag, do you have an empty <operatingSystems> definition in your configuration? I would need to see your POM to be able to give more detailed help (a link to a gist/pastebin/something similar would be the most useful)

      There is a working selenium maven template available here that uses the plugin, this may give you a pointer in the right direction:

      https://github.com/Ardesco/Selenium-Maven-Template

  3. Darragh Grace

    Thanks for the link to the maven template.
    Here is a link to my pom.xml – https://gist.github.com/b851ca1bc3b310631461
    I dont have any in my configuration. Hopefully you can spot something..

    • Ardesco

      I can’t see anything that looks wrong in the POM. The only thing that looks different is that you are using Java 7 (If I’m reading things right), the plugin was written using Java 6. I’ll have to install Java 7 and see if that causes any problems, I would have thought that the majority of things would be backwards compatible with 6 but maybe I used something that isn’t.

      • Darragh Grace

        Thanks for looking into this for me, much appreciated. Did you have any luck repro’ing the problem I am seeing?

        • Ardesco

          No I haven’t. I’ve switched my selenium-maven-template over to Java 7 locally which uses the plugin to download binaries and it still works fine. Does the template work for you?

          Versions I have tried to replicate it with are:

          java version “1.7.0_05″
          javac 1.7.0_06
          Apache Maven 2.2.1(r801777)

        • Ardesco

          The latest version should now be working correctly for you

          • Still am seeing this error with version 0.9.1. I am using only your “Basic Usage”, as described above.
            Apache Maven 3.1.0
            Java version: 1.7.0_21, vendor: Oracle Corporation
            OS name: “windows 7″, version: “6.1″, arch: “amd64″, family: “windows”
            Any ideas?

  4. Daniel

    Looks interesting, is it possible to use this with gradle also?

    • Ardesco

      I’m not aware of a viable way to use maven plugins with gradle, having a look at gradle plugins is on my TODO list however :)

      • Daniel

        Good to hear, looking forward to that.
        I was experimenting with this https://github.com/geb/geb-example-gradle when I found your project and thought that it would be great if it was possible to mix them together. It would make a test suite very portable.

  5. pPxXY4RYP55EOi

    Could it be okay to write several of this on my small internet web site only incorporate a 1 way link towards the web site?

    • Ardesco

      I’m not sure I fully understand what you mean…

  6. kashu4055

    I have framework where i am using jbehave with junit,webdriver etc.Now in order to run test cases in different browser so how this plug in will help us in that? will this plug in automatically download latest version of selenium or ie ,chrome driver? awaiting your reply.

    • Ardesco

      Yup it just downloads the stand alone executables. If you want to see an example of it in action have a look at: https://github.com/Ardesco/Selenium-Maven-Template

      • kashu4055

        I have now looked your POM,template..very good way constucted
        but got few questions like
        1) if i use ${driver-binary-downloader-maven-plugin} kind of configuration then will that update latest version from your side automatically ?
        2)What is use of binaryRootFolder=${standalone.binary.root.folder}
        browser=${browser}
        threads=${threads} in property file? is there any we can specify browser execution through POM?

Trackbacks/Pingbacks

  1. A Smattering of Selenium #109 « Official Selenium Blog

Leave a Reply




+ six = nine