plotly / plotly/dash

provide easier way to run integration tests in a Docker container

Open
#1,420 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature P3 testing
Dominant language
Python
Stars
24.4k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
13

Description

My environment:

dash                 1.16.0
dash-core-components 1.12.0
dash-html-components 1.1.1
dash-table           4.10.1

I'm trying to runn integration tests with

pytest --headless tests/

inside a docker container, and it fails with messages like

ERROR    dash.testing.browser:browser.py:415 <<<Webdriver not initialized correctly>>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/dash/testing/browser.py", line 413, in get_webdriver
    return getattr(self, "_get_{}".format(self._browser))()
  File "/usr/local/lib/python3.8/site-packages/dash/testing/browser.py", line 459, in _get_chrome
    else webdriver.Chrome(options=options, desired_capabilities=capabilities)
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/chrome/webdriver.py", line 76, in __init__
    RemoteWebDriver.__init__(
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 157, in __init__
    self.start_session(capabilities, browser_profile)
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 252, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally.
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
                         

I have made the same tests pass outside the container. The code is sent to jenkins and a docker image get build, I'm trying to use the image for running tests on jenkins, which is why container becomes relevant.

Is this a good practice, if not, what's the recommended way?

Btw, I can actually make the tests pass by adding options.add_argument("--no-sandbox") right before these lines:

https://github.com/plotly/dash/blob/107bcc022f4803c06b2b47f3c0e498b477189bdf/dash/testing/browser.py#L449-L457

learned from this answer, but it feels hacky. It seems related to starting chrome as root, so I also tried starting the container as non-root, but it still doesn't work.

A minimal reproducible example can be

$ cat Dockerfile

FROM python:3.8

RUN apt-get update -y

RUN apt-get install -y unzip openjdk-11-jre-headless xvfb libxi6 libgconf-2-4
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

RUN wget https://chromedriver.storage.googleapis.com/85.0.4183.87/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && mv chromedriver /usr/bin && rm -v chromedriver_linux64.zip

WORKDIR /app

RUN python -m pip install --upgrade pip && python -m pip install dash[testing]

COPY . /app/

with the test example from https://dash.plotly.com/testing

$ cat tests/test_example.py

import dash
import dash_html_components as html


def test_bsly001_falsy_child(dash_duo):
    app = dash.Dash(__name__)
    app.layout = html.Div(id="nully-wrapper", children=0)

    dash_duo.start_server(app)

    dash_duo.wait_for_text_to_equal("#nully-wrapper", "0", timeout=4)

    assert dash_duo.find_element("#nully-wrapper").text == "0"

    assert dash_duo.get_logs() == [], "browser console should contain no error"

    dash_duo.percy_snapshot("bsly001-layout")

The directory structure is

$ tree .

.
├── Dockerfile
└── tests
    └── test_example.py

To reproduce error:

docker build . -t myapp
docker run -it --rm  myapp:latest pytest --headless tests  

To run the container as non-root user:

docker run -it --rm  --user 1000:1000 myapp:latest pytest --headless tests

To add options.add_argument("--no-sandbox"), one needs to get inside the container, change the dash source code, and then rerun pytest:

docker run -it --rm  myapp:latest /bin/bash
# add the line to /usr/local/lib/python3.8/site-packages/dash/testing/browser.py
root@e566ed62cea1:/app# pytest --headless tests/

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided Dockerfile and tests/test_example.py, then inspect dash/testing/browser.py around the Chrome options lines linked in the issue. Reproduce the failure with the documented docker build and docker run commands, including the non-root variant. Done should provide a supported way to run the integration test in the container without editing installed package files.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, python
Domain
devops, testing-qa
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.