Browse Source

Migrate from nose to testr.

Run tests with testr for parallel execution.

Part of blueprint grizzly-testtools.

Change-Id: I38e8a2df12678002e19264a53bad26e80265c6e4
Monty Taylor 6 years ago
parent
commit
7b2097e706
9 changed files with 84 additions and 58 deletions
  1. 2
    0
      .gitignore
  2. 4
    0
      .testr.conf
  3. 8
    0
      HACKING
  4. 45
    15
      run_tests.sh
  5. 0
    8
      setup.cfg
  6. 0
    1
      setup.py
  7. 14
    0
      tests/utils.py
  8. 5
    7
      tools/test-requires
  9. 6
    27
      tox.ini

+ 2
- 0
.gitignore View File

@@ -1,5 +1,7 @@
1 1
 .coverage
2 2
 .venv
3
+.testrepository
4
+subunit.log
3 5
 .tox
4 6
 *,cover
5 7
 cover

+ 4
- 0
.testr.conf View File

@@ -0,0 +1,4 @@
1
+[DEFAULT]
2
+test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ./tests $LISTOPT $IDOPTION
3
+test_id_option=--load-list $IDFILE
4
+test_list_option=--list

+ 8
- 0
HACKING View File

@@ -113,3 +113,11 @@ Text encoding
113 113
     returntext = do_some_magic_with(mytext)
114 114
     returnstring = returntext.encode('utf-8')
115 115
     outfile.write(returnstring)
116
+
117
+Running Tests
118
+-------------
119
+The testing system is based on a combination of tox and testr. If you just
120
+want to run the whole suite, run `tox` and all will be fine. However, if
121
+you'd like to dig in a bit more, you might want to learn some things about
122
+testr itself. A basic walkthrough for OpenStack can be found at
123
+http://wiki.openstack.org/testr

+ 45
- 15
run_tests.sh View File

@@ -33,8 +33,8 @@ function process_option {
33 33
     -p|--pep8) just_pep8=1;;
34 34
     -P|--no-pep8) no_pep8=1;;
35 35
     -c|--coverage) coverage=1;;
36
-    -*) noseopts="$noseopts $1";;
37
-    *) noseargs="$noseargs $1"
36
+    -*) testropts="$testropts $1";;
37
+    *) testrargs="$testrargs $1"
38 38
   esac
39 39
 }
40 40
 
@@ -45,34 +45,62 @@ never_venv=0
45 45
 force=0
46 46
 no_site_packages=0
47 47
 installvenvopts=
48
-noseargs=
49
-noseopts=
48
+testrargs=
49
+testropts=
50 50
 wrapper=""
51 51
 just_pep8=0
52 52
 no_pep8=0
53 53
 coverage=0
54 54
 
55
+LANG=en_US.UTF-8
56
+LANGUAGE=en_US:en
57
+LC_ALL=C
58
+
55 59
 for arg in "$@"; do
56 60
   process_option $arg
57 61
 done
58 62
 
59
-# If enabled, tell nose to collect coverage data
60
-if [ $coverage -eq 1 ]; then
61
-    noseopts="$noseopts --with-coverage --cover-package=novaclient"
62
-fi
63
-
64 63
 if [ $no_site_packages -eq 1 ]; then
65 64
   installvenvopts="--no-site-packages"
66 65
 fi
67 66
 
67
+function init_testr {
68
+  if [ ! -d .testrepository ]; then
69
+    ${wrapper} testr init
70
+  fi
71
+}
72
+
68 73
 function run_tests {
74
+  # Cleanup *pyc
75
+  ${wrapper} find . -type f -name "*.pyc" -delete
76
+
77
+  if [ $coverage -eq 1 ]; then
78
+    # Do not test test_coverage_ext when gathering coverage.
79
+    if [ "x$testrargs" = "x" ]; then
80
+      testrargs = "^(?!.*test_coverage_ext).*$"
81
+    fi
82
+    export PYTHON="${wrapper} coverage run --source novaclient --parallel-mode"
83
+  fi
69 84
   # Just run the test suites in current environment
70
-  ${wrapper} $NOSETESTS
71
-  # If we get some short import error right away, print the error log directly
85
+  set +e
86
+  TESTRTESTS="$TESTRTESTS $testrargs"
87
+  echo "Running \`${wrapper} $TESTRTESTS\`"
88
+  ${wrapper} $TESTRTESTS
72 89
   RESULT=$?
90
+  set -e
91
+
92
+  copy_subunit_log
93
+
73 94
   return $RESULT
74 95
 }
75 96
 
