diff options
| author | Damian Johnson <atagar@torproject.org> | 2015-03-03 09:30:15 -0800 |
|---|---|---|
| committer | Damian Johnson <atagar@torproject.org> | 2015-03-03 09:31:43 -0800 |
| commit | 55bfd9c10ff8d8c1dc418a06ab43f05a8d581d41 (patch) | |
| tree | 9a462518c399d3d989861861bab1d216d82991bf | |
| parent | b8411f0dafab408f42f2b00ab6622fa64c6d120d (diff) | |
| parent | 230a8aa131dd51234fb2b8df4fae463cef5cce9b (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-x | run_tests.py | 27 | ||||
| -rw-r--r-- | test/util.py | 45 |
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(): |
