diff --git a/cms/envs/acceptance.py b/cms/envs/acceptance.py index bbb767118c..db7332ee22 100644 --- a/cms/envs/acceptance.py +++ b/cms/envs/acceptance.py @@ -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) diff --git a/common/djangoapps/terrain/browser.py b/common/djangoapps/terrain/browser.py index 6454cbf644..ca91298ec4 100644 --- a/common/djangoapps/terrain/browser.py +++ b/common/djangoapps/terrain/browser.py @@ -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() diff --git a/common/djangoapps/terrain/steps.py b/common/djangoapps/terrain/steps.py index c4783d4aca..3a33028699 100644 --- a/common/djangoapps/terrain/steps.py +++ b/common/djangoapps/terrain/steps.py @@ -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: diff --git a/jenkins/test_acceptance.sh b/jenkins/test_acceptance.sh index 5577ea6838..8070576231 100755 --- a/jenkins/test_acceptance.sh +++ b/jenkins/test_acceptance.sh @@ -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}" diff --git a/lms/envs/acceptance.py b/lms/envs/acceptance.py index 2182bbcad6..0383c291b9 100644 --- a/lms/envs/acceptance.py +++ b/lms/envs/acceptance.py @@ -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) diff --git a/lms/envs/sauce.py b/lms/envs/sauce.py index f0f9e3f14c..89e0a4fe21 100644 --- a/lms/envs/sauce.py +++ b/lms/envs/sauce.py @@ -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],