From 02eb985124efa92bf735712db0ed174c40b74d14 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Mon, 24 Dec 2012 22:01:28 -0600 Subject: [PATCH] Move from nose to testr. Granted - this takes the test suite from 3 seconds to 1 second... but there are a bunch of other ways (correctness) that testr is better than nose. Removed tests/v1/utils - it was not being used anywhere. Part of blueprint grizzly-testtools. Change-Id: I54d9a0b7dc22305ec60d779d6f19025a0b5dc785 --- .gitignore | 2 ++ .testr.conf | 4 +++ run_tests.sh | 63 +++++++++++++++++++++++++++++++-------------- setup.cfg | 8 ------ setup.py | 1 - tests/utils.py | 15 ++++++++++- tests/v1/utils.py | 29 --------------------- tools/test-requires | 7 +++-- tox.ini | 29 +++++---------------- 9 files changed, 73 insertions(+), 85 deletions(-) create mode 100644 .testr.conf delete mode 100644 tests/v1/utils.py diff --git a/.gitignore b/.gitignore index b0dca9bd5..2c64f1527 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .coverage .venv .tox +.testrepository +subunit.log *,cover cover *.pyc diff --git a/.testr.conf b/.testr.conf new file mode 100644 index 000000000..2109af6ce --- /dev/null +++ b/.testr.conf @@ -0,0 +1,4 @@ +[DEFAULT] +test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ./tests $LISTOPT $IDOPTION +test_id_option=--load-list $IDFILE +test_list_option=--list diff --git a/run_tests.sh b/run_tests.sh index 96bd437d6..e74a0cada 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -9,7 +9,6 @@ function usage { echo " -V, --virtual-env Always use virtualenv. Install automatically if not present" echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment" echo " -s, --no-site-packages Isolate the virtualenv from the global Python environment" - echo " -x, --stop Stop running tests after the first error or failure." echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added." echo " -p, --pep8 Just run pep8" echo " -P, --no-pep8 Don't run pep8" @@ -33,8 +32,8 @@ function process_option { -p|--pep8) just_pep8=1;; -P|--no-pep8) no_pep8=1;; -c|--coverage) coverage=1;; - -*) noseopts="$noseopts $1";; - *) noseargs="$noseargs $1" + -*) testropts="$testropts $1";; + *) testrargs="$testrargs $1" esac } @@ -45,36 +44,62 @@ never_venv=0 force=0 no_site_packages=0 installvenvopts= -noseargs= -noseopts= +testrargs= +testropts= wrapper="" just_pep8=0 no_pep8=0 coverage=0 +LANG=en_US.UTF-8 +LANGUAGE=en_US:en +LC_ALL=C + for arg in "$@"; do process_option $arg done -# If enabled, tell nose to collect coverage data -if [ $coverage -eq 1 ]; then - noseopts="$noseopts --with-coverage --cover-package=cinderclient" -fi - if [ $no_site_packages -eq 1 ]; then installvenvopts="--no-site-packages" fi +function init_testr { + if [ ! -d .testrepository ]; then + ${wrapper} testr init + fi +} + function run_tests { - # Cleanup *.pyc + # Cleanup *pyc ${wrapper} find . -type f -name "*.pyc" -delete + + if [ $coverage -eq 1 ]; then + # Do not test test_coverage_ext when gathering coverage. + if [ "x$testrargs" = "x" ]; then + testrargs="^(?!.*test_coverage_ext).*$" + fi + export PYTHON="${wrapper} coverage run --source cinderclient --parallel-mode" + fi # Just run the test suites in current environment - ${wrapper} $NOSETESTS - # If we get some short import error right away, print the error log directly + set +e + TESTRTESTS="$TESTRTESTS $testrargs" + echo "Running \`${wrapper} $TESTRTESTS\`" + ${wrapper} $TESTRTESTS RESULT=$? + set -e + + copy_subunit_log + return $RESULT } +function copy_subunit_log { + LOGNAME=`cat .testrepository/next-stream` + LOGNAME=$(($LOGNAME - 1)) + LOGNAME=".testrepository/${LOGNAME}" + cp $LOGNAME subunit.log +} + function run_pep8 { echo "Running pep8 ..." srcfiles="cinderclient tests" @@ -98,7 +123,7 @@ function run_pep8 { ${wrapper} pep8 ${pep8_opts} ${srcfiles} } -NOSETESTS="nosetests $noseopts $noseargs" +TESTRTESTS="testr run --parallel $testropts" if [ $never_venv -eq 0 ] then @@ -136,13 +161,12 @@ if [ $just_pep8 -eq 1 ]; then exit fi +init_testr run_tests # NOTE(sirp): we only want to run pep8 when we're running the full-test suite, -# not when we're running tests individually. To handle this, we need to -# distinguish between options (noseopts), which begin with a '-', and -# arguments (noseargs). -if [ -z "$noseargs" ]; then +# not when we're running tests individually. +if [ -z "$testrargs" ]; then if [ $no_pep8 -eq 0 ]; then run_pep8 fi @@ -150,5 +174,6 @@ fi if [ $coverage -eq 1 ]; then echo "Generating coverage report in covhtml/" - ${wrapper} coverage html -d covhtml -i + ${wrapper} coverage combine + ${wrapper} coverage html --include='cinderclient/*' --omit='cinderclient/openstack/common/*' -d covhtml -i fi diff --git a/setup.cfg b/setup.cfg index 2d8f47ad6..6d6fe64a8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,11 +1,3 @@ -[nosetests] -cover-package = cinderclient -cover-html = true -cover-erase = true -cover-inclusive = true -verbosity=2 -detailed-errors=1 - [build_sphinx] all_files = 1 source-dir = doc/source diff --git a/setup.py b/setup.py index 50db70808..cb550fcf7 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,6 @@ setuptools.setup( tests_require=tests_require, setup_requires=['setuptools-git>=0.4'], dependency_links=depend_links, - test_suite="nose.collector", classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", diff --git a/tests/utils.py b/tests/utils.py index a2fd0347b..9da5f1a27 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,8 @@ -import testtools +import os +import fixtures import requests +import testtools class TestCase(testtools.TestCase): @@ -9,6 +11,17 @@ class TestCase(testtools.TestCase): 'verify': True, } + def setUp(self): + super(TestCase, self).setUp() + if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or + os.environ.get('OS_STDOUT_CAPTURE') == '1'): + stdout = self.useFixture(fixtures.StringStream('stdout')).stream + self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) + if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or + os.environ.get('OS_STDERR_CAPTURE') == '1'): + stderr = self.useFixture(fixtures.StringStream('stderr')).stream + self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) + class TestResponse(requests.Response): """ Class used to wrap requests.Response and provide some diff --git a/tests/v1/utils.py b/tests/v1/utils.py deleted file mode 100644 index f878a5e26..000000000 --- a/tests/v1/utils.py +++ /dev/null @@ -1,29 +0,0 @@ -from nose.tools import ok_ - - -def fail(msg): - raise AssertionError(msg) - - -def assert_in(thing, seq, msg=None): - msg = msg or "'%s' not found in %s" % (thing, seq) - ok_(thing in seq, msg) - - -def assert_not_in(thing, seq, msg=None): - msg = msg or "unexpected '%s' found in %s" % (thing, seq) - ok_(thing not in seq, msg) - - -def assert_has_keys(dict, required=[], optional=[]): - keys = dict.keys() - for k in required: - assert_in(k, keys, "required key %s missing from %s" % (k, dict)) - allowed_keys = set(required) | set(optional) - extra_keys = set(keys).difference(set(required + optional)) - if extra_keys: - fail("found unexpected keys: %s" % list(extra_keys)) - - -def assert_isinstance(thing, kls): - ok_(isinstance(thing, kls), "%s is not an instance of %s" % (thing, kls)) diff --git a/tools/test-requires b/tools/test-requires index e36dc9498..4dd52496c 100644 --- a/tools/test-requires +++ b/tools/test-requires @@ -1,11 +1,10 @@ distribute>=0.6.24 +coverage +discover fixtures mock -nose -nosehtmloutput -nosexcover -openstack.nose_plugin pep8==1.3.3 sphinx>=1.1.2 +testrepository>=0.0.13 testtools>=0.9.22 diff --git a/tox.ini b/tox.ini index c54b59615..34ca825c1 100644 --- a/tox.ini +++ b/tox.ini @@ -3,14 +3,13 @@ envlist = py26,py27,pep8 [testenv] setenv = VIRTUAL_ENV={envdir} - NOSE_WITH_OPENSTACK=1 - NOSE_OPENSTACK_COLOR=1 - NOSE_OPENSTACK_RED=0.05 - NOSE_OPENSTACK_YELLOW=0.025 - NOSE_OPENSTACK_SHOW_ELAPSED=1 + LANG=en_US.UTF-8 + LANGUAGE=en_US:en + LC_ALL=C + deps = -r{toxinidir}/tools/pip-requires -r{toxinidir}/tools/test-requires -commands = nosetests +commands = python setup.py testr --testr-args='{posargs}' [testenv:pep8] deps = pep8 @@ -20,23 +19,7 @@ commands = pep8 --repeat --show-source cinderclient setup.py commands = {posargs} [testenv:cover] -commands = nosetests --cover-erase --cover-package=cinderclient --with-xcoverage +commands = python setup.py testr --coverage --testr-args='{posargs}' [tox:jenkins] downloadcache = ~/cache/pip - -[testenv:jenkins26] -basepython = python2.6 -setenv = NOSE_WITH_XUNIT=1 - -[testenv:jenkins27] -basepython = python2.7 -setenv = NOSE_WITH_XUNIT=1 - -[testenv:jenkinscover] -setenv = NOSE_WITH_XUNIT=1 -commands = nosetests --cover-erase --cover-package=cinderclient --with-xcoverage - -[testenv:jenkinsvenv] -setenv = NOSE_WITH_XUNIT=1 -commands = {posargs}