Skip to content

Commit

Permalink
acceptance tests - retry getting selenium webdriver instance of Conne…
Browse files Browse the repository at this point in the history
…ctionError raised
  • Loading branch information
jantman committed Feb 25, 2018
1 parent 3d7aefb commit 8e9e95d
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Unreleased Changes
* Add support for writing tests of data manipulation during database migrations, and write tests for the migration in for Issue 105, above.
* Add support for ``BIWEEKLYBUDGET_LOG_FILE`` environment variable to cause Flask application logs to go to a file *in addition to* STDOUT.
* Add support for ``SQL_POOL_PRE_PING`` environment variable to enable SQLAlchemy ``pool_pre_ping`` feature (see `Disconnect Handling - Pessimistic <http://docs.sqlalchemy.org/en/latest/core/pooling.html#pool-disconnects-pessimistic>`_) for resource-constrained systems.
* Modify acceptance tests to retry up to 3 times, 3 seconds apart, if a ConnectionError (or subclass thereof) is raised when constructing the Selenium driver instance. This is a workaround for intermittent ConnectionResetErrors in TravisCI.

0.7.1 (2018-01-10)
------------------
Expand Down
62 changes: 55 additions & 7 deletions biweeklybudget/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
from time import time
from tempfile import mkstemp

from retrying import retry

import biweeklybudget.settings
from biweeklybudget.tests.fixtures.sampledata import SampleDataLoader
from biweeklybudget.tests.sqlhelpers import restore_mysqldump, do_mysqldump
Expand All @@ -59,6 +61,8 @@

try:
import pytest_selenium.pytest_selenium
from selenium.webdriver.support.event_firing_webdriver import \
EventFiringWebDriver
HAVE_PYTEST_SELENIUM = True
except ImportError:
HAVE_PYTEST_SELENIUM = False
Expand Down Expand Up @@ -230,19 +234,63 @@ def base_url(testflask):
return testflask.url()


@pytest.fixture
def selenium(selenium):
def retry_if_conn_error(ex):
return isinstance(ex, ConnectionError)


@retry(
stop_max_attempt_number=3, wait_fixed=3000,
retry_on_exception=retry_if_conn_error
)
def get_driver_for_class(driver_class, driver_kwargs):
"""
Wrapper around the selenium ``driver()`` fixture's
``driver_class(**driver_kwargs)`` call that retries up to 3 times, 3
seconds apart, if a ConnectionError is raised.
"""
return driver_class(**driver_kwargs)


@pytest.yield_fixture
def driver(request, driver_class, driver_kwargs):
"""
Returns a WebDriver instance based on options and capabilities
This is copied from pytest-selenium 1.11.4, but modified to retry getting
the driver up to 3 times to cope with intermittent connection resets in
TravisCI. We ripped the original ``driver = driver_class(**driver_kwargs)``
out and replaced it with the ``get_driver_for_class()`` function, which
is wrapped in the retrying package's ``@retry`` decorator.
"""
driver = get_driver_for_class(driver_class, driver_kwargs)

event_listener = request.config.getoption('event_listener')
if event_listener is not None:
# Import the specified event listener and wrap the driver instance
mod_name, class_name = event_listener.rsplit('.', 1)
mod = __import__(mod_name, fromlist=[class_name])
event_listener = getattr(mod, class_name)
if not isinstance(driver, EventFiringWebDriver):
driver = EventFiringWebDriver(driver, event_listener())

request.node._driver = driver
yield driver
driver.quit()


@pytest.yield_fixture
def selenium(driver):
"""
Per pytest-selenium docs, use this to override the selenium fixture to
provide global common setup.
"""
selenium.set_window_size(1920, 1080)
selenium.implicitly_wait(2)
driver.set_window_size(1920, 1080)
driver.implicitly_wait(2)
# from http://stackoverflow.com/a/13853684/211734
selenium.set_script_timeout(30)
driver.set_script_timeout(30)
# from http://stackoverflow.com/a/17536547/211734
selenium.set_page_load_timeout(30)
return selenium
driver.set_page_load_timeout(30)
yield driver


def _gather_screenshot(item, report, driver, summary, extra):
Expand Down
3 changes: 3 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ deps =
pytest-blockage
pytest-timeout
alembic-verify
retrying

passenv=CI TRAVIS* CONTINUOUS_INTEGRATION AWS* NO_REFRESH_DB DB_CONNSTRING NO_CLASS_REFRESH_DB
setenv =
Expand Down Expand Up @@ -138,6 +139,7 @@ deps =
pytest-selenium
pytest-timeout
alembic-verify
retrying
passenv = {[testenv]passenv}
setenv = {[testenv]setenv}
basepython = python2.7
Expand Down Expand Up @@ -170,6 +172,7 @@ deps =
freezegun
alembic-verify
pytest-html
retrying
passenv=CI TRAVIS* CONTINUOUS_INTEGRATION NO_REFRESH_DB DB_CONNSTRING NO_CLASS_REFRESH_DB MYSQL_*
setenv = {[testenv]setenv}
basepython = python3.6
Expand Down

0 comments on commit 8e9e95d

Please sign in to comment.