summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/run-tests-for-diff.sh25
-rwxr-xr-xtools/run-tests.py107
2 files changed, 132 insertions, 0 deletions
diff --git a/tools/run-tests-for-diff.sh b/tools/run-tests-for-diff.sh
new file mode 100755
index 0000000000..4dc4897964
--- /dev/null
+++ b/tools/run-tests-for-diff.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+here=`dirname $0`
+
+if test -z "$1"; then
+ set -- HEAD
+elif test "x$1" = "x-HEAD"; then
+ # Simulate behaviour from flake8wrap.sh
+ shift
+ set -- HEAD~1
+fi
+
+git diff --name-only "$@" | $here/run-tests.py
diff --git a/tools/run-tests.py b/tools/run-tests.py
new file mode 100755
index 0000000000..34bc960b5a
--- /dev/null
+++ b/tools/run-tests.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 SUSE
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+
+
+# Filters list of files on STDIN for test files (can be more than one
+# per line), and runs any which can be run in the current tox
+# virtualenv. Automatically detects which stestr options to use,
+# e.g. --test-path=./nova/tests/functional if we're in a virtualenv
+# for functional tests.
+
+import os
+import re
+import subprocess
+import sys
+
+
+def get_tox_env():
+ if os.getenv('VIRTUAL_ENV', '').find('/.tox/') == -1:
+ sys.stderr.write(
+ """%s should be run within a tox virtualenv.
+Please first activate the tox virtualenv you want to use, e.g.
+
+ source .tox/py36/bin/activate
+""" %
+ os.path.realpath(__file__))
+ sys.exit(1)
+
+ return os.getenv('VIRTUAL_ENV')
+
+
+def tox_env_is_functional():
+ return get_tox_env().find('.tox/functional') != -1
+
+
+def get_stestr_opts():
+ opts = sys.argv[1:]
+
+ if tox_env_is_functional():
+ opts = ['--test-path=./nova/tests/functional'] + opts
+
+ return opts
+
+
+def get_test_files():
+ test_files = []
+ functional = tox_env_is_functional()
+
+ for line in sys.stdin:
+ files = line.strip().split()
+ for f in files:
+ if not re.match(r'^nova/tests/.*\.py$', f):
+ # In the future we could get really clever and
+ # map source files to their corresponding tests,
+ # as is typically done by Guardfile in projects
+ # which use Guard: https://guardgem.org
+ continue
+
+ functional_re = r'^nova/tests/functional/'
+ if functional:
+ if not re.match(functional_re, f):
+ continue
+ else:
+ if re.match(functional_re, f):
+ continue
+
+ test_files.append(f[:-3].replace('/', '.'))
+
+ return test_files
+
+
+def main():
+ stestr_opts = get_stestr_opts()
+ test_files = get_test_files()
+
+ if not test_files:
+ print("No test files found to run")
+ sys.exit(0)
+
+ if len(test_files) == 1:
+ # If there's only one module to run (or test therein), we can
+ # skip discovery which will chop quite a few seconds off the
+ # runtime.
+ stestr_opts = ['-n'] + stestr_opts
+
+ cmd = ['stestr', 'run', *stestr_opts] + test_files
+ print(' '.join(cmd))
+ try:
+ subprocess.check_call(cmd)
+ except subprocess.CalledProcessError as e:
+ print("\nstestr returned non-zero exit code %d\n" % e.returncode)
+
+
+if __name__ == '__main__':
+ main()