Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Commit

Permalink
TE-2526 Make needle an optional dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
jmbowman committed Aug 10, 2018
1 parent 8938e9c commit df74621
Show file tree
Hide file tree
Showing 19 changed files with 152 additions and 60 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ python:
- '2.7'
- '3.5'
- '3.6'
env:
- TOXENV=core
- TOXENV=needle
sudo: false
branches:
only:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v0.9.0 (08/09/18)
* Make Needle an optional dependency; everything except visual diffs works without it, nose, and pillow

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
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@ upgrade: ## update the requirements/*.txt files with the latest packages satisfy
pip-compile --upgrade -o requirements/base.txt requirements/base.in
pip-compile --upgrade -o requirements/doc.txt requirements/doc.in
pip-compile --upgrade -o requirements/test.txt requirements/test.in
pip-compile --upgrade -o requirements/needle.txt requirements/needle.in
pip-compile --upgrade -o requirements/travis.txt requirements/travis.in
pip-compile --upgrade -o requirements/dev.txt requirements/dev.in
25 changes: 17 additions & 8 deletions bok_choy/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,17 @@
from json import dumps
from shutil import copyfile

from needle.driver import (NeedleFirefox, NeedleChrome, NeedleIe,
NeedleSafari, NeedlePhantomJS, NeedleOpera)
try:
from needle.driver import (
NeedleChrome as Chrome,
NeedleFirefox as Firefox,
NeedleIe as Ie,
NeedleOpera as Opera,
NeedlePhantomJS as PhantomJS,
NeedleSafari as Safari
)
except ImportError:
from selenium.webdriver import Chrome, Firefox, Ie, Opera, PhantomJS, Safari
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.chrome.options import Options as ChromeOptions
Expand Down Expand Up @@ -45,12 +54,12 @@


BROWSERS = {
'firefox': NeedleFirefox,
'chrome': NeedleChrome,
'internet explorer': NeedleIe,
'safari': NeedleSafari,
'phantomjs': NeedlePhantomJS,
'opera': NeedleOpera,
'chrome': Chrome,
'firefox': Firefox,
'internet explorer': Ie,
'opera': Opera,
'phantomjs': PhantomJS,
'safari': Safari,
}

FIREFOX_PROFILE_ENV_VAR = 'FIREFOX_PROFILE_PATH'
Expand Down
61 changes: 38 additions & 23 deletions bok_choy/web_app_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@

from abc import ABCMeta
import sys
from unittest import SkipTest
from unittest import SkipTest, TestCase
from uuid import uuid4

from needle.cases import NeedleTestCase, import_from_string
from needle.driver import NeedlePhantomJS
try:
from needle.cases import import_from_string, NeedleTestCase as BaseTestCase
except ImportError:
try:
from unittest2 import TestCase as BaseTestCase
except ImportError:
BaseTestCase = TestCase
from selenium.webdriver import PhantomJS
import six

from .browser import browser, save_screenshot, save_driver_logs, save_source


@six.add_metaclass(ABCMeta)
class WebAppTest(NeedleTestCase):
class WebAppTest(BaseTestCase):

"""
Base class for testing a web application.
Expand All @@ -25,6 +31,9 @@ class WebAppTest(NeedleTestCase):
# Execute tests in parallel!
_multiprocess_can_split_ = True

viewport_width = 1024
viewport_height = 768

def __init__(self, *args, **kwargs):
super(WebAppTest, self).__init__(*args, **kwargs)

Expand All @@ -40,21 +49,24 @@ def setUpClass(cls):
Instead we start up the browser once per TestCase instance,
in the setUp method.
"""
# Instantiate the diff engine.
# This will allow Needle's flexibility for choosing which you want to use.
# These lines are copied over from Needle's setUpClass method.
klass = import_from_string(cls.engine_class)
cls.engine = klass()

# Needle's setUpClass method set up the driver (thus starting up the browser),
# and set the initial window position and viewport size.
# Those lines are not copied here into WebAppTest's setUpClass method,
# but instead into our setUp method. This follows our paradigm of starting
# up a new browser session for each TestCase.

# Now call the super of the NeedleTestCase class, so that we get everything
# from the setUpClass method of its parent (unittest.TestCase).
super(NeedleTestCase, cls).setUpClass() # pylint: disable=bad-super-call
if hasattr(cls, 'engine_class'):
# Instantiate the diff engine.
# This will allow Needle's flexibility for choosing which you want to use.
# These lines are copied over from Needle's setUpClass method.
klass = import_from_string(cls.engine_class)
cls.engine = klass()

