Commit da538b87 by Jay Zoldak

Merge pull request #1044 from edx/zoldak/acceptance-grid

Add ability to run against generic selenium grid
parents 1d2e0b66 4c411e21
......@@ -84,12 +84,26 @@ USE_I18N = True
# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command
INSTALLED_APPS += ('lettuce.django',)
LETTUCE_APPS = ('contentstore',)
LETTUCE_SERVER_PORT = choice(PORTS) if SAUCE.get('SAUCE_ENABLED') else randint(1024, 65535)
LETTUCE_BROWSER = os.environ.get('LETTUCE_BROWSER', 'chrome')
# Where to run: local, saucelabs, or grid
LETTUCE_SELENIUM_CLIENT = os.environ.get('LETTUCE_SELENIUM_CLIENT', 'local')
SELENIUM_GRID = {
'URL': 'http://127.0.0.1:4444/wd/hub',
'BROWSER': LETTUCE_BROWSER,
}
#####################################################################
# Lastly, see if the developer has any local overrides.
try:
from .private import * # pylint: disable=F0401
except ImportError:
pass
# Because an override for where to run will affect which ports to use,
# set this up after the local overrides.
if LETTUCE_SELENIUM_CLIENT == 'saucelabs':
LETTUCE_SERVER_PORT = choice(PORTS)
else:
LETTUCE_SERVER_PORT = randint(1024, 65535)
......@@ -43,18 +43,18 @@ LOGGER.info("Loading the lettuce acceptance testing terrain file...")
MAX_VALID_BROWSER_ATTEMPTS = 20
def get_username_and_key():
def get_saucelabs_username_and_key():
"""
Returns the Sauce Labs username and access ID as set by environment variables
"""
return {"username": settings.SAUCE.get('USERNAME'), "access-key": settings.SAUCE.get('ACCESS_ID')}
def set_job_status(jobid, passed=True):
def set_saucelabs_job_status(jobid, passed=True):
"""
Sets the job status on sauce labs
"""
config = get_username_and_key()
config = get_saucelabs_username_and_key()
url = 'http://saucelabs.com/rest/v1/{}/jobs/{}'.format(config['username'], world.jobid)
body_content = dumps({"passed": passed})
base64string = encodestring('{}:{}'.format(config['username'], config['access-key']))[:-1]
......@@ -63,7 +63,7 @@ def set_job_status(jobid, passed=True):
return result.status_code == 200
def make_desired_capabilities():
def make_saucelabs_desired_capabilities():
"""
Returns a DesiredCapabilities object corresponding to the environment sauce parameters
"""
......@@ -88,9 +88,9 @@ def initial_setup(server):
"""
Launch the browser once before executing the tests.
"""
world.absorb(settings.SAUCE.get('SAUCE_ENABLED'), 'SAUCE_ENABLED')
world.absorb(settings.LETTUCE_SELENIUM_CLIENT, 'LETTUCE_SELENIUM_CLIENT')
if not world.SAUCE_ENABLED:
if world.LETTUCE_SELENIUM_CLIENT == 'local':
browser_driver = getattr(settings, 'LETTUCE_BROWSER', 'chrome')
# There is an issue with ChromeDriver2 r195627 on Ubuntu
......@@ -121,15 +121,26 @@ def initial_setup(server):
world.browser.driver.set_window_size(1280, 1024)
else:
config = get_username_and_key()
elif world.LETTUCE_SELENIUM_CLIENT == 'saucelabs':
config = get_saucelabs_username_and_key()
world.browser = Browser(
'remote',
url="http://{}:{}@ondemand.saucelabs.com:80/wd/hub".format(config['username'], config['access-key']),
**make_desired_capabilities()
**make_saucelabs_desired_capabilities()
)
world.browser.driver.implicitly_wait(30)
elif world.LETTUCE_SELENIUM_CLIENT == 'grid':
world.browser = Browser(
'remote',
url=settings.SELENIUM_GRID.get('URL'),
browser=settings.SELENIUM_GRID.get('BROWSER'),
)
world.browser.driver.implicitly_wait(30)
else:
raise Exception("Unknown selenium client '{}'".format(world.LETTUCE_SELENIUM_CLIENT))
world.absorb(world.browser.driver.session_id, 'jobid')
......@@ -183,6 +194,6 @@ def teardown_browser(total):
"""
Quit the browser after executing the tests.
"""
if world.SAUCE_ENABLED:
set_job_status(world.jobid, total.scenarios_ran == total.scenarios_passed)
if world.LETTUCE_SELENIUM_CLIENT == 'saucelabs':
set_saucelabs_job_status(world.jobid, total.scenarios_ran == total.scenarios_passed)
world.browser.quit()
......@@ -138,9 +138,10 @@ def should_have_link_with_path_and_text(step, path, text):
@step(r'should( not)? see "(.*)" (?:somewhere|anywhere) (?:in|on) (?:the|this) page')
def should_see_in_the_page(step, doesnt_appear, text):
multiplier = 1
if world.SAUCE_ENABLED:
if world.LETTUCE_SELENIUM_CLIENT == 'saucelabs':
multiplier = 2
else:
multiplier = 1
if doesnt_appear:
assert world.browser.is_text_not_present(text, wait_time=5*multiplier)
else:
......
......@@ -36,7 +36,7 @@ SKIP_TESTS=""
if [ ! -z ${LETTUCE_BROWSER+x} ]; then
SKIP_TESTS="--tag -skip_$LETTUCE_BROWSER"
fi
if [ ! -z ${SAUCE_ENABLED+x} ]; then
if [ "$LETTUCE_SELENIUM_CLIENT" == saucelabs ]; then
# SAUCE_INFO is a - seperated string PLATFORM-BROWSER-VERSION-DEVICE
# Error checking is done in the setting up of the browser
IFS='-' read -a SAUCE <<< "${SAUCE_INFO}"
......
......@@ -71,23 +71,6 @@ DATABASES = {
}
}
# Set up XQueue information so that the lms will send
# requests to a mock XQueue server running locally
XQUEUE_PORT = choice(PORTS) if SAUCE.get('SAUCE_ENABLED') else randint(1024, 65535)
XQUEUE_INTERFACE = {
"url": "http://127.0.0.1:%d" % XQUEUE_PORT,
"django_auth": {
"username": "lms",
"password": "***REMOVED***"
},
"basic_auth": ('anant', 'agarwal'),
}
# Set up Video information so that the lms will send
# requests to a mock Youtube server running locally
VIDEO_PORT = XQUEUE_PORT + 2
# Forums are disabled in test.py to speed up unit tests, but we do not have
# per-test control for acceptance tests
MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = True
......@@ -123,12 +106,52 @@ FEEDBACK_SUBMISSION_EMAIL = 'dummy@example.com'
# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command
INSTALLED_APPS += ('lettuce.django',)
LETTUCE_APPS = ('courseware',)
LETTUCE_SERVER_PORT = choice(PORTS) if SAUCE.get('SAUCE_ENABLED') else randint(1024, 65535)
LETTUCE_BROWSER = os.environ.get('LETTUCE_BROWSER', 'chrome')
# Where to run: local, saucelabs, or grid
LETTUCE_SELENIUM_CLIENT = os.environ.get('LETTUCE_SELENIUM_CLIENT', 'local')
SELENIUM_GRID = {
'URL': 'http://127.0.0.1:4444/wd/hub',
'BROWSER': LETTUCE_BROWSER,
}
#####################################################################
# Lastly, see if the developer has any local overrides.
# See if the developer has any local overrides.
try:
from .private import * # pylint: disable=F0401
except ImportError:
pass
# Because an override for where to run will affect which ports to use,
# set these up after the local overrides.
if LETTUCE_SELENIUM_CLIENT == 'saucelabs':
LETTUCE_SERVER_PORT = choice(PORTS)
PORTS.remove(LETTUCE_SERVER_PORT)
else:
LETTUCE_SERVER_PORT = randint(1024, 65535)
# Set up XQueue information so that the lms will send
# requests to a mock XQueue server running locally
if LETTUCE_SELENIUM_CLIENT == 'saucelabs':
XQUEUE_PORT = choice(PORTS)
PORTS.remove(XQUEUE_PORT)
else:
XQUEUE_PORT = randint(1024, 65535)
XQUEUE_INTERFACE = {
"url": "http://127.0.0.1:%d" % XQUEUE_PORT,
"django_auth": {
"username": "lms",
"password": "***REMOVED***"
},
"basic_auth": ('anant', 'agarwal'),
}
# Set up Video information so that the lms will send
# requests to a mock Youtube server running locally
if LETTUCE_SELENIUM_CLIENT == 'saucelabs':
VIDEO_PORT = choice(PORTS)
PORTS.remove(VIDEO_PORT)
else:
VIDEO_PORT = randint(1024, 65535)
......@@ -51,7 +51,6 @@ SAUCE_INFO = ALL_CONFIG.get(os.environ.get('SAUCE_INFO', 'Linux-chrome--'))
# Information needed to utilize Sauce Labs.
SAUCE = {
'SAUCE_ENABLED': os.environ.get('SAUCE_ENABLED'),
'USERNAME': os.environ.get('SAUCE_USER_NAME'),
'ACCESS_ID': os.environ.get('SAUCE_API_KEY'),
'PLATFORM': SAUCE_INFO[0],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment