Selenium Load Tests With Cicada Distributed
Tags: python, testing, docker, showdev
Published: 2021-08-17 13:33:41

[Cicada Distributed](https://cicadatesting.github.io/cicada-distributed-docs/) is unique because it allows end-to-end browser tests and load tests with many users to be run with the same framework. This is particularly useful with server side rendered websites, where the site’s performance is more limited. In this tutorial, you’ll learn how to modify the Cicada Dockerfile with a [Selenium installation](https://selenium-python.readthedocs.io/), and run Selenium tests through [CicadaD](https://github.com/cicadatesting/cicada-distributed).

Source code available at https://github.com/cicadatesting/cicada-distributed-demos/tree/main/selenium-demo

## Installing Selenium

First, generate the base Dockerfile and test.py:

```bash
cicada-distributed init
```

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

```dockerfile
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](https://cicadatesting.github.io/cicada-distributed-docs/docs/reference/user-commands/). 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:

```python
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:

```python
@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](https://cicadatesting.github.io/cicada-distributed-docs/) which verifies clicking the *Tutorial* navigation button will load the *installation* page:

```python
@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`](https://cicadatesting.github.io/cicada-distributed-docs/docs/reference/decorators/#users-per-container) parameter, introduced in version [1.3.0](https://github.com/cicadatesting/cicada-distributed/releases/tag/v1.3.0), to `1` in order to prevent resource contention in the user containers:

Finally, run the test:

```bash
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!