# Needle's setUpClass method set up the driver (thus starting up the browser),
# and set the initial window position and viewport size.
# Those lines are not copied here into WebAppTest's setUpClass method,
# but instead into our setUp method. This follows our paradigm of starting
# up a new browser session for each TestCase.

# Now call the super of the NeedleTestCase class, so that we get everything
# from the setUpClass method of its parent (unittest.TestCase).
super(BaseTestCase, cls).setUpClass() # pylint: disable=bad-super-call
else:
super(WebAppTest, cls).setUpClass()

@classmethod
def tearDownClass(cls):
Expand All @@ -63,9 +75,12 @@ def tearDownClass(cls):
would quit the browser. This is not needed as we have already quit the browser
after each TestCase, by virtue of a cleanup that we add in the setUp method.
"""
# We still want to call the super of the NeedleTestCase class, so that we get
# everything from the tearDownClass method of its parent (unittest.TestCase).
super(NeedleTestCase, cls).tearDownClass() # pylint: disable=bad-super-call
if hasattr(cls, 'engine_class'):
# We still want to call the super of the NeedleTestCase class, so that we get
# everything from the tearDownClass method of its parent (unittest.TestCase).
super(BaseTestCase, cls).tearDownClass() # pylint: disable=bad-super-call
else:
super(WebAppTest, cls).tearDownClass()

def get_web_driver(self):
"""
Expand All @@ -78,7 +93,7 @@ def quit_browser(self):
"""
Terminate the web browser which was launched to run the tests.
"""
if isinstance(self.browser, NeedlePhantomJS):
if isinstance(self.browser, PhantomJS):
# Workaround for https://github.com/SeleniumHQ/selenium/issues/767
self.browser.service.send_remote_shutdown_command()
self.browser.service._cookie_temp_file = None # pylint:disable=protected-access
Expand Down
8 changes: 7 additions & 1 deletion docs/visual_diff.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ Visual Diff Testing

The bok-choy framework uses `Needle`_ to provide the ability to capture
portions of a rendered page in the browser and assert that the image captured
matches that of a baseline.
matches that of a baseline. Needle is an optional dependency of bok-choy,
which you can install via either of the following commands:

.. code-block:: console
pip install bok-choy[visual_diff]
pip install needle
The general methodology for creating a test with a screenshot assertion
consists of the following steps.
Expand Down
1 change: 0 additions & 1 deletion requirements/base.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Core requirements for using this application

lazy # For lazy evaluation of the page object's a11y_audit attribute
needle # For test assertions involving screenshots and visual diffs
selenium>=2,<4 # Browser automation driver
six # For Python 2 & 3 compatibility
6 changes: 2 additions & 4 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
# make upgrade
#
lazy==1.3
needle==0.5.0
nose==1.3.7 # via needle
pillow==5.2.0 # via needle
selenium==3.13.0
selenium==3.14.0
six==1.11.0
urllib3==1.23 # via selenium
2 changes: 1 addition & 1 deletion requirements/dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# Please do not use this file for packages that are needed for test runs.

-r pip-tools.txt # pip-tools and its dependencies, for managing requirements files
-r test.txt # Dependencies for running the various test suites
-r needle.txt # Dependencies for running the various test suites
-r travis.txt # Dependencies for tox and related utilities
8 changes: 4 additions & 4 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ pyparsing==2.2.0
pytest-cov==2.5.1
pytest-forked==0.2
pytest-xdist==1.22.5
pytest==3.7.0
pytest==3.7.1
requests==2.19.1
scandir==1.7
selenium==3.13.0
scandir==1.9.0
selenium==3.14.0
singledispatch==3.4.0.3
six==1.11.0
tox-battery==0.5.1
tox-travis==0.10
tox==3.1.2
tox==3.2.1
urllib3==1.23
virtualenv==16.0.0
wrapt==1.10.11
7 changes: 2 additions & 5 deletions requirements/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,18 @@ imagesize==1.0.0 # via sphinx
jinja2==2.10 # via sphinx
lazy==1.3
markupsafe==1.0 # via jinja2
needle==0.5.0
nose==1.3.7
packaging==17.1 # via sphinx
pillow==5.2.0
pycparser==2.18 # via cffi
pygments==2.2.0 # via readme-renderer, sphinx
pyparsing==2.2.0 # via packaging
pytz==2018.5 # via babel
readme-renderer==21.0
requests==2.19.1 # via sphinx
selenium==3.13.0
selenium==3.14.0
six==1.11.0
snowballstemmer==1.2.1 # via sphinx
sphinx==1.7.6
sphinxcontrib-websupport==1.1.0 # via sphinx
typing==3.6.4 # via sphinx
urllib3==1.23 # via requests
urllib3==1.23
webencodings==0.5.1 # via html5lib
5 changes: 5 additions & 0 deletions requirements/needle.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Requirements for test runs with needle installed for visual diff support

