[PATCH 2/6] tests: Remove Selenium tests

Stephen Finucane stephen at that.guru
Wed Apr 25 07:05:37 AEST 2018


These were added quite some time ago in order to allow some level of UI
testing. However, I've personally never used them, they're not used by
the CI, and no one has shown any desire in extending them in their time
here. It is time to bid these tests adieu.

Removing these allows us to remove a whole load of wiring that existed
just to enable these. Some of this, like the '--quick-tox' option for
the Dockerfile, is retained so we don't need to use different commands
for various versions of Patchwork, but the majority is just stripped
out.

Signed-off-by: Stephen Finucane <stephen at that.guru>
Cc: Daniel Axtens <dja at axtens.net>
---
 .travis.yml                          |   1 -
 docs/development/installation.rst    |  46 ++-------
 patchwork/tests/browser.py           | 176 -----------------------------------
 patchwork/tests/test_user_browser.py |  41 --------
 tools/docker/Dockerfile              |   9 +-
 tools/docker/entrypoint.sh           |  14 +--
 tox.ini                              |   3 +-
 7 files changed, 17 insertions(+), 273 deletions(-)
 delete mode 100644 patchwork/tests/browser.py
 delete mode 100644 patchwork/tests/test_user_browser.py

diff --git a/.travis.yml b/.travis.yml
index 7e871da8..6cb983f3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,7 +22,6 @@ env:
     - PW_TEST_DB_TYPE=mysql PW_TEST_DB_USER=root
   global:
     - PW_TEST_DB_PASS=""
-    - PW_SKIP_BROWSER_TESTS=yes
 
 before_script:
   - mysql -e 'create database patchwork character set utf8;'
diff --git a/docs/development/installation.rst b/docs/development/installation.rst
index a1bee1d1..f2ed0f2d 100644
--- a/docs/development/installation.rst
+++ b/docs/development/installation.rst
@@ -41,7 +41,8 @@ To run a shell within this environment, run:
 
    $ docker-compose run --rm web --shell
 
-To run `django-manage` commands, such as `createsuperuser` or `migrate`, run:
+To run ``django-manage`` commands, such as ``createsuperuser`` or ``migrate``,
+run:
 
 .. code-block:: shell
 
@@ -53,48 +54,17 @@ To access the SQL command-line client, run:
 
    $ docker-compose run --rm web python manage.py dbshell
 
-To run unit tests, excluding Selenium UI interaction tests, using only the
-package versions installed during container initialization, run:
-
-.. code-block:: shell
-
-   $ docker-compose run --rm web --quick-test
-
-To run the same against all supported versions of Django (via tox), run:
-
-.. code-block:: shell
-
-   $ docker-compose run --rm web --quick-tox
-
-To run specific tox targets or tests, pass arguments to the above:
+To run unit tests against the system Python packages, run:
 
 .. code-block:: shell
 
-   $ docker-compose run --rm web --quick-tox -e py27-django18 \
-       patchwork.tests.test_bundles
+   $ docker-compose run --rm web python manage.py test
 
-To run all tests, including Selenium UI interaction tests, using only the
-package versions installed container initialization, run:
-
-.. code-block:: shell
-
-   $ docker-compose run --rm web --test
-
-To run the same against all supported versions of Django (via tox), run:
-
-.. code-block:: shell
-
-   $ docker-compose run --rm web --tox
-
-To run all tests, including Selenium UI interaction tests in non-headless mode,
-run:
+To run unit tests for multiple versions using ``tox``, run:
 
 .. code-block:: shell
 
-   $ docker run -it --rm -v (pwd):/home/patchwork/patchwork/ \
-       --link patchwork_db_1:db -p 8000:8000 \
-       -v /tmp/.X11-unix:/tmp/.X11-unix \
-       -e PW_TEST_DB_HOST=db -e DISPLAY patchwork_web bash
+   $ docker-compose run --rm web tox
 
 To reset the database before any of these commands, add ``--reset`` to the
 command line after ``web`` and before any other arguments. Conversely, to
@@ -102,8 +72,8 @@ backup the database at any stage, run:
 
 .. code-block:: shell
 
-    $ docker exec DATABASECONTAINER /usr/bin/mysqldump -u DATABASEUSER \
-        --password=DATABASEPASSWORD DATABASE > backup.sql
+   $ docker exec DATABASECONTAINER /usr/bin/mysqldump -u DATABASEUSER \
+       --password=DATABASEPASSWORD DATABASE > backup.sql
 
 where ``DATABASECONTAINER`` is found by ``docker ps -a`` and the other settings
 are the same as those defined in ``patchwork/settings/dev.py``. To restore this
