Description
openedon Oct 1, 2020
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:
Lines 449 to 457 in 107bcc0
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/