Install Browsers and Webdrivers in TravisCI
Tags: testing, travisci, cicd, devops
Published: 2020-04-13 06:09:49

Howdy developers, testers, and continuous integrators. Do you have a project involving selenium scripts to automate browser tests? Would you like to integrate those tests into your CI/CD pipeline, but aren't sure how to install browsers and webdrivers on your build server? Do you want me to stop asking rhetorical questions?

If you answered yes to any of the previous questions, read on to learn the spells to cast in your `.travis.yml` file to make this happen.

# A Frustrating Evening
Tonight I was working on my personal browser automation framework, LuluTest (which can be found [here](https://github.com/erik-whiting/LuluTest/), I always welcome contributors). In the early days of LuluTest, I only worried about driving a Chrome browser, and never worried about other browsers.

However, because LuluTest aims to help users of all browsers, I decided it was time to implement support for Firefox (no IE or Safari yet, baby steps). In TDD fashion, I copied some old tests that were using Chrome and ran them with Firefox. Eventually, everything worked locally, and I pushed the changes to Github.

But to my chagrin, TravisCI reported a failed build. I realized it was because there was no Firefox browser or Geckodriver installed on the build server, and I began to weep. My weeping was because I remember the frustration involved in hooking up Chrome and chromedriver in Travis, and I knew it was going to be a long night.

Luckily for you, I've decided to spare everyone else the pain and show you exactly how to get Chrome, Firefox, and their relevant drivers into your build server (assuming you're using TravisCI, though I imagine the steps would be the same for other CI/CD servers).

# Overview of what we'll do
Webdrivers are executables that allow us to programatically manipulate a web browser. If you've been writing browser automation tests with Selenium for long, you know that you need to either pass the path of these executables to your `Webdriver` instantiations, or have the path in your system PATH variable for the test scripts to work.

This is easy enough when you're writing tests at home on your personal computer, but if we're CI/CD proponents, we want our tests to run in a build server as well. So we'll need to update or `.travis.yml` file to install the relevant browsers and drivers. This all seems straightforward enough, but I spent at least an hour getting this right when really it should've taken ten minutes at most. So let me help you save some time.

# Chrome and Firefox browsers
First, let's install the Google Chrome and Mozilla Firefox web browsers on our build server. In your `.travis.yml` file, in the `addons` section, put:
```
addons:
  chrome: stable
  firefox: latest
```
Why are these both slightly different from each other? I have no idea but it drives me crazy.

Luckily for us, this is all we need to do to install the browsers themselves. Installing the drivers is a little bit more involved.

# Chromedriver
We're going to use the `wget` program to download the chromedriver distro from Google. Then we'll unzip the distro, remove the archive, and make the driver executable.

## Installation
Under the `install` section of your `.travis.yml` file, write:
```
install:
  - wget -N https://chromedriver.storage.googleapis.com/80.0.3987.106/chromedriver_linux64.zip -P ~/
```
Depending on when you read this article, the version number might not be the most current. Since we used `stable` to install the Chrome browser, we need to use the relevant driver as well. First, look up what the current version of Chrome is, then go to https://chromedriver.storage.googleapis.com/ and find the relevant version.

After you've located the version, find the relevant distro (most likely Linux, but maybe you're build server is Windows) and append it to the URL. The pattern for the URL you want to use in your `wget` command is `https://chromedriver.storage.googleapis.com/[RELEVANT_VERSION]/[RELEVANT_FILE]`

Also note the `-P ~/` at the end of the line. This downloads the compressed file to our build server's home directory. I do this because I have no earthly idea where the heck TravisCI is installing things, so I always explicitly denote what directory I want things done in.

## Unzip and Clean Up
the next line in your `install` section should look like this:
```
- unzip ~/chromedriver_linux64.zip -d ~/
```
Again, the `-d ~/` is ensuring that the files are unzipped to the home directory. Now that we've decompressed, we'll remove the archive. This part isn't exactly necessary, but I do it anyway:
```
- rm ~/chromedriver_linux64.zip
```

Finally, let's move the executable to the `/usr/local/share/` directory. Altogether, what we've done looks like this:
```
- wget -N https://chromedriver.storage.googleapis.com/80.0.3987.106/chromedriver_linux64.zip -P ~/
- unzip ~/chromedriver_linux64.zip -d ~/
- rm ~/chromedriver_linux64.zip
- sudo mv -f ~/chromedriver /usr/local/share/
```
## Making the driver accessible
Now that chromedriver is in our `share` directory, we need to give it executable permission, then put it in our bin directory. First, we'll use `chmod`:
```
- sudo chmod +x /usr/local/share/chromedriver
```
And finally, we'll make the chromedriver executable by the build server by making a symbolic link to it in `usr/local/bin`:
```
- sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
```
And that's all she wrote.

# Geckodriver
Geckdriver is to Firefox what Chromedriver is to Chrome. Why? I don't know, I'm not a doctor. Anyway, the strategy for getting Geckodriver all hooked up in TravisCI is the same, but there's two tiny little differences.

## Installation
The first difference is the pattern of the URL we'll feed to our `wget` command. To find the latest version of Geckodriver, go to https://github.com/mozilla/geckodriver and click "releases" under "Downloads in the README. This will automatically link to the current version, which we'll use in our URL. The `wget` command is:
```
- wget -N https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz -P ~/
```
Note the pattern here is `download/[VERSION]/geckodriver-[VERSION]-[RELEVANT OS].[FILE EXTENSION]`. Again, note the use of `-P ~/`.

## Unzip and Clean Up
This download is a tarball unlike the last installation which was a zip for some reason. Because of this, the second difference is that the command to extract the archive is a little different (but not complicatedly so). Let's also remove the archive afterwards:
```
- tar -xzf ~/geckodriver-v0.26.0-linux64.tar.gz -C ~/
- rm ~/geckodriver-v0.26.0-linux64.tar.gz
```
## Making the driver accessible
Everything is pretty much the same as last time from here. We'll move `geckodriver`, give it execute permission, and put it in `/usr/local/bin`:
```
- sudo mv -f ~/geckodriver /usr/local/share
- sudo chmod +x /usr/local/share/geckodriver
- sudo ln -s /usr/local/share/geckodriver /usr/local/bin/geckodriver
```
And voila, you should now be able to run your automated browser tests on TravisCI.

# Conclusion
This all seems straightforward, but I spent too much time on it, piecing together disparate answers across SO and other parts of the internet. I hope someone out there found this helpful. Altogether, these are the things we added to our `.travis.yml` file in this article:

```
addons:
  chrome: stable
  firefox: latest

install:
  - wget -N https://chromedriver.storage.googleapis.com/80.0.3987.106/chromedriver_linux64.zip -P ~/
  - unzip ~/chromedriver_linux64.zip -d ~/
  - rm ~/chromedriver_linux64.zip
  - sudo mv -f ~/chromedriver /usr/local/share/
  - sudo chmod +x /usr/local/share/chromedriver
  - sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
  - wget -N https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz -P ~/
  - tar -xzf ~/geckodriver-v0.26.0-linux64.tar.gz -C ~/
  - rm ~/geckodriver-v0.26.0-linux64.tar.gz
  - sudo mv -f ~/geckodriver /usr/local/share
  - sudo chmod +x /usr/local/share/geckodriver
  - sudo ln -s /usr/local/share/geckodriver /usr/local/bin/geckodriver
```