11 Aug 2016 HTTPS Everywhere Unit Testing For Chromium
Let’s start by explaining what HTTPS Everywhere is.
HTTPS Everywhere is a browser extension created and maintained by the Electronic Frontier Foundation to increase the usage of HTTPS websites across users. The extension works by checking the url of websites against a ruleset, and if the browsed HTTP website has a working HTTPS domain, the user is automatically redirected to the secure website. HTTPS Everywhere also checks the SSL certificates against the SSL Observatory, however, that doesn’t work on Chromium because we don’t have access to the certificate’s information.
In this article, I’m going to explain how I’ve implemented integration testing of the Chrome extension using Selenium and ChromeDriver, and how we’ve integrated this with Travis. I’ll start by discussing how to get a normal Selenium ChromeDriver unit testing script to run, and then I’ll move on to explain how to set Travis correctly to allow the script to run, and finally, how to integrate everything together and run it.
Disclaimer: I’m the person who wrote the code and I’m proud of being one of the people who contributed to HTTPS Everywhere, but please be aware that I’m not part of EFF, HTTPS Everywhere Team, Selenium, ChromeDriver, Travis, or any of the other technologies and/or services discussed here, nor am I officially responsible for any of these projects, nor is Spirula Systems officially affiliated with any of this work. Some of the information here may be outdated and/or incorrect, please feel free to correct me and we’ll be happy to update the article accordingly.
Almost all of the code we’ll be discussing is represented in those pull requests, https://github.com/EFForg/https-everywhere/pull/2623 and https://github.com/EFForg/https-everywhere/pull/2731. Feel free to browse the code and comments.
Getting the script to run
The first thing to do was to create the Python script itself and make sure it runs successfully. This meant multiple things. The first step was to install Selenium and Chromedriver. To install these packages, you should run the following commands.
sudo apt-get install python-pip chromium-chromedriver
sudo pip install selenium
Of course, Chromium or Google Chrome should be installed. If it isn’t, run the following command.
sudo apt-get install chromium-browser
Things going okay? Now you should get your hands on a text editor and write some Python code.
This is the script we’re using to run the tests. Of course you are free to Google additional ChromeDriver Python samples elsewhere. Now, running the script using “python script.py” should spawn a Chromium browser and the tests should be running.
Integrating it with Travis
This is the difficult part.
Travis has a problem with Chromium and almost everything related to it. It was quite tricky to get the script to work on Travis. Let’s explain how.
The first step was to make sure the required software is installed in Travis. To do this, we added this line, where requirements.txt basically included the “selenium” package in order to install Selenium.
For Chromium browser itself, the work was easy.
A simple apt entry installed the package. However, for ChromeDriver, we had to do some magic.
The ChromeDriver package itself isn’t white-listed in Travis, and thus adding chromium-chromedriver to the apt section won’t work. Instead, we had to write the script that downloads the package and installs it manually. The following snippet shows how that is done.
– export DISPLAY=:99.0
– sh -e /etc/init.d/xvfb start
– wget https://chromedriver.storage.googleapis.com/2.12/chromedriver_linux64.zip
– unzip chromedriver_linux64.zip
– mv chromedriver test/chromium/chromedriver
Additionally, export DISPLAY=:99.0 and sh -e /etc/init.d/xvfb start had to be executed in order to allow the Chromium browser itself to run successfully.
Note that chromedriver is moved to test/chromium/chromedriver and not /usr/bin or any other directory that belongs to $PATH. This is done in order to avoid requiring sudo access, which downgrades our Travis machines to legacy ones.
In order to make this work for both cases where the tests are run by the user and by Travis, we check the environment variables to detect whether Travis is running. If so, we change the ChromeDriver path in order to reflect the downloaded binary file. This is illustrated in the following code.
chromedriver_path = “chromedriver”
if ‘TRAVIS’ in os.environ:
chromdriver_path = os.path.abspath(“test/chromium/chromedriver”)
# First argument is optional, if not specified will search path.
driver = webdriver.Chrome(chromedriver_path, chrome_options=chromeOps)
except WebDriverException as e:
error = e.__str__()
You may have already noticed this line, chromeOps.add_argument(‘–no-sandbox’). This line is critical to allow running Chromium on Travis because of how the virtualization environment of Travis is set.
Pulling the trigger
You’re ready! The only thing left is to add the shell script that runs the Python script and sets everything correctly. Our very own script is called chromium.sh , and here are the interesting lines.
# Make sure we have xvfb-run and it’s not already set.
if [ -z “$XVFB_RUN” -a -n “$(which xvfb-run)” ]; then
echo “running tests”
CRX_NAME=”`ls -tr pkg/*.crx | tail -1`”
$XVFB_RUN python2.7 test/chromium/script.py $CRX_NAME
The xvfb-run line runs Chromium in a virtual X environment which Chromium requires to start. You might remember Xvfb from this line, sh -e /etc/init.d/xvfb start, which we had to execute before running the tests to start the Xvfb service.
./makecrx.sh is the script that creates the extension CRX, however, it’s out of the article’s scope. Of course, you can still check the file here.
After creating the CRX we check the most updated CRX file we have and we use it to run the script, and voila! The Chromium unit testing for HTTPS Everywhere is now running!