summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamian Johnson <atagar@torproject.org>2015-03-03 09:30:15 -0800
committerDamian Johnson <atagar@torproject.org>2015-03-03 09:31:43 -0800
commit55bfd9c10ff8d8c1dc418a06ab43f05a8d581d41 (patch)
tree9a462518c399d3d989861861bab1d216d82991bf
parentb8411f0dafab408f42f2b00ab6622fa64c6d120d (diff)
parent230a8aa131dd51234fb2b8df4fae463cef5cce9b (diff)
Allow just a single test to be run
Our run_tests.py's '--test' argument can now be giving a single test to just run that. For example... ./run_tests.py --unit --test test.unit.util.conf.test_parse_enum_csv -v The 'test.unit.' or 'test.integ.' prefix is optional. Initial patch thanks to civ! https://trac.torproject.org/projects/tor/ticket/14944
-rwxr-xr-xrun_tests.py27
-rw-r--r--test/util.py45
2 files changed, 41 insertions, 31 deletions
diff --git a/run_tests.py b/run_tests.py
index bfdd101f..497a3fc4 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -443,21 +443,32 @@ def _run_test(args, test_class, output_filters, logging_buffer):
start_time = time.time()
if args.verbose:
- test.output.print_divider(test_class.__module__)
+ test.output.print_divider(test_class)
else:
- label = test_class.__module__
-
- if label.startswith('test.unit.'):
- label = label[10:]
- elif label.startswith('test.integ.'):
- label = label[11:]
+ # Test classes look like...
+ #
+ # test.unit.util.conf.TestConf.test_parse_enum_csv
+ #
+ # We want to strip the 'test.unit.' or 'test.integ.' prefix since it's
+ # redundant. We also want to drop the test class name. The individual test
+ # name at the end it optional (only present if we used the '--test'
+ # argument).
+
+ label_comp = test_class.split('.')[2:]
+ del label_comp[-1 if label_comp[-1][0].isupper() else -2]
+ label = '.'.join(label_comp)
label = ' %s...' % label
label = '%-54s' % label
println(label, STATUS, NO_NL)
- suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
+ try:
+ suite = unittest.TestLoader().loadTestsFromName(test_class)
+ except:
+ # should only come up if user provided '--test' for something that doesn't exist
+ println(" no such test", ERROR)
+ return None
test_results = StringIO()
run_result = unittest.TextTestRunner(test_results, verbosity=2).run(suite)
diff --git a/test/util.py b/test/util.py
index b6bca298..55243a3d 100644
--- a/test/util.py
+++ b/test/util.py
@@ -75,51 +75,50 @@ Target = stem.util.enum.UppercaseEnum(
STEM_BASE = os.path.sep.join(__file__.split(os.path.sep)[:-2])
-def get_unit_tests(module_substring = None):
+def get_unit_tests(module_prefix = None):
"""
Provides the classes for our unit tests.
- :param str module_substring: only provide the test if the module includes this substring
+ :param str module_prefix: only provide the test if the module starts with
+ this substring
:returns: an **iterator** for our unit tests
"""
- return _get_tests(CONFIG['test.unit_tests'].splitlines(), module_substring)
+ if module_prefix and not module_prefix.startswith('test.unit.'):
+ module_prefix = 'test.unit.' + module_prefix
+ return _get_tests(CONFIG['test.unit_tests'].splitlines(), module_prefix)
-def get_integ_tests(module_substring = None):
+
+def get_integ_tests(module_prefix = None):
"""
Provides the classes for our integration tests.
- :param str module_substring: only provide the test if the module includes this substring
+ :param str module_prefix: only provide the test if the module starts with
+ this substring
:returns: an **iterator** for our integration tests
"""
- return _get_tests(CONFIG['test.integ_tests'].splitlines(), module_substring)
+ if module_prefix and not module_prefix.startswith('test.integ.'):
+ module_prefix = 'test.integ.' + module_prefix
+
+ return _get_tests(CONFIG['test.integ_tests'].splitlines(), module_prefix)
-def _get_tests(modules, module_substring):
+def _get_tests(modules, module_prefix):
for import_name in modules:
if import_name:
- if module_substring and module_substring not in import_name:
- continue
-
- # Dynamically imports test modules. The __import__() call has a couple
- # quirks that make this a little clunky...
- #
- # * it only accepts modules, not the actual class we want to import
- #
- # * it returns the top level module, so we need to transverse into it
- # for the test class
-
- module_name = '.'.join(import_name.split('.')[:-1])
- module = __import__(module_name)
+ module, module_name = import_name.rsplit('.', 1) # example: util.conf.TestConf
- for subcomponent in import_name.split('.')[1:]:
- module = getattr(module, subcomponent)
+ if not module_prefix or module.startswith(module_prefix):
+ yield import_name
+ elif module_prefix.startswith(module):
+ # single test for this module
- yield module
+ test = module_prefix.rsplit('.', 1)[1]
+ yield '%s.%s' % (import_name, test)
def get_help_message():