avocado.plugins.test_lister: Make 'avocado list' to accept a list of paths

Make the subcommand 'avocado list' to accept a list of paths.
Avocado will scan the directories passed to it and find suitable
tests in them. One can use --verbose to see headers with extra
information and summary of the files scanned.
Signed-off-by: NLucas Meneghel Rodrigues <lmr@redhat.com>
上级 f95dc31b
......@@ -12,12 +12,14 @@
# Copyright: Red Hat Inc. 2013-2014
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
import os
import sys
from avocado import loader
from avocado import test
from avocado.core import data_dir
from avocado.core import output
from avocado.settings import settings
from avocado.utils import path
from avocado.core import exit_codes
from avocado.utils import astring
from avocado.plugins import plugin
......@@ -29,6 +31,9 @@ class TestLister(plugin.Plugin):
name = 'test_lister'
enabled = True
view = None
test_loader = loader.TestLoader()
term_support = output.TermSupport()
def configure(self, parser):
"""
......@@ -39,40 +44,123 @@ class TestLister(plugin.Plugin):
self.parser = parser.subcommands.add_parser(
'list',
help='List available test modules')
self.parser.add_argument('paths', type=str, default=[], nargs='*',
help="List of paths. If no paths provided, "
"avocado will list tests on the "
"configured test directory, "
"see 'avocado config --datadir'")
self.parser.add_argument('-V', '--verbose',
action='store_true', default=False,
help='Whether to show extra information '
'(headers and summary). Current: %('
'default)s')
super(TestLister, self).configure(self.parser)
def run(self, args):
def _run(self, args):
"""
List available test modules.
:param args: Command line args received from the list subparser.
"""
view = output.View(app_args=args, use_paginator=True)
base_test_dir = data_dir.get_test_dir()
test_files = os.listdir(base_test_dir)
test_dirs = []
blength = 0
for t in test_files:
inspector = path.PathInspector(path=t)
if inspector.is_python():
clength = len((t.split('.')[0]))
if clength > blength:
blength = clength
test_dirs.append((t.split('.')[0], os.path.join(base_test_dir, t)))
format_string = " %-" + str(blength) + "s %s"
view.notify(event="message", msg='Config files read (in order):')
for cfg_path in settings.config_paths:
view.notify(event="message", msg=' %s' % cfg_path)
if settings.config_paths_failed:
view.notify(event="minor", msg='')
view.notify(event="error", msg='Config files that failed to read:')
for cfg_path in settings.config_paths_failed:
view.notify(event="error", msg=' %s' % cfg_path)
view.notify(event="minor", msg='')
view.notify(event="message", msg='Tests dir: %s' % base_test_dir)
if len(test_dirs) > 0:
view.notify(event="minor", msg=format_string % ('Alias', 'Path'))
for test_dir in test_dirs:
view.notify(event="minor", msg=format_string % test_dir)
else:
view.notify(event="error", msg='No tests were found on current tests dir')
self.view = output.View(app_args=args)
paths = [data_dir.get_test_dir()]
if args.paths:
paths = args.paths
params_list = self.test_loader.discover_urls(paths)
for params in params_list:
params['omit_non_tests'] = False
test_suite = self.test_loader.discover(params_list)
error_msg_parts = self.test_loader.validate_ui(test_suite,
ignore_not_test=True,
ignore_access_denied=True,
ignore_broken_symlinks=True)
if error_msg_parts:
for error_msg in error_msg_parts:
self.view.notify(event='error', msg=error_msg)
sys.exit(exit_codes.AVOCADO_FAIL)
test_matrix = []
stats = {'simple': 0,
'instrumented': 0,
'buggy': 0,
'missing': 0,
'not_a_test': 0,
'broken_symlink': 0,
'access_denied': 0}
for cls, params in test_suite:
id_label = ''
type_label = cls.__name__
if 'params' in params:
id_label = params['params']['id']
else:
if 'name' in params:
id_label = params['name']
elif 'path' in params:
id_label = params['path']
if cls == test.SimpleTest:
stats['simple'] += 1
type_label = self.term_support.healthy_str('SIMPLE')
elif cls == test.BuggyTest:
stats['buggy'] += 1
type_label = self.term_support.fail_header_str('BUGGY')
elif cls == test.NotATest:
if not args.verbose:
continue
stats['not_a_test'] += 1
type_label = self.term_support.warn_header_str('NOT_A_TEST')
elif cls == test.MissingTest:
stats['missing'] += 1
type_label = self.term_support.fail_header_str('MISSING')
elif cls == loader.BrokenSymlink:
stats['broken_symlink'] += 1
type_label = self.term_support.fail_header_str('BROKEN_SYMLINK')
elif cls == loader.AccessDeniedPath:
stats['access_denied'] += 1
type_label = self.term_support.fail_header_str('ACCESS_DENIED')
else:
if issubclass(cls, test.Test):
stats['instrumented'] += 1
type_label = self.term_support.healthy_str('INSTRUMENTED')
test_matrix.append((type_label, id_label))
header = None
if args.verbose:
header = (self.term_support.header_str('Type'),
self.term_support.header_str('file'))
for line in astring.tabular_output(test_matrix,
header=header).splitlines():
self.view.notify(event='minor', msg="%s" % line)
if args.verbose:
self.view.notify(event='minor', msg='')
self.view.notify(event='message', msg=("SIMPLE: %s" %
stats['simple']))
self.view.notify(event='message', msg=("INSTRUMENTED: %s" %
stats['instrumented']))
self.view.notify(event='message', msg=("BUGGY: %s" %
stats['buggy']))
self.view.notify(event='message', msg=("MISSING: %s" %
stats['missing']))
self.view.notify(event='message', msg=("NOT_A_TEST: %s" %
stats['not_a_test']))
self.view.notify(event='message', msg=("ACCESS_DENIED: %s" %
stats['access_denied']))
self.view.notify(event='message', msg=("BROKEN_SYMLINK: %s" %
stats['broken_symlink']))
def run(self, args):
try:
self._run(args)
except KeyboardInterrupt:
msg = ('Command interrupted by '
'user...')
if self.view is not None:
self.view.notify(event='error', msg=msg)
else:
sys.stderr.write(msg)
sys.exit(exit_codes.AVOCADO_FAIL)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册