diff --git a/patchwork/tests/browser.py b/patchwork/tests/browser.py
deleted file mode 100644
index 1939defb..00000000
--- a/patchwork/tests/browser.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Patchwork - automated patch tracking system
-# Copyright (C) 2015 Intel Corporation
-#
-# This file is part of the Patchwork package.
-#
-# Patchwork is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# Patchwork is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Patchwork; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-import errno
-import os
-import time
-
-from django.contrib.staticfiles.testing import StaticLiveServerTestCase
-from selenium.common.exceptions import (
-    NoSuchElementException, StaleElementReferenceException,
-    TimeoutException)
-from selenium import webdriver
-from selenium.webdriver.support.ui import WebDriverWait
-from selenium.webdriver.chrome.options import Options
-
-
-class Wait(WebDriverWait):
-
-    """Subclass of WebDriverWait.
-
-    Includes a predetermined timeout and poll frequency. Also deals with a
-    wider variety of exceptions.
-    """
-    _TIMEOUT = 10
-    _POLL_FREQUENCY = 0.5
-
-    def __init__(self, driver):
-        super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
-
-    def until(self, method, message=''):
-        """Call method with driver until it returns True."""
-        end_time = time.time() + self._timeout
-
-        while True:
-            try:
-                value = method(self._driver)
-                if value:
-                    return value
-            except NoSuchElementException:
-                pass
-            except StaleElementReferenceException:
-                pass
-
-            time.sleep(self._poll)
-            if(time.time() > end_time):
-                break
-
-        raise TimeoutException(message)
-
-    def until_not(self, method, message=''):
-        """Call method with driver until it returns True."""
-        end_time = time.time() + self._timeout
-        while(True):
-            try:
-                value = method(self._driver)
-                if not value:
-                    return value
-            except NoSuchElementException:
-                return True
-            except StaleElementReferenceException:
-                pass
-
-            time.sleep(self._poll)
-            if(time.time() > end_time):
-                break
-
-        raise TimeoutException(message)
-
-
-def mkdir(path):
-    try:
-        os.makedirs(path)
-    except OSError as error:
-        if error.errno == errno.EEXIST and os.path.isdir(path):
-            pass
-        else:
-            raise
-
-
-class SeleniumTestCase(StaticLiveServerTestCase):
-    # TODO(stephenfin): This should handle non-UNIX paths
-    _SCREENSHOT_DIR = os.path.dirname(__file__) + '/../../selenium_screenshots'
-
-    def setUp(self):
-        self.skip = os.getenv('PW_SKIP_BROWSER_TESTS', None)
-        if self.skip:
-            self.skipTest('Disabled by environment variable')
-
-        super(SeleniumTestCase, self).setUp()
-
-        self.browser = os.getenv('SELENIUM_BROWSER', 'chrome')
-        if self.browser == 'firefox':
-            self.selenium = webdriver.Firefox()
-        if self.browser == 'chrome':
-            chrome_options = Options()
-            # chrome's aggressive sandboxing doesn't work well with
-            # docker so disable the sandbox. We're only looking at our
-            # own site so it should be safe enough
-            chrome_options.add_argument("--no-sandbox")
-            self.selenium = webdriver.Chrome(
-                service_args=['--verbose', '--log-path=selenium.log'],
-                chrome_options=chrome_options
-            )
-
-        mkdir(self._SCREENSHOT_DIR)
-        self._screenshot_number = 1
-
-    def tearDown(self):
-        self.selenium.quit()
-        super(SeleniumTestCase, self).tearDown()
-
-    def screenshot(self):
-        name = '%s_%d.png' % (self._testMethodName, self._screenshot_number)
-        path = os.path.join(self._SCREENSHOT_DIR, name)
-        self.selenium.get_screenshot_as_file(path)
-        self._screenshot_number += 1
-
-    def get(self, relative_url):
-        self.selenium.get('%s%s' % (self.live_server_url, relative_url))
-        self.screenshot()
-
-    def find(self, selector):
-        return self.selenium.find_element_by_css_selector(selector)
-
-    def focused_element(self):
-        return self.selenium.switch_to.active_element
-
-    def wait_until_present(self, name):
-        def is_present(driver):
-            return driver.find_element_by_name(name)
-        msg = "An element named '%s' should be on the page" % name
-        element = Wait(self.selenium).until(is_present, msg)
-        self.screenshot()
-        return element
-
-    def wait_until_visible(self, selector):
-        def is_visible(driver):
-            return self.find(selector).is_displayed()
-        msg = "The element matching '%s' should be visible" % selector
-        Wait(self.selenium).until(is_visible, msg)
-        self.screenshot()
-        return self.find(selector)
-
-    def wait_until_focused(self, selector):
-        def is_focused(driver):
-            return self.find(selector) == self.focused_element()
-        msg = "The element matching '%s' should be focused" % selector
-        Wait(self.selenium).until(is_focused, msg)
-        self.screenshot()
-        return self.find(selector)
-
-    def enter_text(self, name, value):
-        field = self.wait_until_present(name)
-        field.send_keys(value)
-        return field
-
-    def click(self, selector):
-        element = self.wait_until_visible(selector)
-        element.click()
-        return element
diff --git a/patchwork/tests/test_user_browser.py b/patchwork/tests/test_user_browser.py
deleted file mode 100644
index ad4143fc..00000000
--- a/patchwork/tests/test_user_browser.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Patchwork - automated patch tracking system
-# Copyright (C) 2015 Intel Corporation
-#
-# This file is part of the Patchwork package.
-#
-# Patchwork is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# Patchwork is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Patchwork; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-from patchwork.compat import reverse
-from patchwork.tests.browser import SeleniumTestCase
-from patchwork.tests.utils import create_user
-
-
-class LoginTestCase(SeleniumTestCase):
-
-    def setUp(self):
-        super(LoginTestCase, self).setUp()
-        self.user = create_user()
-
-    def test_default_focus(self):
-        self.get(reverse('auth_login'))
-        self.wait_until_focused('#id_username')
-
-    def test_login(self):
-        self.get(reverse('auth_login'))
-        self.enter_text('username', self.user.username)
-        self.enter_text('password', self.user.username)
-        self.click('input[value="Login"]')
-        dropdown = self.wait_until_visible('a.dropdown-toggle strong')
-        self.assertEqual(dropdown.text, self.user.username)
diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile
index 31b2aaee..68a62e15 100644
--- a/tools/docker/Dockerfile
+++ b/tools/docker/Dockerfile
@@ -13,8 +13,8 @@ ENV DEBIAN_FRONTEND noninteractive
 ENV PYTHONUNBUFFERED 1
 
 # System