-r test.txt # Base testing dependencies

needle # For test assertions involving screenshots and visual diffs
50 changes: 50 additions & 0 deletions requirements/needle.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# make upgrade
#
apipkg==1.5
astroid==1.5.2
atomicwrites==1.1.5
attrs==18.1.0
backports.functools-lru-cache==1.5
click-log==0.1.8
click==6.7
configparser==3.5.0
coverage==4.5.1
edx-lint==0.5.5
enum34==1.1.6
execnet==1.5.0
funcsigs==1.0.2
futures==3.2.0 ; python_version == "2.7"
isort==4.3.4
lazy-object-proxy==1.3.1
lazy==1.3
mccabe==0.6.1
mock==2.0.0
more-itertools==4.3.0
needle==0.5.0
nose==1.3.7 # via needle
packaging==17.1
pathlib2==2.3.2
pbr==4.2.0
pillow==5.2.0 # via needle
pluggy==0.7.1
py==1.5.4
pycodestyle==2.4.0
pylint-celery==0.3
pylint-django==0.7.2
pylint-plugin-utils==0.3
pylint==1.7.1
pyparsing==2.2.0
pytest-cov==2.5.1
pytest-forked==0.2
pytest-xdist==1.22.5
pytest==3.7.1
scandir==1.9.0
selenium==3.14.0
singledispatch==3.4.0.3
six==1.11.0
urllib3==1.23
wrapt==1.10.11
10 changes: 4 additions & 6 deletions requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ lazy==1.3
mccabe==0.6.1 # via pylint
mock==2.0.0
more-itertools==4.3.0 # via pytest
needle==0.5.0
nose==1.3.7
packaging==17.1
pathlib2==2.3.2 # via pytest
pbr==4.2.0 # via mock
pillow==5.2.0
pluggy==0.7.1 # via pytest
py==1.5.4 # via pytest
pycodestyle==2.4.0
Expand All @@ -41,9 +38,10 @@ pyparsing==2.2.0 # via packaging
pytest-cov==2.5.1
pytest-forked==0.2 # via 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
pytest==3.7.1 # via pytest-cov, pytest-forked, pytest-xdist
scandir==1.9.0 # via pathlib2
selenium==3.14.0
singledispatch==3.4.0.3 # via astroid, pylint
six==1.11.0
urllib3==1.23
wrapt==1.10.11 # via astroid
6 changes: 2 additions & 4 deletions requirements/travis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ chardet==3.0.4 # via requests
codecov==2.0.15
coverage==4.5.1 # via codecov
idna==2.7 # via requests
packaging==17.1 # 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
six==1.11.0 # via tox
tox-battery==0.5.1
tox-travis==0.10
tox==3.1.2
tox==3.2.1
urllib3==1.23 # via requests
virtualenv==16.0.0 # via tox
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
from setuptools import setup

VERSION = '0.8.1'
VERSION = '0.9.0'
DESCRIPTION = 'UI-level acceptance test framework'


Expand Down Expand Up @@ -74,4 +74,7 @@ def is_requirement(line):
packages=['bok_choy', 'bok_choy/a11y'],
package_data={'bok_choy': ['vendor/google/*.*', 'vendor/axe-core/*.*']},
install_requires=load_requirements('requirements/base.in'),
extras_require={
'visual_diff': ['needle']
}
)
2 changes: 2 additions & 0 deletions tests/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,14 @@ def load_next(self, page, delay_sec):
page.visit()


@js_defined('$')
class FocusedPage(SitePage):
"""
Page that has a link to a focusable element.
"""
name = "focused"

@wait_for_js
def focus_on_main_content(self):
"""
Give focus to the element with the ``main-content`` ID.
Expand Down
Loading

0 comments on commit df74621

Please sign in to comment.