Selenium Load Tests With Cicada Distributed

Installing Selenium

First, generate the base Dockerfile and test.py:

cicada-distributed init

Next, modify the Dockerfile in order to install Chrome, Webdriver, and Selenium for Python.

FROM cicadatesting/cicada-distributed-base-image:1.3.0

RUN apt-get update
RUN apt-get install -y bash unzip curl xvfb libxi6 libgconf-2-4 gnupg

# Install chrome
RUN curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add
RUN echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
RUN apt-get -y update
RUN apt-get -y install google-chrome-stable

# Install ChromeDriver.
# NOTE: may have to change this to appropriate version of google-chrome-stable listed here: https://www.ubuntuupdates.org/pm/google-chrome-stable
RUN wget -N https://chromedriver.storage.googleapis.com/92.0.4515.107/chromedriver_linux64.zip -P ~/
RUN unzip ~/chromedriver_linux64.zip -d ~/
RUN rm ~/chromedriver_linux64.zip
RUN mv -f ~/chromedriver /usr/local/bin/chromedriver
RUN chown root:root /usr/local/bin/chromedriver
RUN chmod 0755 /usr/local/bin/chromedriver

# Install selenium
RUN pip install selenium

# Install tests
COPY . .

ENTRYPOINT ["python", "-u", "test.py"]

Adding Selenium to the Test

In this example, we’ll add the Selenium driver to a custom user loop. You don’t have to do it this way, but it is a nice way of separating the driver setup code from the test code in Cicada.

First, create a custom user loop in test.py to initialize the driver:

from datetime import datetime
from typing import Any

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from cicadad.core.scenario import UserCommands
from cicadad.core.decorators import scenario, user_loop, users_per_container
from cicadad.core.engine import Engine

CHROMEDRIVER_PATH = "/usr/local/bin/chromedriver"
WINDOW_SIZE = "1920,1080"

engine = Engine()


def chromedriver_user_loop(user_commands: UserCommands, context: dict):
    chrome_options = Options()

    chrome_options.add_argument("--headless")
    chrome_options.add_argument(f"--window-size={WINDOW_SIZE}")
    chrome_options.add_argument("--no-sandbox")

    driver = webdriver.Chrome(
        executable_path=CHROMEDRIVER_PATH, chrome_options=chrome_options
    )

    start = datetime.now()

    output, exception, logs = user_commands.run(
        context=context,
        driver=driver,
    )

    end = datetime.now()

    user_commands.report_result(
        output,
        exception,
        logs,
        time_taken=(end - start).seconds,
    )

    driver.close()

Next, pass it to the test function:

@scenario(engine)
@user_loop(chromedriver_user_loop)
def get_tutorial(context, driver: Any):
    print(driver)


if __name__ == "__main__":
    engine.start()

Creating a Selenium Test

The last step is to add test code to verify functionality of your site. Let’s add a simple test to the Cicada Docsite which verifies clicking the Tutorial navigation button will load the installation page:

@scenario(engine)
@user_loop(chromedriver_user_loop)
def get_tutorial(context, driver: Any):
    driver.get("https://cicadatesting.github.io/cicada-distributed-docs/")

    em = driver.find_element_by_link_text("Tutorial")

    assert em is not None
    em.click()

    url = driver.current_url

    assert "installation" in url, f"Did not navigate to tutorial; current url is {url}"
    return url

In addition, limit the users_per_container parameter, introduced in version 1.3.0, to 1 in order to prevent resource contention in the user containers:

Finally, run the test:

cicada-distributed run

The test should hit the docsite and return the URL of the installation page.

Congratulations! You’ve learned how to run Selenium through Cicada Distributed!

17