-# trusty and findutils is for python3.4
-# xenial is for python3.5
+# trusty and findutils is for python3.4; xenial is for python3.5
+# TODO(stephenfin): Are curl, unzip required?
 COPY tools/docker/trusty.list /etc/apt/sources.list.d/trusty.list
 COPY tools/docker/xenial.list /etc/apt/sources.list.d/xenial.list
 RUN apt-get update -qq && \
@@ -22,9 +22,8 @@ RUN apt-get update -qq && \
     python-dev python-pip python-setuptools python-wheel \
     python3.5-dev python3-pip python3-setuptools python3-wheel \
     python3.4-dev findutils=4.4.2-7 python3.6-dev \
-    libmysqlclient-dev mysql-client curl unzip xvfb chromium-chromedriver \
-    chromium-browser build-essential git postgresql-client tzdata && \
-    ln -s /usr/lib/chromium-browser/chromedriver /usr/bin/
+    libmysqlclient-dev mysql-client curl unzip build-essential \
+    git postgresql-client tzdata
 
 # User
 RUN useradd --uid=$UID --create-home patchwork
diff --git a/tools/docker/entrypoint.sh b/tools/docker/entrypoint.sh
index 4a899781..997b8763 100755
--- a/tools/docker/entrypoint.sh
+++ b/tools/docker/entrypoint.sh
@@ -106,26 +106,20 @@ elif ! test_database; then
     reset_data
 fi
 
+# TODO(stephenfin): Deprecated the --test, --tox, --quick-test and --quick-tox
+# flags in a future release
 if [ $# -eq 0 ]; then
     # we probably ran with --reset and nothing else
     # just exit cleanly
     exit 0
 elif [ "$1" == "--shell" ]; then
     exec bash
-elif [ "$1" == "--quick-test" ]; then
+elif [ "$1" == "--test" ] || [ "$1" == "--quick-test" ]; then
     shift
-    export PW_SKIP_BROWSER_TESTS=yes
     python3 manage.py test $@
-elif [ "$1" == "--test" ]; then
+elif [ "$1" == "--tox" ] || [ "$1" == "--quick-tox" ]; then
     shift
-    xvfb-run --server-args='-screen 0, 1024x768x16' python3 manage.py test $@
-elif [ "$1" == "--quick-tox" ]; then
-    shift
-    export PW_SKIP_BROWSER_TESTS=yes
     tox $@
-elif [ "$1" == "--tox" ]; then
-    shift
-    xvfb-run --server-args='-screen 0, 1024x768x16' tox $@
 else # run whatever CMD is set to
     $@
 fi
diff --git a/tox.ini b/tox.ini
index a7c6dfc6..a64d9587 100644
--- a/tox.ini
+++ b/tox.ini
@@ -20,8 +20,7 @@ setenv =
 passenv =
     http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
     PW_TEST_DB_TYPE PW_TEST_DB_USER PW_TEST_DB_PASS PW_TEST_DB_HOST
-    PW_TEST_DB_PORT DISPLAY SELENIUM_BROWSER PW_SKIP_BROWSER_TESTS
-    DISPLAY HOME XAUTHORITY
+    PW_TEST_DB_PORT
 commands =
     python -Wonce {toxinidir}/manage.py test --noinput '{posargs:patchwork}'
 
-- 
2.14.3



More information about the Patchwork mailing list