Skip to content

Commit

Permalink
Add support for TestingBot
Browse files Browse the repository at this point in the history
  • Loading branch information
davehunt committed Aug 18, 2015
1 parent 9c89124 commit 2a5efd2
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 1 deletion.
34 changes: 34 additions & 0 deletions docs/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,40 @@ See the
for additional configuration that can be set using ``--capability`` command line
arguments.

TestingBot
----------

To run your automated tests using `TestingBot <http://testingbot.com/>`_, you
must provide a valid key and secret. This can be done either by using a
``setup.cfg`` file or by setting the ``TESTINGBOT_KEY`` and
``TESTINGBOT_SECRET`` environment variables.

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

Below is an example ``setup.cfg`` showing the configuration options:

.. code-block:: ini
[pytest]
testingbot_key = key
testingbot_secret = secret
Running tests
~~~~~~~~~~~~~

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

.. code-block:: bash
$ py.test --driver TestingBot --capability browserName firefox --capability browserName 39 --capability platform WIN8
See the `list of available browsers <http://testingbot.com/support/getting-started/browsers.html>`_
to help you with your configuration. Additional capabilities can be set using
the ``--capability`` command line arguments. See the
`test options <http://testingbot.com/support/other/test-options>`_
for full details of what can be configured.

Capabilities
------------

Expand Down
1 change: 1 addition & 0 deletions pytest_selenium/cloud/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .browserstack import * # noqa
from .saucelabs import * # noqa
from .testingbot import * # noqa
96 changes: 96 additions & 0 deletions pytest_selenium/cloud/testingbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# 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 pytest
from _pytest.mark import MarkInfo
from py.xml import html
import requests
from selenium import webdriver

from .base import CloudProvider


class Provider(CloudProvider):

@property
def name(self):
return 'TestingBot'

def _key(self, config):
key = config.getini('testingbot_key')
if not key:
raise pytest.UsageError('TestingBot key must be set')
return key

def _secret(self, config):
secret = config.getini('testingbot_secret')
if not secret:
raise pytest.UsageError('TestingBot secret must be set')
return secret

def start_driver(self, item, capabilities):
keywords = item.keywords
marks = [m for m in keywords.keys() if isinstance(
keywords[m], MarkInfo)]
groups = capabilities.get('groups', []) + marks
test_id = '.'.join(self.split_class_and_test_names(item.nodeid))
capabilities['name'] = test_id
if groups:
capabilities['groups'] = groups

executor = 'http://{0}:{1}@hub.testingbot.com/wd/hub'.format(
self._key(item.config), self._secret(item.config))
return webdriver.Remote(command_executor=executor,
desired_capabilities=capabilities)

def url(self, config, session):
return 'http://testingbot.com/members/tests/{0}'.format(session)

def additional_html(self, session):
return [self._video_html(session)]

def update_status(self, config, session, passed):
requests.put('https://api.testingbot.com/v1/tests/{0}'.format(session),
data={'test[success]': '1' if passed else '0'},
auth=(self._key(config), self._secret(config)))

def _video_html(self, session):
flash_vars = 'config={{\
"clip":{{\
"url":"{0}",\
"provider":"rtmp"}},\
"plugins":{{\
"controls":{{\
"url":"http://testingbot.com/assets/\
flowplayer.controls-3.2.14.swf",\
"mute":null,\
"volume":null}},\
"rtmp":{{\
"url":"http://testingbot.com/assets/\
flowplayer.rtmp-3.2.11.swf",\
"netConnectionUrl":"rtmp://s2tuay45tyrz3f.cloudfront.net/\
cfx/st"}}}},\
"playerId":"mediaplayer{0}",\
"playlist":[{{\
"url":"{0}",\
"provider":"rtmp"}}]}}'.format(session)

return html.div(html.object(
html.param(value='true', name='allowfullscreen'),
html.param(value='always', name='allowscriptaccess'),
html.param(value='high', name='quality'),
html.param(value='#000000', name='bgcolor'),
html.param(value='opaque', name='wmode'),
html.param(
value=flash_vars.replace(' ', ''),
name='flashvars'),
width='100%',
height='100%',
type='application/x-shockwave-flash',
data='http://testingbot.com/assets/flowplayer-3.2.14.swf',
name='mediaplayer_api',
id='mediaplayer_api'),
id='mediaplayer{0}'.format(session),
style='border:1px solid #e6e6e6; float:right; height:240px;'
'margin-left:5px; overflow:hidden; width:320px')
6 changes: 6 additions & 0 deletions pytest_selenium/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ def saucelabs_driver(item, capabilities):
return Provider().start_driver(item, capabilities)


def testingbot_driver(item, capabilities):
"""Return a WebDriver using a TestingBot instance"""
from .cloud.testingbot import Provider
return Provider().start_driver(item, capabilities)


def _create_firefox_profile(options):
"""Return a FirefoxProfile based on the specified options"""
profile = webdriver.FirefoxProfile(options.firefox_profile)
Expand Down
11 changes: 10 additions & 1 deletion pytest_selenium/pytest_selenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
'IE',
'PhantomJS',
'Remote',
'SauceLabs']
'SauceLabs',
'TestingBot']


@pytest.fixture(autouse=True)
Expand Down Expand Up @@ -154,6 +155,14 @@ def pytest_addoption(parser):
help='default visibility for jobs',
default='public restricted')

# testingbot configuration
parser.addini('testingbot_key',
help='testingbot key',
default=os.getenv('TESTINGBOT_KEY'))
parser.addini('testingbot_secret',
help='testingbot secret',
default=os.getenv('TESTINGBOT_SECRET'))

group = parser.getgroup('selenium', 'selenium')
group._addoption('--base-url',
metavar='url',
Expand Down
50 changes: 50 additions & 0 deletions testing/test_testingbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# 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, webserver_base_url):
return partial(failure_with_output, testdir, testfile, webserver_base_url,
'--driver', 'TestingBot')


def test_missing_key(failure):
out = failure()
assert 'UsageError: TestingBot key must be set' in out


def test_missing_secret(failure, monkeypatch):
monkeypatch.setenv('TESTINGBOT_KEY', 'foo')
out = failure()
assert 'UsageError: TestingBot secret must be set' in out


def test_invalid_credentials(failure, monkeypatch):
monkeypatch.setenv('TESTINGBOT_KEY', 'foo')
monkeypatch.setenv('TESTINGBOT_SECRET', 'bar')
failure('--capability', 'browserName', 'firefox')

0 comments on commit 2a5efd2

Please sign in to comment.