diff --git a/.travis.yml b/.travis.yml index 925ecee1..7fc27f10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,15 +8,13 @@ branches: only: - master before_install: -- export DISPLAY=:99.0 -- sh -e /etc/init.d/xvfb start -- sleep 3 # give xvfb some time to start -- wget https://github.com/mozilla/geckodriver/releases/download/v0.20.0/geckodriver-v0.20.0-linux64.tar.gz +- wget https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-linux64.tar.gz - mkdir geckodriver -- tar -xzf geckodriver-v0.20.0-linux64.tar.gz -C geckodriver +- tar -xzf geckodriver-v0.21.0-linux64.tar.gz -C geckodriver - export PATH=$PATH:$PWD/geckodriver +- export BOKCHOY_HEADLESS=true addons: - firefox: '59.0.1' + firefox: '61.0.1' install: - pip install -r requirements/travis.txt script: diff --git a/CHANGELOG b/CHANGELOG index dacb3d0c..6f71df18 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v0.8.1 (08/01/18) +* Support use of headless Chrome and Firefox by setting the BOKCHOY_HEADLESS environment variable to "true" +* Only try to save logs which are available for the browser in use + v0.8.0 (07/18/18) * Preserve geckodriver log for Firefox test failures * Better handling of screenshot and log directory settings diff --git a/bok_choy/browser.py b/bok_choy/browser.py index 86611751..49744702 100644 --- a/bok_choy/browser.py +++ b/bok_choy/browser.py @@ -161,7 +161,7 @@ def save_driver_logs(driver, prefix): copyfile(log_path, dest_path) return - log_types = ['browser', 'driver', 'client', 'server'] + log_types = driver.log_types for log_type in log_types: try: log = driver.get_log(log_type) @@ -357,6 +357,7 @@ def _local_browser_class(browser_name): # Get class of local browser based on name browser_class = BROWSERS.get(browser_name) + headless = os.environ.get('BOKCHOY_HEADLESS', 'false').lower() == 'true' if browser_class is None: raise BrowserConfigError( "Invalid browser name {name}. Options are: {options}".format( @@ -370,6 +371,8 @@ def _local_browser_class(browser_name): firefox_options = FirefoxOptions() firefox_options.log.level = 'trace' + if headless: + firefox_options.set_headless(True) browser_args = [] browser_kwargs = { 'firefox_profile': _firefox_profile(), @@ -394,6 +397,8 @@ def _local_browser_class(browser_name): elif browser_name == 'chrome': chrome_options = ChromeOptions() + if headless: + chrome_options.set_headless(True) # Emulate webcam and microphone for testing purposes chrome_options.add_argument('--use-fake-device-for-media-stream') diff --git a/docs/testing.rst b/docs/testing.rst index 0364d937..385a404b 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -4,7 +4,19 @@ Testing Environment Configuration Testing via TravisCI -------------------- -``bok-choy`` can be used along with Travis CI to test changes remotely. One way to accomplish this testing is by using the X Virtual Framebuffer (xvfb) to imitate a display. To use xvfb, you'll start it up via a ``before_script`` section in your ``.travis.yml`` file, like this: +``bok-choy`` can be used along with Travis CI to test changes remotely. +One way to accomplish this testing is to use the headless version of Chrome or Firefox. +bok-choy does this when the ``BOKCHOY_HEADLESS`` environment is set to "true". + +.. code-block:: yaml + + before_script: + - export BOKCHOY_HEADLESS=true + +Another option is to use the X Virtual Framebuffer (xvfb) to imitate a display. +Headless versions of Chrome and Firefox are relatively new developments, +so you may want to use xvfb if you encounter a bug with headless browser usage. +To use xvfb, you'll start it up via a ``before_script`` section in your ``.travis.yml`` file, like this: .. code-block:: yaml @@ -23,7 +35,9 @@ Testing via tox ``bok-choy`` can be used along with tox to test against multiple Python virtual environments containing different versions of requirements. -An important detail when using tox in a Travis CI environment: tox passes along only a fixed list of environment variables to each tox-created virtual environment. When using ``bok-choy`` in tox, the DISPLAY environment variable is needed but is not automatically passed-in. The tox.ini file needs to specify the DISPLAY variable like this: +An important detail when using tox in a Travis CI environment: tox passes along only a fixed list of environment variables to each tox-created virtual environment. +When using ``bok-choy`` via xvfb in tox, the DISPLAY environment variable is needed but is not automatically passed-in. +The tox.ini file needs to specify the DISPLAY variable like this: .. code-block:: yaml diff --git a/requirements/dev.txt b/requirements/dev.txt index ae0551af..41170bb5 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -28,14 +28,15 @@ lazy-object-proxy==1.3.1 lazy==1.3 mccabe==0.6.1 mock==2.0.0 -more-itertools==4.2.0 +more-itertools==4.3.0 needle==0.5.0 nose==1.3.7 packaging==17.1 -pbr==4.1.0 +pathlib2==2.3.2 +pbr==4.2.0 pillow==5.2.0 pip-tools==2.0.2 -pluggy==0.6.0 +pluggy==0.7.1 py==1.5.4 pycodestyle==2.4.0 pylint-celery==0.3 @@ -45,15 +46,16 @@ pylint==1.7.1 pyparsing==2.2.0 pytest-cov==2.5.1 pytest-forked==0.2 -pytest-xdist==1.22.2 -pytest==3.6.3 +pytest-xdist==1.22.5 +pytest==3.7.0 requests==2.19.1 +scandir==1.7 selenium==3.13.0 singledispatch==3.4.0.3 six==1.11.0 tox-battery==0.5.1 tox-travis==0.10 -tox==3.1.1 +tox==3.1.2 urllib3==1.23 virtualenv==16.0.0 wrapt==1.10.11 diff --git a/requirements/doc.txt b/requirements/doc.txt index 41ffcc47..10dc959e 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -33,7 +33,7 @@ requests==2.19.1 # via sphinx selenium==3.13.0 six==1.11.0 snowballstemmer==1.2.1 # via sphinx -sphinx==1.7.5 +sphinx==1.7.6 sphinxcontrib-websupport==1.1.0 # via sphinx typing==3.6.4 # via sphinx urllib3==1.23 # via requests diff --git a/requirements/test.in b/requirements/test.in index dfbb2997..8eb59582 100644 --- a/requirements/test.in +++ b/requirements/test.in @@ -7,5 +7,6 @@ futures ; python_version == "2.7" # via isort mock # For mocking functionality in assorted tests packaging # For version number parsing and comparisons pycodestyle # For checking compliance with PEP 8 coding style guidelines +pylint-plugin-utils<0.4 # via pylint-celery, pylint-django; newer versions drop Python 2 support pytest-cov # For code coverage statistics generation pytest-xdist # For parallel test execution diff --git a/requirements/test.txt b/requirements/test.txt index 696cae2e..af1e23b5 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -23,24 +23,26 @@ lazy-object-proxy==1.3.1 # via astroid lazy==1.3 mccabe==0.6.1 # via pylint mock==2.0.0 -more-itertools==4.2.0 # via pytest +more-itertools==4.3.0 # via pytest needle==0.5.0 nose==1.3.7 packaging==17.1 -pbr==4.1.0 # via mock +pathlib2==2.3.2 # via pytest +pbr==4.2.0 # via mock pillow==5.2.0 -pluggy==0.6.0 # via pytest +pluggy==0.7.1 # via pytest py==1.5.4 # via pytest pycodestyle==2.4.0 pylint-celery==0.3 # via edx-lint pylint-django==0.7.2 # via edx-lint -pylint-plugin-utils==0.3 # via pylint-celery, pylint-django +pylint-plugin-utils==0.3 pylint==1.7.1 # via edx-lint, pylint-celery, pylint-django, pylint-plugin-utils pyparsing==2.2.0 # via packaging pytest-cov==2.5.1 pytest-forked==0.2 # via pytest-xdist -pytest-xdist==1.22.2 -pytest==3.6.3 # via pytest-cov, pytest-forked, pytest-xdist +pytest-xdist==1.22.5 +pytest==3.7.0 # via pytest-cov, pytest-forked, pytest-xdist +scandir==1.7 # via pathlib2 selenium==3.13.0 singledispatch==3.4.0.3 # via astroid, pylint six==1.11.0 diff --git a/requirements/travis.txt b/requirements/travis.txt index e593188f..5b29ec72 100644 --- a/requirements/travis.txt +++ b/requirements/travis.txt @@ -10,13 +10,13 @@ codecov==2.0.15 coverage==4.5.1 # via codecov idna==2.7 # via requests packaging==17.1 # via tox -pluggy==0.6.0 # via tox +pluggy==0.7.1 # via tox py==1.5.4 # via tox pyparsing==2.2.0 # via packaging requests==2.19.1 # via codecov six==1.11.0 # via packaging, tox tox-battery==0.5.1 tox-travis==0.10 -tox==3.1.1 +tox==3.1.2 urllib3==1.23 # via requests virtualenv==16.0.0 # via tox diff --git a/setup.py b/setup.py index 410037bd..4d0ef70f 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ import sys from setuptools import setup -VERSION = '0.8.0' +VERSION = '0.8.1' DESCRIPTION = 'UI-level acceptance test framework' diff --git a/tests/test_browser.py b/tests/test_browser.py index 85b74784..d7062446 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -224,6 +224,8 @@ def test_save_driver_logs_dir_not_set(self, caplog, monkeypatch): bok_choy.browser.save_driver_logs(browser, 'empty') assert 'The SELENIUM_DRIVER_LOG_DIR environment variable was not set; not saving logs' in caplog.text + @pytest.mark.skipif(os.environ.get('SELENIUM_BROWSER', 'firefox') != "firefox", + reason="Selenium driver logs are supported on non-firefox browsers") def test_save_driver_logs_unsupported(self): browser = self.browser tempdir_path = self.tempdir_path @@ -252,7 +254,7 @@ def test_save_driver_logs(self): # Check that the files were created. # Note that the 'client' and 'server' log files will be empty. - log_types = ['browser', 'driver', 'client', 'server'] + log_types = browser.log_types for log_type in log_types: expected_file = os.path.join(tempdir_path, 'js_page_{}.log'.format(log_type)) assert os.path.isfile(expected_file) @@ -270,7 +272,7 @@ def test_save_driver_logs_exception(self, caplog): bok_choy.browser.save_driver_logs(browser, 'js_page') # Check that no files were created. - log_types = ['browser', 'driver', 'client', 'server'] + log_types = browser.log_types for log_type in log_types: expected_file = os.path.join(tempdir_path, 'js_page_{}.log'.format(log_type)) assert not os.path.exists(expected_file) diff --git a/tests/test_selector.py b/tests/test_selector.py index 9bb2157a..d03e6151 100644 --- a/tests/test_selector.py +++ b/tests/test_selector.py @@ -59,7 +59,7 @@ def test_scroll(self): self.long_page.scroll_to_element('#element_after_long_part') # Different browsers, CI systems, and resolutions may present the # element in varying locations. Use a greater-than instead of an equals. - self.assertGreaterEqual(self._get_window_position(), 1900) + self.assertGreaterEqual(self._get_window_position(), 1800) def test_scroll_false_element(self): """ diff --git a/tox.ini b/tox.ini index 97e2001a..08c8c716 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,9 @@ deps = -r{toxinidir}/requirements/test.txt passenv = DISPLAY + BOKCHOY_HEADLESS + MOZ_HEADLESS + SELENIUM_BROWSER setenv = SCREENSHOT_DIR={toxinidir}/logs SELENIUM_DRIVER_LOG_DIR={toxinidir}/logs