Skip to content

Commit

Permalink
Move sensitive configuration options into separate files
Browse files Browse the repository at this point in the history
Read credentials for cloud testing services from configuration files in the working or home directory. Fixes #60
  • Loading branch information
davehunt committed Jan 24, 2017
1 parent 39cffc1 commit 11e78f8
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 129 deletions.
45 changes: 22 additions & 23 deletions pytest_selenium/drivers/browserstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
# 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/.

try:
import configparser
except ImportError:
# Python 2.7
import ConfigParser as configparser

import os

import pytest
Expand All @@ -12,24 +18,15 @@
EXECUTOR_URL = 'http://{username}:{key}@hub.browserstack.com:80/wd/hub'


def pytest_addoption(parser):
parser.addini('browserstack_username',
help='browserstack username',
default=os.getenv('BROWSERSTACK_USERNAME'))
parser.addini('browserstack_access_key',
help='browserstack access key',
default=os.getenv('BROWSERSTACK_ACCESS_KEY'))


@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'))
session_id = item._driver.session_id
auth = (_username(item.config), _access_key(item.config))
api_url = API_JOB_URL.format(session=session_id)
auth = (credentials()['username'], credentials()['key'])

try:
job_info = requests.get(api_url, auth=auth, timeout=10).json()
Expand Down Expand Up @@ -63,24 +60,26 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):

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


def _access_key(config):
access_key = config.getini('browserstack_access_key')
if not access_key:
raise pytest.UsageError('BrowserStack access key must be set')
return access_key


def _username(config):
username = config.getini('browserstack_username')
def credentials():
config = configparser.ConfigParser()
config.read(['.browserstack', os.path.expanduser('~/.browserstack')])
try:
username = config.get('credentials', 'username')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
username = os.getenv('BROWSERSTACK_USERNAME')
if not username:
raise pytest.UsageError('BrowserStack username must be set')
return username
try:
key = config.get('credentials', 'key')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
key = os.getenv('BROWSERSTACK_ACCESS_KEY')
if not key:
raise pytest.UsageError('BrowserStack access key must be set')
return {'username': username, 'key': key}
58 changes: 28 additions & 30 deletions pytest_selenium/drivers/crossbrowsertesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
# 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/.

try:
import configparser
except ImportError:
# Python 2.7
import ConfigParser as configparser

import os

from py.xml import html
Expand All @@ -13,23 +19,15 @@
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

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

if videos and len(videos) > 0:
Expand All @@ -45,9 +43,10 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):
passed = report.passed or (report.failed and hasattr(report, 'wasxfail'))

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

url = info.get('show_result_public_url')
Expand All @@ -65,7 +64,7 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):
r = requests.put(
API_URL.format(session=info.get('selenium_test_id')),
data=data,
auth=_auth(item),
auth=auth,
timeout=10)
r.raise_for_status()
except Exception as e:
Expand All @@ -75,32 +74,31 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):

def driver_kwargs(request, test, capabilities, **kwargs):
capabilities.setdefault('name', test)
executor = EXECUTOR_URL.format(
username=_username(request.config),
key=_auth_key(request.config))
executor = EXECUTOR_URL.format(**credentials())
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')
def credentials():
config = configparser.ConfigParser()
config.read([
'.crossbrowsertesting',
os.path.expanduser('~/.crossbrowsertesting')])
try:
username = config.get('credentials', 'username')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
username = os.getenv('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))
try:
key = config.get('credentials', 'key')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
key = os.getenv('CROSSBROWSERTESTING_AUTH_KEY')
if not key:
raise pytest.UsageError('CrossBrowserTesting auth key must be set')
return {'username': username, 'key': key}


def _video_html(video):
Expand Down
48 changes: 23 additions & 25 deletions pytest_selenium/drivers/saucelabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
# 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/.

try:
import configparser
except ImportError:
# Python 2.7
import ConfigParser as configparser

import json
import os

Expand All @@ -16,15 +22,6 @@
JOB_URL = 'http://saucelabs.com/jobs/{session}'


def pytest_addoption(parser):
parser.addini('sauce_labs_username',
help='sauce labs username',
default=os.getenv('SAUCELABS_USERNAME'))
parser.addini('sauce_labs_api_key',
help='sauce labs api key',
default=os.getenv('SAUCELABS_API_KEY'))


@pytest.mark.optionalhook
def pytest_selenium_capture_debug(item, report, extra):
if item.config.getoption('driver') != DRIVER:
Expand All @@ -51,9 +48,8 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):