97
+function copy_subunit_log {
98
+  LOGNAME=`cat .testrepository/next-stream`
99
+  LOGNAME=$(($LOGNAME - 1))
100
+  LOGNAME=".testrepository/${LOGNAME}"
101
+  cp $LOGNAME subunit.log
102
+}
103
+
76 104
 function run_pep8 {
77 105
   echo "Running pep8 ..."
78 106
   srcfiles="novaclient tests"
@@ -96,7 +124,7 @@ function run_pep8 {
96 124
   ${wrapper} pep8 ${pep8_opts} ${srcfiles}
97 125
 }
98 126
 
99
-NOSETESTS="nosetests $noseopts $noseargs"
127
+TESTRTESTS="testr run --parallel $testropts"
100 128
 
101 129
 if [ $never_venv -eq 0 ]
102 130
 then
@@ -134,13 +162,14 @@ if [ $just_pep8 -eq 1 ]; then
134 162
     exit
135 163
 fi
136 164
 
165
+init_testr
137 166
 run_tests
138 167
 
139 168
 # NOTE(sirp): we only want to run pep8 when we're running the full-test suite,
140 169
 # not when we're running tests individually. To handle this, we need to
141 170
 # distinguish between options (noseopts), which begin with a '-', and
142
-# arguments (noseargs).
143
-if [ -z "$noseargs" ]; then
171
+# arguments (testrargs).
172
+if [ -z "$testrargs" ]; then
144 173
   if [ $no_pep8 -eq 0 ]; then
145 174
     run_pep8
146 175
   fi
@@ -148,5 +177,6 @@ fi
148 177
 
149 178
 if [ $coverage -eq 1 ]; then
150 179
     echo "Generating coverage report in covhtml/"
151
-    ${wrapper} coverage html -d covhtml -i
180
+    ${wrapper} cverage combine
181
+    ${wrapper} coverage html --include='novaclient/*' --omit='novaclient/openstack/common/*' -d covhtml -i
152 182
 fi

+ 0
- 8
setup.cfg View File

@@ -1,11 +1,3 @@
1
-[nosetests]
2
-cover-package = novaclient
3
-cover-html = true
4
-cover-erase = true
5
-cover-inclusive = true
6
-verbosity=2
7
-detailed-errors=1
8
-
9 1
 [build_sphinx]
10 2
 source-dir = doc/source
11 3
 build-dir = doc/build

+ 0
- 1
setup.py View File

@@ -34,7 +34,6 @@ setuptools.setup(
34 34
     url="https://github.com/openstack/python-novaclient",
35 35
     packages=setuptools.find_packages(exclude=['tests', 'tests.*']),
36 36
     install_requires=setup.parse_requirements(),
37
-    test_suite="nose.collector",
38 37
     cmdclass=setup.get_cmdclass(),
39 38
     classifiers=[
40 39
         "Development Status :: 5 - Production/Stable",

+ 14
- 0
tests/utils.py View File

@@ -1,3 +1,6 @@
1
+import os
2
+
3
+import fixtures
1 4
 import requests
2 5
 import testtools
3 6
 
@@ -8,6 +11,17 @@ class TestCase(testtools.TestCase):
8 11
         'verify': True,
9 12
     }
10 13
 
14
+    def setUp(self):
15
+        super(TestCase, self).setUp()
16
+        if (os.environ.get('OS_STDOUT_NOCAPTURE') == 'True' and
17
+                os.environ.get('OS_STDOUT_NOCAPTURE') == '1'):
18
+            stdout = self.useFixture(fixtures.StringStream('stdout')).stream
19
+            self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
20
+        if (os.environ.get('OS_STDERR_NOCAPTURE') == 'True' and
21
+                os.environ.get('OS_STDERR_NOCAPTURE') == '1'):
22
+            stderr = self.useFixture(fixtures.StringStream('stderr')).stream
23
+            self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
24
+
11 25
 
12 26
 class TestResponse(requests.Response):
13 27
     """

+ 5
- 7
tools/test-requires View File

@@ -1,12 +1,10 @@
1 1
 distribute>=0.6.24
2 2
 
3
-fixtures
3
+coverage
4
+discover
5
+fixtures>=0.3.12
4 6
 mock
5
-nose
6
-nose-exclude
7
-nosexcover
8
-openstack.nose_plugin
9
-nosehtmloutput
10 7
 pep8==1.1
11 8
 sphinx>=1.1.2
12
-testtools
9
+testrepository>=0.0.13
10
+testtools>=0.9.26

+ 6
- 27
tox.ini View File

@@ -3,14 +3,13 @@ envlist = py26,py27,pep8
3 3
 
4 4
 [testenv]
5 5
 setenv = VIRTUAL_ENV={envdir}
6
-         NOSE_WITH_OPENSTACK=1
7
-         NOSE_OPENSTACK_COLOR=1
8
-         NOSE_OPENSTACK_RED=0.05
9
-         NOSE_OPENSTACK_YELLOW=0.025
10
-         NOSE_OPENSTACK_SHOW_ELAPSED=1
6
+         LANG=en_US.UTF-8
7
+         LANGUAGE=en_US:en
8
+         LC_ALL=C
9
+
11 10
 deps = -r{toxinidir}/tools/pip-requires
12 11
        -r{toxinidir}/tools/test-requires
13
-commands = nosetests
12
+commands = python setup.py testr --testr-args='{posargs}'
14 13
 
15 14
 [testenv:pep8]
16 15
 deps = pep8==1.1
@@ -20,27 +19,7 @@ commands = pep8 --repeat --show-source novaclient setup.py
20 19
 commands = {posargs}
21 20
 
22 21
 [testenv:cover]
23
-commands = nosetests --cover-erase --cover-package=novaclient --with-xcoverage
22
+commands = python setup.py testr --coverage --testr-args='{posargs}'
24 23
 
25 24
 [tox:jenkins]
26 25
 downloadcache = ~/cache/pip
27
-
28
-[testenv:jenkins26]
29
-basepython = python2.6
30
-setenv = NOSE_WITH_XUNIT=1
31
-deps = file://{toxinidir}/.cache.bundle
32
-
33
-[testenv:jenkins27]
34
-basepython = python2.7
35
-setenv = NOSE_WITH_XUNIT=1
36
-deps = file://{toxinidir}/.cache.bundle
37
-
38
-[testenv:jenkinscover]
39
-deps = file://{toxinidir}/.cache.bundle
40
-setenv = NOSE_WITH_XUNIT=1
41
-commands = nosetests --cover-erase --cover-package=novaclient --with-xcoverage
42
-
43
-[testenv:jenkinsvenv]
44
-deps = file://{toxinidir}/.cache.bundle
45
-setenv = NOSE_WITH_XUNIT=1
46
-commands = {posargs}

Loading…
Cancel
Save