Skip to content

Commit

Permalink
Add support for CrossBrowserTesting
Browse files Browse the repository at this point in the history
  • Loading branch information
davehunt committed Nov 17, 2016
1 parent 7d30b17 commit 2c8ecfe
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 0 deletions.
36 changes: 36 additions & 0 deletions docs/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,42 @@ the ``--capability`` command line arguments. See the
`test options <http://testingbot.com/support/other/test-options>`_
for full details of what can be configured.

CrossBrowserTesting
-------------------

To run your automated tests using
`CrossBrowserTesting <https://crossbrowsertesting.com/>`_, you must provide a
valid username and auth key. This can be done either by using
a :ref:`configuration file <configuration-files>`, or by setting the
``CROSSBROWSERTESTING_USERNAME`` and ``CROSSBROWSERTESTING_AUTH_KEY``
environment variables.

Configuration
~~~~~~~~~~~~~

Below is an example :ref:`configuration file <configuration-files>`:

.. code-block:: ini
[pytest]
crossbrowsertesting_username = username
crossbrowsertesting_auth_key = secret
Running tests
~~~~~~~~~~~~~

To run your automated tests, simply specify ``CrossBrowserTesting`` as your
driver:

.. code-block:: bash
$ py.test --driver CrossBrowserTesting --capability os_api_name Win10 --capability browser_api_name FF46
Additional capabilities can be set using the ``--capability`` command line
arguments. See the
`automation capabilities <https://help.crossbrowsertesting.com/selenium-testing/general/crossbrowsertesting-automation-capabilities/>`_
for full details of what can be configured.

Specifying Capabilities
***********************

Expand Down
117 changes: 117 additions & 0 deletions pytest_selenium/drivers/crossbrowsertesting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import os

from py.xml import html
import pytest
import requests

DRIVER = 'CrossBrowserTesting'
API_URL = 'https://crossbrowsertesting.com/api/v3/selenium/{session}'
EXECUTOR_URL = 'http://{username}:{key}@hub.crossbrowsertesting.com:80/wd/hub'


def pytest_addoption(parser):
parser.addini('crossbrowsertesting_username',
help='crossbrowsertesting username',
default=os.getenv('CROSSBROWSERTESTING_USERNAME'))
parser.addini('crossbrowsertesting_auth_key',
help='crossbrowsertesting auth key',
default=os.getenv('CROSSBROWSERTESTING_AUTH_KEY'))


@pytest.mark.optionalhook
def pytest_selenium_capture_debug(item, report, extra):
if item.config.getoption('driver') != DRIVER:
return

videos = requests.get(
API_URL.format(session=item._driver.session_id),
auth=_auth(item),
timeout=10).json().get('videos')

if videos and len(videos) > 0:
pytest_html = item.config.pluginmanager.getplugin('html')
extra.append(pytest_html.extras.html(_video_html(videos[0])))


@pytest.mark.optionalhook
def pytest_selenium_runtest_makereport(item, report, summary, extra):
if item.config.getoption('driver') != DRIVER:
return

passed = report.passed or (report.failed and hasattr(report, 'wasxfail'))

# Add the test URL to the summary
info = requests.get(
API_URL.format(session=item._driver.session_id),
auth=_auth(item),
timeout=10).json()

url = info.get('show_result_public_url')
summary.append('{0}: {1}'.format(DRIVER, url))
pytest_html = item.config.pluginmanager.getplugin('html')
# Add the job URL to the HTML report
extra.append(pytest_html.extras.url(url, DRIVER))

try:
# Update the test result
if report.when == 'setup' or info.get('test_score') is not 'fail':
# Only update the result if it's not already marked as failed
score = 'pass' if passed else 'fail'
data = {'action': 'set_score', 'score': score}
r = requests.put(
API_URL.format(session=info.get('selenium_test_id')),
data=data,
auth=_auth(item),
timeout=10)
r.raise_for_status()
except Exception as e:
summary.append('WARNING: Failed to update {0} job status: {1}'.format(
DRIVER, e))


def driver_kwargs(request, test, capabilities, **kwargs):
capabilities.setdefault('name', test)
executor = EXECUTOR_URL.format(
username=_username(request.config),
key=_auth_key(request.config))
kwargs = {
'command_executor': executor,
'desired_capabilities': capabilities}
return kwargs


def _auth_key(config):
auth_key = config.getini('crossbrowsertesting_auth_key')
if not auth_key:
raise pytest.UsageError('CrossBrowserTesting auth key must be set')
return auth_key


def _username(config):
username = config.getini('crossbrowsertesting_username')
if not username:
raise pytest.UsageError('CrossBrowserTesting username must be set')
return username


def _auth(item):
username = _username(item.config)
return (username, _auth_key(item.config))


def _video_html(video):
html.__tagspec__.update(dict([(x, 1) for x in ('video', 'source')]))
video_attrs = {
'controls': '',
'poster': video.get('image'),
'play-pause-on-click': '',
'style': 'border:1px solid #e6e6e6; float:right; height:240px; '
'margin-left:5px; overflow:hidden; width:320px'}
source_attrs = {'src': video.get('video'), 'type': 'video/mp4'}
return str(html.video(
html.source(**source_attrs),
**video_attrs))
1 change: 1 addition & 0 deletions pytest_selenium/pytest_selenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

SUPPORTED_DRIVERS = [
'BrowserStack',
'CrossBrowserTesting',
'Chrome',
'Firefox',
'Ie',
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
'selenium = pytest_selenium.pytest_selenium',
'selenium_safety = pytest_selenium.safety',
'browserstack_driver = pytest_selenium.drivers.browserstack',
'crossbrowsertesting_driver = '
'pytest_selenium.drivers.crossbrowsertesting',
'chrome_driver = pytest_selenium.drivers.chrome',
'firefox_driver = pytest_selenium.drivers.firefox',
'ie_driver = pytest_selenium.drivers.internet_explorer',
Expand Down
53 changes: 53 additions & 0 deletions testing/test_crossbrowsertesting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from functools import partial

import pytest

pytestmark = pytestmark = [pytest.mark.skip_selenium,
pytest.mark.nondestructive]


@pytest.fixture
def testfile(testdir):
return testdir.makepyfile("""
import pytest
@pytest.mark.nondestructive
def test_pass(selenium): pass
""")


def failure_with_output(testdir, *args, **kwargs):
reprec = testdir.inline_run(*args, **kwargs)
passed, skipped, failed = reprec.listoutcomes()
assert len(failed) == 1
out = failed[0].longrepr.reprcrash.message
return out


@pytest.fixture
def failure(testdir, testfile, httpserver_base_url):
return partial(failure_with_output, testdir, testfile, httpserver_base_url,
'--driver', 'CrossBrowserTesting')


def test_missing_username(failure):
out = failure()
assert 'UsageError: CrossBrowserTesting username must be set' in out


def test_missing_api_key(failure, monkeypatch):
monkeypatch.setenv('CROSSBROWSERTESTING_USERNAME', 'foo')
out = failure()
assert 'UsageError: CrossBrowserTesting auth key must be set' in out


def test_invalid_credentials(failure, monkeypatch):
monkeypatch.setenv('CROSSBROWSERTESTING_USERNAME', 'foo')
monkeypatch.setenv('CROSSBROWSERTESTING_AUTH_KEY', 'bar')
failure('--capability', 'browser_api_name', 'FF46', '--capability',
'os_api_name', 'Win10')
out = failure()
assert 'You are not authorized to view this!' in out

0 comments on commit 2c8ecfe

Please sign in to comment.