GoodDeviceLabs onJul 3, 2020

Testing Web interfaces with Selenium and CanaryQA

Updated on 03 July 2020 / Andrew Murray

Validating that a device works as expected often requires you to replicate typical user-flows, these flows may include physical device interactions such as pressing buttons or checking an LED has lit. They may also include more complex interactions such as navigating the device’s web interface. In this post we’ll walk through the steps required to test that a device’s web interface works as expected (in our case the device is a network router).

The de-facto way to test a web interface is to use Selenium, an umbrella project for a range of tools and libraries that enable automation of web browsers. By using Selenium you can interact with the most commonly used web browsers, just as a user would. The test execution enviornment of CanaryQA allows you to pull in any third-party library or dependency that your tests need (this is useful as often when interacting with your device you may need a third-party library to validate data returned from the device), therefore in this post we will leverage Selenium to test a web interface within a CanaryQA test.

We’ll start by writing a skeleton pytest case that simply powers on our router device, as follows:

$ cat test-interface.py
from gdl.cell.widgets.power import Power
import time

def test_web_interface():
    # Turn the router on
    power = Power('PWR1')
    power.power_on()

    # Our device has a requirement that it will be ready after 15 seconds
    time.sleep(15)

    assert True

Our router is expected to be responsive via it’s web interface within 15 seconds after power on, therefore our test case simply powers on the device and waits for 15 seconds. We now want to check that we can login to our router with its default credentials, to do that we’ll need to make use of Selenium.

We first need to add a standard PIP package manager requirements.txt dependencies file to our test package as follows:

$ cat requirements.txt
selenium==3.141.0

When our package is uploaded to CanaryQA, prior to running tests, the execution environment will install any Python dependencies listed in the requirements file, in this case just Selenium.

We can now update our test case to open the webpage and login.

$ cat test-interface.py
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from gdl.cell.widgets.power import Power
import time

def test_web_interface():
    # Turn the router on
    power = Power('PWR1')
    power.power_on()

    # Our device has a requirement that it will be ready after 15 seconds
    time.sleep(15)

    # Verify we can login and navigate to the devices page
    driver = webdriver.Chrome()
    driver.get("http://192.168.1.1")

    # Login
    driver.find_element_by_id("user").send_keys("admin")
    driver.find_element_by_id("password").send_keys("admin")
    driver.find_element_by_id("login").click()

    # Check login was successful and took us to the 'Devices' page
    WebDriverWait(driver, 5).until(EC.title_is("Devices"))

And that’s it - Our test will turn on the device, wait 15 seconds and then use the Selenium Chrome driver to type a username and password into the login form and click on the ‘login’ button. We consider the test successful when we’re redirected to a ‘Devices’ page.

Let’s examine the raw pytest output when we run the test in CanaryQA:

============================= test session starts ==============================
platform linux -- Python 3.6.10, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 
cachedir: .pytest_cache
collecting ... collected 1 items

test-interface.py::test_web_interface PASSED

============================= 1 passed in 4.49s ==============================

We’ve shown that with just a few lines of code we can combine the physical automation offered by CanaryQA with the powerful Selenium project to verify that our device works as expected. If this were integrated into a Continuous Integration pipeline, then any regressions would be quickly identified and the test could be run on every code push.

If you’re interested in finding out more, why not get in touch with us?