try:
# Update the job result
username = _username(item.config)
auth = (username, _api_key(item.config))
api_url = API_JOB_URL.format(username=username, session=session_id)
auth = (credentials()['username'], credentials()['key'])
api_url = API_JOB_URL.format(session=session_id, **credentials())
job_info = requests.get(api_url, auth=auth, timeout=10).json()
if report.when == 'setup' or job_info.get('passed') is not False:
# Only update the result if it's not already marked as failed
Expand All @@ -71,27 +67,29 @@ def driver_kwargs(request, test, capabilities, **kwargs):
tags = capabilities.get('tags', []) + markers
if tags:
capabilities['tags'] = tags
executor = EXECUTOR_URL.format(
username=_username(request.config),
key=_api_key(request.config))
executor = EXECUTOR_URL.format(**credentials())
kwargs = {
'command_executor': executor,
'desired_capabilities': capabilities}
return kwargs


def _api_key(config):
api_key = config.getini('sauce_labs_api_key')
if not api_key:
raise pytest.UsageError('Sauce Labs API key must be set')
return api_key


def _username(config):
username = config.getini('sauce_labs_username')
def credentials():
config = configparser.ConfigParser()
config.read(['.saucelabs', os.path.expanduser('~/.saucelabs')])
try:
username = config.get('credentials', 'username')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
username = os.getenv('SAUCELABS_USERNAME')
if not username:
raise pytest.UsageError('Sauce Labs username must be set')
return username
try:
key = config.get('credentials', 'key')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
key = os.getenv('SAUCELABS_API_KEY')
if not key:
raise pytest.UsageError('Sauce Labs API key must be set')
return {'username': username, 'key': key}


def _video_html(session):
Expand Down
41 changes: 20 additions & 21 deletions pytest_selenium/drivers/testingbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
# 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/.

try:
import configparser
except ImportError:
# Python 2.7
import ConfigParser as configparser

import os

import pytest
Expand All @@ -15,15 +21,6 @@
JOB_URL = 'http://testingbot.com/members/tests/{session}'


def pytest_addoption(parser):
parser.addini('testingbot_key',
help='testingbot key',
default=os.getenv('TESTINGBOT_KEY'))
parser.addini('testingbot_secret',
help='testingbot secret',
default=os.getenv('TESTINGBOT_SECRET'))


@pytest.mark.optionalhook
def pytest_selenium_capture_debug(item, report, extra):
if item.config.getoption('driver') != DRIVER:
Expand All @@ -50,7 +47,7 @@ def pytest_selenium_runtest_makereport(item, report, summary, extra):

try:
# Update the job result
auth = (_key(item.config), _secret(item.config))
auth = (credentials()['key'], credentials()['secret'])
api_url = API_JOB_URL.format(session=session_id)
job_info = requests.get(api_url, auth=auth, timeout=10).json()
if report.when == 'setup' or job_info.get('success') is not False:
Expand All @@ -69,27 +66,29 @@ def driver_kwargs(request, test, capabilities, **kwargs):
groups = capabilities.get('groups', []) + markers
if groups:
capabilities['groups'] = groups
executor = EXECUTOR_URL.format(
key=_key(request.config),
secret=_secret(request.config))
executor = EXECUTOR_URL.format(**credentials())
kwargs = {
'command_executor': executor,
'desired_capabilities': capabilities}
return kwargs


def _key(config):
key = config.getini('testingbot_key')
def credentials():
config = configparser.ConfigParser()
config.read(['.testingbot', os.path.expanduser('~/.testingbot')])
try:
key = config.get('credentials', 'key')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
key = os.getenv('TESTINGBOT_KEY')
if not key:
raise pytest.UsageError('TestingBot key must be set')
return key


def _secret(config):
secret = config.getini('testingbot_secret')
try:
secret = config.get('credentials', 'secret')
except (configparser.NoSectionError, configparser.NoOptionError, KeyError):
secret = os.getenv('TESTINGBOT_SECRET')
if not secret:
raise pytest.UsageError('TestingBot secret must be set')
return secret
return {'key': key, 'secret': secret}


def _video_html(session):
Expand Down
Loading

0 comments on commit 11e78f8

Please sign in to comment.