Cicada Distributed 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, and run Selenium tests through CicadaD.
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:
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!
Top comments (0)