From 72a6a7a94b555c358438c3c1896465211d45e4f8 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Fri, 17 Aug 2018 23:10:50 +0900 Subject: [PATCH] Switch test runner to django default runner nose is not actively maintained now and Django default test runner seems to have enough features. * Horizon test setting no longer depends on nose and related stuffs. This commit cleans up nose related dependencies. The change was made in horizon Rocky-3, so horizon 14.0.0.0b3 is required at least. * Integraion tests is marked via django.test.tag mechanism which is introduced in Django 1.10. * Rename filename of test files to names starting with 'test_' so that the django test runner can find tests expectedly. * run_tests.sh is no longer called from tox.ini, so it can be dropped. Note that the similar run_tests.sh in horizon was dropped long ago. Change-Id: I1e5471078cc95031e8819f01100319a9ee2a3a73 --- lower-constraints.txt | 3 - requirements.txt | 6 +- run_tests.sh | 527 ------------------ .../{sahara_tests.py => test_sahara.py} | 0 sahara_dashboard/test/settings.py | 2 - test-requirements.txt | 2 - tox.ini | 14 +- 7 files changed, 10 insertions(+), 544 deletions(-) delete mode 100755 run_tests.sh rename sahara_dashboard/test/api_tests/{sahara_tests.py => test_sahara.py} (100%) diff --git a/lower-constraints.txt b/lower-constraints.txt index 9301d2f5..2ad0a9ef 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -17,7 +17,6 @@ Django==1.11 django-appconf==1.0.2 django-babel==0.6.2 django-compressor==2.0 -django-nose==1.4.4 django-pyscss==2.0.2 dogpile.cache==0.6.2 eventlet==0.18.2 @@ -47,8 +46,6 @@ msgpack-python==0.4.0 munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -nose==1.3.7 -nose-exclude==0.5.0 openstacksdk==0.11.2 os-client-config==1.28.0 os-service-types==1.2.0 diff --git a/requirements.txt b/requirements.txt index a03fbb21..13329ba9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,10 +3,6 @@ # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 -# Horizon Core Requirements -Django<2,>=1.11;python_version<'3.0' # BSD -Django<2.1,>=1.11;python_version>='3.0' # BSD -django-compressor>=2.0 # MIT keystoneauth1>=3.4.0 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 @@ -18,4 +14,4 @@ python-novaclient>=9.1.0 # Apache-2.0 python-saharaclient>=2.0.0 # Apache-2.0 pytz>=2013.6 # MIT -horizon>=14.0.0.0b2 # Apache-2.0 +horizon>=14.0.0.0b3 # Apache-2.0 diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100755 index c2d2cb21..00000000 --- a/run_tests.sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/bash - -set -o errexit - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run Horizon's test suite(s)" - echo "" - echo " -V, --virtual-env Always use virtualenv. Install automatically" - echo " if not present" - echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local" - echo " environment" - echo " -c, --coverage Generate reports using Coverage" - echo " -f, --force Force a clean re-build of the virtual" - echo " environment. Useful when dependencies have" - echo " been added." - echo " -m, --manage Run a Django management command." - echo " --makemessages Create/Update English translation files." - echo " --compilemessages Compile all translation files." - echo " --check-only Do not update translation files (--makemessages only)." - echo " --pseudo Pseudo translate a language." - echo " -p, --pep8 Just run pep8" - echo " -8, --pep8-changed []" - echo " Just run PEP8 and HACKING compliance check" - echo " on files changed since HEAD~1 (or )" - echo " -P, --no-pep8 Don't run pep8 by default" - echo " -t, --tabs Check for tab characters in files." - echo " -y, --pylint Just run pylint" - echo " -q, --quiet Run non-interactively. (Relatively) quiet." - echo " Implies -V if -N is not set." - echo " --only-selenium Run only the Selenium unit tests" - echo " --with-selenium Run unit tests including Selenium tests" - echo " --selenium-headless Run Selenium tests headless" - echo " --integration Run the integration tests (requires a running " - echo " OpenStack environment)" - echo " --runserver Run the Django development server for" - echo " openstack_dashboard in the virtual" - echo " environment." - echo " --docs Just build the documentation" - echo " --backup-environment Make a backup of the environment on exit" - echo " --restore-environment Restore the environment before running" - echo " --destroy-environment Destroy the environment and exit" - echo " -h, --help Print this usage message" - echo "" - echo "Note: with no options specified, the script will try to run the tests in" - echo " a virtual environment, If no virtualenv is found, the script will ask" - echo " if you would like to create one. If you prefer to run tests NOT in a" - echo " virtual environment, simply pass the -N option." - exit -} - -# DEFAULTS FOR RUN_TESTS.SH -# -root=`pwd -P` -venv=$root/.venv -with_venv=tools/with_venv.sh -included_dirs="sahara_dashboard" - -always_venv=0 -backup_env=0 -command_wrapper="" -destroy=0 -force=0 -just_pep8=0 -just_pep8_changed=0 -no_pep8=0 -just_pylint=0 -just_docs=0 -just_tabs=0 -never_venv=0 -quiet=0 -restore_env=0 -runserver=0 -only_selenium=0 -with_selenium=0 -selenium_headless=0 -integration=0 -testopts="" -testargs="" -with_coverage=0 -makemessages=0 -compilemessages=0 -check_only=0 -pseudo=0 -manage=0 - -# NOTE(tonyb): the release team will automatically update tox.ini to point at -# the correct requirements branch when creating stable/* from master. So go to -# a little effort to get the deault from there to avoid dift and having to -# update this when branching -_default_uc=$(sed -n 's/^.*{env:UPPER_CONSTRAINTS_FILE\:\([^}]*\)}.*$/\1/p' \ - tox.ini | head -n1) - - -# Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default" -[ "$JOB_NAME" ] || JOB_NAME="default" - -function process_option { - # If running manage command, treat the rest of options as arguments. - if [ $manage -eq 1 ]; then - testargs="$testargs $1" - return 0 - fi - - case "$1" in - -h|--help) usage;; - -V|--virtual-env) always_venv=1; never_venv=0;; - -N|--no-virtual-env) always_venv=0; never_venv=1;; - -p|--pep8) just_pep8=1;; - -8|--pep8-changed) just_pep8_changed=1;; - -P|--no-pep8) no_pep8=1;; - -y|--pylint) just_pylint=1;; - -f|--force) force=1;; - -t|--tabs) just_tabs=1;; - -q|--quiet) quiet=1;; - -c|--coverage) with_coverage=1;; - -m|--manage) manage=1;; - --makemessages) makemessages=1;; - --compilemessages) compilemessages=1;; - --check-only) check_only=1;; - --pseudo) pseudo=1;; - --only-selenium) only_selenium=1;; - --with-selenium) with_selenium=1;; - --selenium-headless) selenium_headless=1;; - --integration) integration=1;; - --docs) just_docs=1;; - --runserver) runserver=1;; - --backup-environment) backup_env=1;; - --restore-environment) restore_env=1;; - --destroy-environment) destroy=1;; - -*) testopts="$testopts $1";; - *) testargs="$testargs $1" - esac -} - -function run_management_command { - ${command_wrapper} python $root/manage.py $testopts $testargs -} - -function run_server { - echo "Starting Django development server..." - ${command_wrapper} python $root/manage.py runserver $testopts $testargs - echo "Server stopped." -} - -function run_pylint { - echo "Running pylint ..." - PYTHONPATH=$root ${command_wrapper} pylint --rcfile=.pylintrc -f parseable $included_dirs > pylint.txt || true - CODE=$? - grep Global -A2 pylint.txt - if [ $CODE -lt 32 ]; then - echo "Completed successfully." - exit 0 - else - echo "Completed with problems." - exit $CODE - fi -} - -function warn_on_flake8_without_venv { - set +o errexit - ${command_wrapper} python -c "import hacking" 2>/dev/null - no_hacking=$? - set -o errexit - if [ $never_venv -eq 1 -a $no_hacking -eq 1 ]; then - echo "**WARNING**:" >&2 - echo "OpenStack hacking is not installed on your host. Its detection will be missed." >&2 - echo "Please install or use virtual env if you need OpenStack hacking detection." >&2 - fi -} - -function run_pep8 { - echo "Running flake8 ..." - warn_on_flake8_without_venv - DJANGO_SETTINGS_MODULE=sahara_dashboard.test.settings ${command_wrapper} flake8 -} - -function run_pep8_changed { - # NOTE(gilliard) We want use flake8 to check the entirety of every file that has - # a change in it. Unfortunately the --filenames argument to flake8 only accepts - # file *names* and there are no files named (eg) "nova/compute/manager.py". The - # --diff argument behaves surprisingly as well, because although you feed it a - # diff, it actually checks the file on disk anyway. - local base_commit=${testargs:-HEAD~1} - files=$(git diff --name-only $base_commit | tr '\n' ' ') - echo "Running flake8 on ${files}" - warn_on_flake8_without_venv - diff -u --from-file /dev/null ${files} | DJANGO_SETTINGS_MODULE=sahara_dashboard.test.settings ${command_wrapper} flake8 --diff - exit -} - -function run_sphinx { - echo "Building sphinx..." - DJANGO_SETTINGS_MODULE=sahara_dashboard.test.settings ${command_wrapper} python setup.py build_sphinx - echo "Build complete." -} - -function tab_check { - TAB_VIOLATIONS=`find $included_dirs -type f -regex ".*\.\(css\|js\|py\|html\)" -print0 | xargs -0 awk '/\t/' | wc -l` - if [ $TAB_VIOLATIONS -gt 0 ]; then - echo "TABS! $TAB_VIOLATIONS of them! Oh no!" - HORIZON_FILES=`find $included_dirs -type f -regex ".*\.\(css\|js\|py|\html\)"` - for TABBED_FILE in $HORIZON_FILES - do - TAB_COUNT=`awk '/\t/' $TABBED_FILE | wc -l` - if [ $TAB_COUNT -gt 0 ]; then - echo "$TABBED_FILE: $TAB_COUNT" - fi - done - fi - return $TAB_VIOLATIONS; -} - -function destroy_venv { - echo "Cleaning environment..." - echo "Removing virtualenv..." - rm -rf $venv - echo "Virtualenv removed." -} - -function sanity_check { - # Anything that should be determined prior to running the tests, server, etc. - # Don't sanity-check anything environment-related in -N flag is set - if [ $never_venv -eq 0 ]; then - if [ ! -e ${venv} ]; then - echo "Virtualenv not found at $venv. Did install_venv.py succeed?" - exit 1 - fi - fi - # Remove .pyc files. This is sanity checking because they can linger - # after old files are deleted. - find . -name "*.pyc" -exec rm -rf {} \; -} - -function backup_environment { - if [ $backup_env -eq 1 ]; then - echo "Backing up environment \"$JOB_NAME\"..." - if [ ! -e ${venv} ]; then - echo "Environment not installed. Cannot back up." - return 0 - fi - if [ -d /tmp/.horizon_environment/$JOB_NAME ]; then - mv /tmp/.horizon_environment/$JOB_NAME /tmp/.horizon_environment/$JOB_NAME.old - rm -rf /tmp/.horizon_environment/$JOB_NAME - fi - mkdir -p /tmp/.horizon_environment/$JOB_NAME - cp -r $venv /tmp/.horizon_environment/$JOB_NAME/ - # Remove the backup now that we've completed successfully - rm -rf /tmp/.horizon_environment/$JOB_NAME.old - echo "Backup completed" - fi -} - -function restore_environment { - if [ $restore_env -eq 1 ]; then - echo "Restoring environment from backup..." - if [ ! -d /tmp/.horizon_environment/$JOB_NAME ]; then - echo "No backup to restore from." - return 0 - fi - - cp -r /tmp/.horizon_environment/$JOB_NAME/.venv ./ || true - - echo "Environment restored successfully." - fi -} - -function install_venv { - # Install with install_venv.py - export UPPER_CONSTRAINTS_FILE=${UPPER_CONSTRAINTS_FILE:-$_default_uc} - export PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE-/tmp/.pip_download_cache} - export PIP_USE_MIRRORS=true - if [ $quiet -eq 1 ]; then - export PIP_NO_INPUT=true - fi - echo "Fetching new src packages..." - rm -rf $venv/src - python tools/install_venv.py - command_wrapper="$root/${with_venv}" - # Make sure it worked and record the environment version - sanity_check - chmod -R 754 $venv -} - -function run_tests { - sanity_check - - if [ $with_selenium -eq 1 ]; then - export WITH_SELENIUM=1 - elif [ $only_selenium -eq 1 ]; then - export WITH_SELENIUM=1 - export SKIP_UNITTESTS=1 - fi - - if [ $selenium_headless -eq 1 ]; then - export SELENIUM_HEADLESS=1 - fi - - if [ -z "$testargs" ]; then - run_tests_all - else - run_tests_subset - fi -} - -function run_tests_subset { - project=`echo $testargs | awk -F. '{print $1}'` - ${command_wrapper} python $root/manage.py test --settings=$project.test.settings $testopts $testargs -} - -function run_tests_all { - echo "Running sahara_dashboard application tests" - export NOSE_XUNIT_FILE=sahara_dashboard/nosetests.xml - if [ "$NOSE_WITH_HTML_OUTPUT" = '1' ]; then - export NOSE_HTML_OUT_FILE='sahara_dashboard_nose_results.html' - fi - if [ $with_coverage -eq 1 ]; then - ${command_wrapper} python -m coverage.__main__ erase - coverage_run="python -m coverage.__main__ run -p" - fi - if [ $with_selenium -eq 0 -a $integration -eq 0 ]; then - testopts="$testopts --exclude-dir=sahara_dashboard/test/integration_tests" - fi - ${command_wrapper} ${coverage_run} $root/manage.py test sahara_dashboard --settings=sahara_dashboard.test.settings $testopts - # get results of the Horizon tests - SAHARA_DASHBOARD_RESULT=$? - - if [ $with_coverage -eq 1 ]; then - echo "Generating coverage reports" - ${command_wrapper} python -m coverage.__main__ combine - ${command_wrapper} python -m coverage.__main__ xml -i --omit='/usr*,setup.py,*egg*,.venv/*' - ${command_wrapper} python -m coverage.__main__ html -i --omit='/usr*,setup.py,*egg*,.venv/*' -d reports - fi - # Remove the leftover coverage files from the -p flag earlier. - rm -f .coverage.* - - PEP8_RESULT=0 - if [ $no_pep8 -eq 0 ] && [ $only_selenium -eq 0 ]; then - run_pep8 - PEP8_RESULT=$? - fi - - TEST_RESULT=$(($SAHARA_DASHBOARD_RESULT || $PEP8_RESULT)) - if [ $TEST_RESULT -eq 0 ]; then - echo "Tests completed successfully." - else - echo "Tests failed." - fi - exit $TEST_RESULT -} - -function run_integration_tests { - export INTEGRATION_TESTS=1 - - if [ $selenium_headless -eq 1 ]; then - export SELENIUM_HEADLESS=1 - fi - - export HORIZON_INTEGRATION_TESTS_CONFIG_FILE="sahara_dashboard/test/integration_tests/horizon.conf" - - echo "Running Horizon integration tests..." - if [ -z "$testargs" ]; then - ${command_wrapper} nosetests sahara_dashboard/test/integration_tests/tests - else - ${command_wrapper} nosetests $testargs - fi - exit 0 -} - -function run_makemessages { - OPTS="-l en --no-obsolete --settings=openstack_dashboard.test.settings" - DASHBOARD_OPTS="--extension=html,txt,csv --ignore=openstack" - echo -n "horizon: " - cd horizon - ${command_wrapper} $root/manage.py makemessages $OPTS - HORIZON_PY_RESULT=$? - echo -n "horizon javascript: " - ${command_wrapper} $root/manage.py makemessages -d djangojs $OPTS - HORIZON_JS_RESULT=$? - echo -n "openstack_dashboard: " - cd ../openstack_dashboard - ${command_wrapper} $root/manage.py makemessages $DASHBOARD_OPTS $OPTS - DASHBOARD_RESULT=$? - cd .. - if [ $check_only -eq 1 ]; then - git checkout -- horizon/locale/en/LC_MESSAGES/django*.po - git checkout -- openstack_dashboard/locale/en/LC_MESSAGES/django.po - fi - exit $(($HORIZON_PY_RESULT || $HORIZON_JS_RESULT || $DASHBOARD_RESULT)) -} - -function run_compilemessages { - OPTS="--settings=openstack_dashboard.test.settings" - cd horizon - ${command_wrapper} $root/manage.py compilemessages $OPTS - HORIZON_PY_RESULT=$? - cd ../openstack_dashboard - ${command_wrapper} $root/manage.py compilemessages $OPTS - DASHBOARD_RESULT=$? - cd .. - # English is the source language, so compiled catalogs are unnecessary. - rm -vf horizon/locale/en/LC_MESSAGES/django*.mo - rm -vf openstack_dashboard/locale/en/LC_MESSAGES/django.mo - exit $(($HORIZON_PY_RESULT || $DASHBOARD_RESULT)) -} - -function run_pseudo { - for lang in $testargs - # Use English po file as the source file/pot file just like real Horizon translations - do - ${command_wrapper} $root/tools/pseudo.py openstack_dashboard/locale/en/LC_MESSAGES/django.po openstack_dashboard/locale/$lang/LC_MESSAGES/django.po $lang - ${command_wrapper} $root/tools/pseudo.py horizon/locale/en/LC_MESSAGES/django.po horizon/locale/$lang/LC_MESSAGES/django.po $lang - ${command_wrapper} $root/tools/pseudo.py horizon/locale/en/LC_MESSAGES/djangojs.po horizon/locale/$lang/LC_MESSAGES/djangojs.po $lang - done - exit $? -} - - -# ---------PREPARE THE ENVIRONMENT------------ # - -# PROCESS ARGUMENTS, OVERRIDE DEFAULTS -for arg in "$@"; do - process_option $arg -done - -if [ $quiet -eq 1 ] && [ $never_venv -eq 0 ] && [ $always_venv -eq 0 ] -then - always_venv=1 -fi - -# If destroy is set, just blow it away and exit. -if [ $destroy -eq 1 ]; then - destroy_venv - exit 0 -fi - -# Ignore all of this if the -N flag was set -if [ $never_venv -eq 0 ]; then - - # Restore previous environment if desired - if [ $restore_env -eq 1 ]; then - restore_environment - fi - - # Remove the virtual environment if --force used - if [ $force -eq 1 ]; then - destroy_venv - fi - - # Create or update venv. - install_venv - - # Create a backup of the up-to-date environment if desired - if [ $backup_env -eq 1 ]; then - backup_environment - fi -fi - -# ---------EXERCISE THE CODE------------ # - -# Run management commands -if [ $manage -eq 1 ]; then - run_management_command - exit $? -fi - -# Build the docs -if [ $just_docs -eq 1 ]; then - run_sphinx - exit $? -fi - -# Update translation files -if [ $makemessages -eq 1 ]; then - run_makemessages - exit $? -fi - -# Compile translation files -if [ $compilemessages -eq 1 ]; then - run_compilemessages - exit $? -fi - -# Generate Pseudo translation -if [ $pseudo -eq 1 ]; then - run_pseudo - exit $? -fi - -# PEP8 -if [ $just_pep8 -eq 1 ]; then - run_pep8 - exit $? -fi - -if [ $just_pep8_changed -eq 1 ]; then - run_pep8_changed - exit $? -fi - -# Pylint -if [ $just_pylint -eq 1 ]; then - run_pylint - exit $? -fi - -# Tab checker -if [ $just_tabs -eq 1 ]; then - tab_check - exit $? -fi - -# Integration tests -if [ $integration -eq 1 ]; then - run_integration_tests - exit $? -fi - -# Django development server -if [ $runserver -eq 1 ]; then - run_server - exit $? -fi - -# Full test suite -run_tests || exit diff --git a/sahara_dashboard/test/api_tests/sahara_tests.py b/sahara_dashboard/test/api_tests/test_sahara.py similarity index 100% rename from sahara_dashboard/test/api_tests/sahara_tests.py rename to sahara_dashboard/test/api_tests/test_sahara.py diff --git a/sahara_dashboard/test/settings.py b/sahara_dashboard/test/settings.py index d3c86865..c5a5afc0 100644 --- a/sahara_dashboard/test/settings.py +++ b/sahara_dashboard/test/settings.py @@ -13,8 +13,6 @@ from horizon.test.settings import * # noqa from openstack_dashboard.test.settings import * # noqa -TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' - INSTALLED_APPS = list(INSTALLED_APPS) INSTALLED_APPS.append('sahara_dashboard.content.data_processing.clusters') INSTALLED_APPS.append('sahara_dashboard.content.data_processing.jobs') diff --git a/test-requirements.txt b/test-requirements.txt index 7c7d3305..67e219dc 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,10 +5,8 @@ hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 ddt>=1.0.1 # MIT -django-nose>=1.4.4 # BSD mock>=2.0.0 # BSD netifaces>=0.10.4 # MIT -nose-exclude>=0.5.0 # LGPL python-subunit>=1.0.0 # Apache-2.0/BSD selenium>=2.50.1 # Apache-2.0 testscenarios>=0.4 # Apache-2.0/BSD diff --git a/tox.ini b/tox.ini index c9263d71..1ba62ec9 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/re -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt whitelist_externals = /bin/bash -commands = /bin/bash run_tests.sh -N --no-pep8 {posargs} +commands = {envpython} {toxinidir}/manage.py test --settings=sahara_dashboard.test.settings --exclude-tag integration {posargs} [testenv:py27] setenv = @@ -35,16 +35,20 @@ commands = {posargs} [testenv:py35dj20] basepython = python3.5 commands = pip install django>=2.0,<2.1 - /bin/bash run_tests.sh -N --no-pep8 {posargs} + {[testenv]commands} [testenv:py36dj20] basepython = python3.6 commands = pip install django>=2.0,<2.1 - /bin/bash run_tests.sh -N --no-pep8 {posargs} + {[testenv]commands} [testenv:py27integration] basepython = python2.7 -commands = /bin/bash run_tests.sh -N --integration --selenium-headless {posargs} +setenv = + INTEGRATION_TESTS=1 + SELENIUM_HEADLESS=1 + HORIZON_INTEGRATION_TESTS_CONFIG_FILE={toxinidir}/sahara_dashboard/test/integration_tests/horizon.conf +commands = {envpython} {toxinidir}/manage.py test --settings=sahara_dashboard.test.settings --verbosity 2 --tag integration {posargs} [testenv:releasenotes] basepython = python3 @@ -56,7 +60,7 @@ commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasen basepython = python3 commands = coverage erase - coverage run {toxinidir}/manage.py test sahara_dashboard --settings=sahara_dashboard.test.settings --exclude-dir=sahara_dashboard/test/integration_tests {posargs} + coverage run {toxinidir}/manage.py test --settings=sahara_dashboard.test.settings --exclude-tag integration {posargs} coverage html -d cover coverage xml -o cover/coverage.xml