diff --git a/bin/run-functional-tests.sh b/bin/run-integration-tests.sh similarity index 98% rename from bin/run-functional-tests.sh rename to bin/run-integration-tests.sh index 250c08addf6..f8bf4b715ad 100755 --- a/bin/run-functional-tests.sh +++ b/bin/run-integration-tests.sh @@ -11,7 +11,7 @@ set -xe : ${SELENIUM_HOST:="localhost"} : ${SELENIUM_PORT:="4444"} : ${BROWSER_NAME:="firefox"} -: ${TESTS_PATH:="tests/functional"} +: ${TESTS_PATH:="tests"} : ${RESULTS_PATH:="${TESTS_PATH}/results"} # Common arguments diff --git a/docker/dockerfiles/bedrock_functional_tests b/docker/dockerfiles/bedrock_integration_tests similarity index 89% rename from docker/dockerfiles/bedrock_functional_tests rename to docker/dockerfiles/bedrock_integration_tests index 3ce377b4e6a..7966f82e90b 100644 --- a/docker/dockerfiles/bedrock_functional_tests +++ b/docker/dockerfiles/bedrock_integration_tests @@ -2,7 +2,7 @@ FROM debian:jessie WORKDIR /app # Run the tests -CMD ["/app/bin/run-functional-tests.sh"] +CMD ["/app/bin/run-integration-tests.sh"] RUN apt-get update && \ @@ -11,7 +11,7 @@ RUN apt-get update && \ # Defaults ENV PYTEST_PROCESSES 5 ENV PRIVACY "public restricted" -ENV TESTS_PATH /app/tests/functional +ENV TESTS_PATH /app/tests ENV RESULTS_PATH /app/results ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/docker/jenkins/run_functional_tests.sh b/docker/jenkins/run_integration_tests.sh similarity index 51% rename from docker/jenkins/run_functional_tests.sh rename to docker/jenkins/run_integration_tests.sh index 827c8469c84..5aaf1940d32 100755 --- a/docker/jenkins/run_functional_tests.sh +++ b/docker/jenkins/run_integration_tests.sh @@ -1,7 +1,21 @@ #!/bin/bash -xe GIT_COMMIT=${GIT_COMMIT:-$(git rev-parse HEAD)} -cp docker/dockerfiles/bedrock_functional_tests Dockerfile -docker build -t bedrock_functional_tests:${GIT_COMMIT} --pull=true . +cp docker/dockerfiles/bedrock_integration_tests Dockerfile +docker build -t bedrock_integration_tests:${GIT_COMMIT} --pull=true . + +if [ -z "${BASE_URL}" ]; then + # start bedrock + docker run -d \ + --name bedrock-code-${BUILD_NUMBER} \ + -e ALLOWED_HOSTS="*" \ + -e SECRET_KEY=foo \ + -e DEBUG=False \ + -e DATABASE_URL=sqlite:////tmp/temp.db \ + mozorg/bedrock_code:${GIT_COMMIT} + + DOCKER_LINKS=(--link bedrock-code-${BUILD_NUMBER}:bedrock) + BASE_URL="http://bedrock:8000" +fi if [ "${DRIVER}" = "Remote" ]; then # Start Selenium hub and NUMBER_OF_NODES (default 5) firefox nodes. @@ -13,26 +27,18 @@ if [ "${DRIVER}" = "Remote" ]; then docker pull selenium/hub:${SELENIUM_VERSION} docker pull selenium/node-firefox:${SELENIUM_VERSION} - # start bedrock - docker run -d \ - --name bedrock-code-${BUILD_NUMBER} \ - -e ALLOWED_HOSTS="*" \ - -e SECRET_KEY=foo \ - -e DEBUG=False \ - -e DATABASE_URL=sqlite:////tmp/temp.db \ - mozorg/bedrock_code:$GIT_COMMIT - # start selenium grid hub docker run -d \ --name bedrock-selenium-hub-${BUILD_NUMBER} \ selenium/hub:${SELENIUM_VERSION} + DOCKER_LINKS=(${DOCKER_LINKS[@]} --link bedrock-selenium-hub-${BUILD_NUMBER}:hub) + SELENIUM_HOST="hub" # start selenium grid nodes for NODE_NUMBER in `seq ${NUMBER_OF_NODES:-5}`; do docker run -d \ --name bedrock-selenium-node-${NODE_NUMBER}-${BUILD_NUMBER} \ - --link bedrock-selenium-hub-${BUILD_NUMBER}:hub \ - --link bedrock-code-${BUILD_NUMBER}:bedrock \ + ${DOCKER_LINKS[@]} \ selenium/node-firefox:${SELENIUM_VERSION} while ! ${SELENIUM_READY}; do IP=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' bedrock-selenium-node-${NODE_NUMBER}-${BUILD_NUMBER}` @@ -40,29 +46,22 @@ if [ "${DRIVER}" = "Remote" ]; then if eval ${CMD}; then SELENIUM_READY=true; fi done done - - docker run -v `pwd`/results:/app/results \ - --link bedrock-selenium-hub-${BUILD_NUMBER}:hub \ - --link bedrock-code-${BUILD_NUMBER}:bedrock \ - -e BASE_URL=http://bedrock:8000 \ - -e DRIVER=${DRIVER} \ - -e SELENIUM_HOST=hub \ - -e MARK_EXPRESSION=${MARK_EXPRESSION} \ - bedrock_functional_tests:$GIT_COMMIT -else - # Runs functional tests that either don't require Selenium, use a local - # Selenium driver, or use a remote Selenium server (such as Sauce Labs). - docker run -v `pwd`/results:/app/results \ - -e BASE_URL=${BASE_URL} \ - -e DRIVER=${DRIVER} \ - -e SAUCELABS_USERNAME=${SAUCELABS_USERNAME} \ - -e SAUCELABS_API_KEY=${SAUCELABS_API_KEY} \ - -e BROWSER_NAME="${BROWSER_NAME}" \ - -e BROWSER_VERSION=${BROWSER_VERSION} \ - -e PLATFORM="${PLATFORM}" \ - -e SELENIUM_VERSION=${SELENIUM_VERSION} \ - -e BUILD_TAG=${BUILD_TAG} \ - -e SCREEN_RESOLUTION=${SCREEN_RESOLUTION} \ - -e MARK_EXPRESSION="${MARK_EXPRESSION}" \ - bedrock_functional_tests:${GIT_COMMIT} fi + +docker run -v `pwd`/results:/app/results \ + ${DOCKER_LINKS[@]} \ + -e BASE_URL=${BASE_URL} \ + -e DRIVER=${DRIVER} \ + -e SAUCELABS_USERNAME=${SAUCELABS_USERNAME} \ + -e SAUCELABS_API_KEY=${SAUCELABS_API_KEY} \ + -e BROWSER_NAME="${BROWSER_NAME}" \ + -e BROWSER_VERSION=${BROWSER_VERSION} \ + -e PLATFORM="${PLATFORM}" \ + -e SELENIUM_HOST=${SELENIUM_HOST} \ + -e SELENIUM_PORT=${SELENIUM_PORT} \ + -e SELENIUM_VERSION=${SELENIUM_VERSION} \ + -e BUILD_TAG=${BUILD_TAG} \ + -e SCREEN_RESOLUTION=${SCREEN_RESOLUTION} \ + -e MARK_EXPRESSION="${MARK_EXPRESSION}" \ + -e TESTS_PATH="${TESTS_PATH}" \ + bedrock_integration_tests:${GIT_COMMIT} diff --git a/tests/redirects/base.py b/tests/redirects/base.py index dba66c711fe..566047384ed 100644 --- a/tests/redirects/base.py +++ b/tests/redirects/base.py @@ -18,7 +18,8 @@ def get_abs_url(url, base_url): def url_test(url, location=None, status_code=requests.codes.moved_permanently, - req_headers=None, req_kwargs=None, resp_headers=None, query=None): + req_headers=None, req_kwargs=None, resp_headers=None, query=None, + follow_redirects=False, final_status_code=requests.codes.ok): """ Function for producing a config dict for the redirect test. @@ -46,6 +47,8 @@ def url_test(url, location=None, status_code=requests.codes.moved_permanently, :param req_kwargs: Extra arguments to pass to requests.get() :param resp_headers: Dict of headers expected in the response. :param query: Dict of expected query params in `location` URL. + :param follow_redirects: Boolean indicating whether redirects should be followed. + :param final_status_code: Expected status code after following any redirects. :return: dict or list of dicts """ test_data = { @@ -56,6 +59,8 @@ def url_test(url, location=None, status_code=requests.codes.moved_permanently, 'req_kwargs': req_kwargs, 'resp_headers': resp_headers, 'query': query, + 'follow_redirects': follow_redirects, + 'final_status_code': final_status_code, } expanded_urls = list(braceexpand(url)) num_urls = len(expanded_urls) @@ -90,7 +95,8 @@ def url_test(url, location=None, status_code=requests.codes.moved_permanently, def assert_valid_url(url, location=None, status_code=requests.codes.moved_permanently, req_headers=None, req_kwargs=None, resp_headers=None, - query=None, base_url=None): + query=None, base_url=None, follow_redirects=False, + final_status_code=requests.codes.ok): """ Define a test of a URL's response. :param url: The URL in question (absolute or relative). @@ -101,8 +107,10 @@ def assert_valid_url(url, location=None, status_code=requests.codes.moved_perman :param resp_headers: Dict of headers expected in the response. :param base_url: Base URL for the site to test. :param query: Dict of expected query params in `location` URL. + :param follow_redirects: Boolean indicating whether redirects should be followed. + :param final_status_code: Expected status code after following any redirects. """ - kwargs = {'allow_redirects': False} + kwargs = {'allow_redirects': follow_redirects} if req_headers: kwargs['headers'] = req_headers if req_kwargs: @@ -112,8 +120,11 @@ def assert_valid_url(url, location=None, status_code=requests.codes.moved_perman resp = requests.get(abs_url, **kwargs) # so that the value will appear in locals in test output resp_location = resp.headers.get('location') - assert resp.status_code == status_code - if location: + if follow_redirects: + assert resp.status_code == final_status_code + else: + assert resp.status_code == status_code + if location and not follow_redirects: if query: # all query values must be lists for k, v in query.items(): @@ -133,7 +144,7 @@ def assert_valid_url(url, location=None, status_code=requests.codes.moved_perman except AttributeError: assert abs_location == resp_location - if resp_headers: + if resp_headers and not follow_redirects: for name, value in resp_headers.items(): print name, value assert name in resp.headers diff --git a/tests/redirects/map_globalconf.py b/tests/redirects/map_globalconf.py index e424ee37717..3eb1c6513bf 100644 --- a/tests/redirects/map_globalconf.py +++ b/tests/redirects/map_globalconf.py @@ -194,7 +194,7 @@ # bug 860865, 1101220 url_test('/firefox/all-{beta,rc}{/,.html}', '/firefox/beta/all/'), url_test('/firefox/all-aurora{/,.html}', '/firefox/developer/all/'), - url_test('/firefox/aurora/{all,notes,system-requirements}/' + url_test('/firefox/aurora/{all,notes,system-requirements}/', '/firefox/developer/{all,notes,system-requirements}/'), url_test('/firefox/organizations/all.html', '/firefox/organizations/all/'), @@ -980,6 +980,9 @@ url_test('/en-US/firefox/notes/', re.compile(r'/en-US/firefox/[\d\.]+/releasenotes/'), status_code=requests.codes.found), + url_test('/firefox/brand/', '/styleguide/'), + url_test('/firefox/channel/android/', '/en-US/firefox/channel/android/'), + url_test('/en-US/firefox/channel/android/', '/firefox/channel/'), # Bug 1243060 url_test('/firefox/tiles/', diff --git a/tests/redirects/test_redirects.py b/tests/redirects/test_redirects.py new file mode 100644 index 00000000000..ace43de44c0 --- /dev/null +++ b/tests/redirects/test_redirects.py @@ -0,0 +1,45 @@ +"""Test redirects from the global.conf file.""" +from __future__ import absolute_import +from operator import itemgetter + +import pytest + +from .base import assert_valid_url +from .map_htaccess import URLS as HTA_URLS +from .map_globalconf import URLS as GLOBAL_URLS +from .map_external import URLS as EXTERNAL_URLS +from .map_locales import URLS as LOCALE_URLS + + +@pytest.mark.smoke +@pytest.mark.headless +@pytest.mark.nondestructive +@pytest.mark.parametrize('url', GLOBAL_URLS, ids=itemgetter('url')) +def test_global_conf_url(url, base_url): + url['base_url'] = base_url + assert_valid_url(**url) + + +@pytest.mark.smoke +@pytest.mark.headless +@pytest.mark.nondestructive +@pytest.mark.parametrize('url', HTA_URLS, ids=itemgetter('url')) +def test_htaccess_url(url, base_url): + url['base_url'] = base_url + assert_valid_url(**url) + + +@pytest.mark.smoke +@pytest.mark.headless +@pytest.mark.nondestructive +@pytest.mark.parametrize('url', LOCALE_URLS) +def test_locale_url(url, base_url): + url['base_url'] = base_url + assert_valid_url(**url) + + +@pytest.mark.headless +@pytest.mark.nondestructive +@pytest.mark.parametrize('url', EXTERNAL_URLS, ids=itemgetter('url')) +def test_external_url(url): + assert_valid_url(**url) diff --git a/tests/redirects/test_urls.py b/tests/redirects/test_urls.py index 48a581298a9..2164f5a49fa 100644 --- a/tests/redirects/test_urls.py +++ b/tests/redirects/test_urls.py @@ -7,43 +7,15 @@ from .base import assert_valid_url from .map_410 import URLS_410 -from .map_htaccess import URLS as HTA_URLS -from .map_globalconf import URLS as GLOBAL_URLS from .map_external import URLS as EXTERNAL_URLS -from .map_locales import URLS as LOCALE_URLS - - -@pytest.mark.smoke -@pytest.mark.headless -@pytest.mark.nondestructive -@pytest.mark.parametrize('url', GLOBAL_URLS, ids=itemgetter('url')) -def test_global_conf_url(url, base_url): - url['base_url'] = base_url - assert_valid_url(**url) - - -@pytest.mark.smoke -@pytest.mark.headless -@pytest.mark.nondestructive -@pytest.mark.parametrize('url', HTA_URLS, ids=itemgetter('url')) -def test_htaccess_url(url, base_url): - url['base_url'] = base_url - assert_valid_url(**url) - - -@pytest.mark.smoke -@pytest.mark.headless -@pytest.mark.nondestructive -@pytest.mark.parametrize('url', LOCALE_URLS) -def test_locale_url(url, base_url): - url['base_url'] = base_url - assert_valid_url(**url) @pytest.mark.headless @pytest.mark.nondestructive @pytest.mark.parametrize('url', EXTERNAL_URLS, ids=itemgetter('url')) def test_external_url(url): + del url['location'] + url['follow_redirects'] = True assert_valid_url(**url) @@ -52,7 +24,7 @@ def test_external_url(url): @pytest.mark.nondestructive @pytest.mark.parametrize('url', URLS_410) def test_410_url(url, base_url): - assert_valid_url(url, status_code=requests.codes.gone, base_url=base_url) + assert_valid_url(url, base_url=base_url, status_code=requests.codes.gone) @pytest.mark.smoke @@ -70,3 +42,46 @@ def test_404_url(base_url): @pytest.mark.nondestructive def test_x_robots_tag(base_url): assert_valid_url(base_url, resp_headers={'x-robots-tag': 'noodp'}) + + +@pytest.mark.headless +@pytest.mark.nondestructive +@pytest.mark.parametrize('url', [ + '/firefox/', + '/firefox/all/', + '/firefox/android/', + '/firefox/android/faq/', + '/firefox/aurora/all/', + '/firefox/beta/all/', + '/firefox/brand/', + '/firefox/channel/', + '/firefox/channel/android/', + '/firefox/desktop/', + '/firefox/developer/', + '/firefox/geolocation/', + '/firefox/installer-help/', + '/firefox/interest-dashboard/', + '/firefox/latest/releasenotes/', + '/firefox/mobile/', + '/firefox/new/', + '/firefox/nightly/firstrun/', + '/firefox/organizations/', + '/firefox/os/', + '/firefox/os/notes/1.1/', + '/firefox/partners/', + '/firefox/releases/', + '/firefox/speed/', + '/firefox/sync/', + '/firefox/tiles/', + '/firefox/unsupported-systems/', + '/firefox/unsupported/EOL/', + # Legacy URLs (Bug 1110927) + '/firefox/panorama/', + '/firefox/start/central.html', + '/firefox/sync/firstrun.html', + # Thunberbird URLs + '/thunderbird/all/', + '/thunderbird/releases/' +]) +def test_url(url, base_url): + assert_valid_url(url, base_url=base_url, follow_redirects=True)