提交 83a50b5f 编写于 作者: L Lukáš Doktor 提交者: Cleber Rosa

avocado: Change logging initialization

This patch changes the way logging is initialized in avocado app:

1. stdout/stderr/logging is replaced with in-memory handlers
2. when arg parsing is done, logging is reconfigured accordingly to
   setting and re-logs stored messages (when streams are enabled)
3. when job starts and "test" stream is enabled, "" and "avocado.test"
   streams are enabled
4. when job finishes and "test" stream enabled the additional outputs,
   the additional outputs are disabled again.

The 3 and 4 is necessarily as the "" logger contains all logs including
avocado initialization (stevedore, PIL, ...). This way the "test" stream
still outputs everything, but only during the job-execution and not
during avocado initialization and cleanup. (one can use "early" log to
see those).

Last but not least it keeps "avocado.app" output in stdout (and stderr),
but it moves all other outputs to stderr instead. This is IMO better
handling as one can distinguish between debug and "additional" output.
Signed-off-by: NLukáš Doktor <ldoktor@redhat.com>
上级 58cf6f83
...@@ -19,7 +19,7 @@ The core Avocado application. ...@@ -19,7 +19,7 @@ The core Avocado application.
import os import os
import signal import signal
from .log import configure as configure_log from . import log
from .parser import Parser from .parser import Parser
from .output import View from .output import View
from .settings import settings from .settings import settings
...@@ -38,20 +38,29 @@ class AvocadoApp(object): ...@@ -38,20 +38,29 @@ class AvocadoApp(object):
# Catch all libc runtime errors to STDERR # Catch all libc runtime errors to STDERR
os.environ['LIBC_FATAL_STDERR_'] = '1' os.environ['LIBC_FATAL_STDERR_'] = '1'
configure_log()
signal.signal(signal.SIGTSTP, signal.SIG_IGN) # ignore ctrl+z signal.signal(signal.SIGTSTP, signal.SIG_IGN) # ignore ctrl+z
self.parser = Parser() self.parser = Parser()
self.cli_dispatcher = CLIDispatcher() log.early_start()
self.cli_cmd_dispatcher = CLICmdDispatcher() initialized = False
self._print_plugin_failures() try:
self.parser.start() self.cli_dispatcher = CLIDispatcher()
if self.cli_cmd_dispatcher.extensions: self.cli_cmd_dispatcher = CLICmdDispatcher()
self.cli_cmd_dispatcher.map_method('configure', self.parser) self._print_plugin_failures()
if self.cli_dispatcher.extensions: self.parser.start()
self.cli_dispatcher.map_method('configure', self.parser) if self.cli_cmd_dispatcher.extensions:
self.parser.finish() self.cli_cmd_dispatcher.map_method('configure', self.parser)
if self.cli_dispatcher.extensions: if self.cli_dispatcher.extensions:
self.cli_dispatcher.map_method('run', self.parser.args) self.cli_dispatcher.map_method('configure', self.parser)
self.parser.finish()
if self.cli_dispatcher.extensions:
self.cli_dispatcher.map_method('run', self.parser.args)
initialized = True
finally:
if (not initialized and
getattr(self.parser.args, "silent", False) is False):
log.enable_stderr()
self.parser.args.log = ["app", "test"]
log.reconfigure(self.parser.args)
def _print_plugin_failures(self): def _print_plugin_failures(self):
failures = (self.cli_dispatcher.load_failures + failures = (self.cli_dispatcher.load_failures +
......
...@@ -37,6 +37,7 @@ from . import exit_codes ...@@ -37,6 +37,7 @@ from . import exit_codes
from . import exceptions from . import exceptions
from . import job_id from . import job_id
from . import output from . import output
from . import log
from . import multiplexer from . import multiplexer
from . import tree from . import tree
from . import test from . import test
...@@ -108,20 +109,6 @@ class Job(object): ...@@ -108,20 +109,6 @@ class Job(object):
self.loglevel = mapping[raw_log_level] self.loglevel = mapping[raw_log_level]
else: else:
self.loglevel = logging.DEBUG self.loglevel = logging.DEBUG
self.show_job_log = getattr(self.args, 'show_job_log', False)
self.silent = getattr(self.args, 'silent', False)
if self.standalone:
self.show_job_log = True
if self.args is not None:
setattr(self.args, 'show_job_log', True)
if self.show_job_log:
if not self.silent:
output.add_log_handler(_TEST_LOGGER.name, level=logging.DEBUG)
output.add_log_handler('', level=logging.DEBUG)
_TEST_LOGGER.setLevel(self.loglevel)
_TEST_LOGGER.propagate = False
self.test_dir = data_dir.get_test_dir() self.test_dir = data_dir.get_test_dir()
self.test_index = 1 self.test_index = 1
...@@ -533,6 +520,8 @@ class TestProgram(object): ...@@ -533,6 +520,8 @@ class TestProgram(object):
os.environ['AVOCADO_STANDALONE_IN_MAIN'] = 'True' os.environ['AVOCADO_STANDALONE_IN_MAIN'] = 'True'
self.progName = os.path.basename(sys.argv[0]) self.progName = os.path.basename(sys.argv[0])
output.add_log_handler("", output.ProgressStreamHandler,
fmt="%(message)s")
self.parseArgs(sys.argv[1:]) self.parseArgs(sys.argv[1:])
self.args.url = [sys.argv[0]] self.args.url = [sys.argv[0]]
self.runTests() self.runTests()
...@@ -548,6 +537,8 @@ class TestProgram(object): ...@@ -548,6 +537,8 @@ class TestProgram(object):
def runTests(self): def runTests(self):
self.args.standalone = True self.args.standalone = True
self.args.log = ["test"]
log.reconfigure(self.args)
self.job = Job(self.args) self.job = Job(self.args)
exit_status = self.job.run() exit_status = self.job.run()
if self.args.remove_test_results is True: if self.args.remove_test_results is True:
......
...@@ -13,125 +13,126 @@ ...@@ -13,125 +13,126 @@
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com> # Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
__all__ = ['configure', 'DEFAULT_LOGGING'] from StringIO import StringIO
import logging import logging
import os import os
import sys
from . import output
__all__ = ["early_start", "enable_stderr", "reconfigure"]
if hasattr(logging, 'NullHandler'): if hasattr(logging, 'NullHandler'):
NULL_HANDLER = 'logging.NullHandler' NULL_HANDLER = logging.NullHandler
else: else:
NULL_HANDLER = 'logutils.NullHandler' import logutils
NULL_HANDLER = logutils.NullHandler
DEFAULT_LOGGING = {
'version': 1,
'disable_existing_loggers': False, STDOUT = sys.stdout
'formatters': { STDERR = sys.stderr
'brief': {
'format': '%(message)s',
}, def early_start():
}, """
'filters': { Replace all outputs with in-memory handlers
'error': { """
'()': 'avocado.core.output.FilterError', if os.environ.get('AVOCADO_LOG_DEBUG'):
}, output.add_log_handler("avocado.app.debug", logging.StreamHandler,
'info': { STDERR, logging.DEBUG)
'()': 'avocado.core.output.FilterInfo', if os.environ.get('AVOCADO_LOG_EARLY'):
}, output.add_log_handler("", logging.StreamHandler, STDERR,
}, logging.DEBUG)
'handlers': { output.add_log_handler("avocado.test", logging.StreamHandler, STDERR,
'null': { logging.DEBUG)
'level': 'INFO',
'class': NULL_HANDLER,
},
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'brief',
},
'app': {
'level': 'INFO',
'class': 'avocado.core.output.ProgressStreamHandler',
'formatter': 'brief',
'filters': ['info'],
'stream': 'ext://sys.stdout',
},
'error': {
'level': 'ERROR',
'class': 'logging.StreamHandler',
'formatter': 'brief',
'filters': ['error'],
},
'debug': {
'level': 'DEBUG',
'class': 'avocado.core.output.ProgressStreamHandler',
'formatter': 'brief',
'stream': 'ext://sys.stdout',
},
},
'loggers': {
'': {
'handlers': ['null']
},
'avocado': {
'handlers': ['console'],
},
'avocado.app': {
'handlers': ['app', 'error'],
'level': 'INFO',
'propagate': False,
},
'avocado.app.tracebacks': {
# Set DEBUG=true to enable debugs
'handlers': ['error' if os.environ.get('DEBUG') else 'null'],
'level': 'ERROR',
'propagate': False,
},
'avocado.test': {
'handlers': ['null'],
'level': 'DEBUG',
'propagate': False,
},
'avocado.fabric': {
'handlers': ['null'],
'level': 'DEBUG',
'propagate': False,
},
'paramiko': {
'handlers': ['null'],
'level': 'DEBUG',
'propagate': False,
},
'avocado.test.stdout': {
'handlers': ['null'],
'level': 'DEBUG',
'propagate': False,
},
'avocado.test.stderr': {
'handlers': ['null'],
'level': 'DEBUG',
'propagate': False,
},
'avocado.sysinfo': {
'handlers': ['error'],
'level': 'DEBUG',
'propagate': False,
},
'avocado.debug': {
'handlers': ['debug'],
'level': 'DEBUG',
'propagate': False,
},
}
}
def configure(logging_config=DEFAULT_LOGGING):
from logging import config
if not hasattr(config, 'dictConfig'):
from logutils import dictconfig
cfg_func = dictconfig.dictConfig
else: else:
cfg_func = config.dictConfig sys.stdout = StringIO()
cfg_func(logging_config) sys.stderr = sys.stdout
output.add_log_handler("", output.MemStreamHandler, None,
logging.DEBUG)
logging.root.level = logging.DEBUG
def enable_stderr():
"""
Enable direct stdout/stderr (useful for handling errors)
"""
if hasattr(sys.stdout, 'getvalue'):
STDERR.write(sys.stdout.getvalue())
sys.stdout = STDOUT
sys.stderr = STDERR
def reconfigure(args):
"""
Adjust logging handlers accordingly to app args and re-log messages.
"""
# Reconfigure stream loggers
enabled = getattr(args, "log", ["app", "early", "debug"])
if os.environ.get("AVOCADO_LOG_EARLY") and "early" not in enabled:
args.log.append("early")
enabled.append("early")
if os.environ.get("AVOCADO_LOG_DEBUG") and "debug" not in enabled:
args.log.append("debug")
enabled.append("debug")
if getattr(args, "show_job_log", False):
args.log = ["test"]
enabled = ["test"]
if getattr(args, "silent", False):
del args.log[:]
del enabled[:]
if "app" in enabled:
app_logger = logging.getLogger("avocado.app")
app_handler = output.ProgressStreamHandler()
app_handler.setFormatter(logging.Formatter("%(message)s"))
app_handler.addFilter(output.FilterInfo())
app_handler.stream = STDOUT
app_logger.addHandler(app_handler)
app_logger.propagate = False
app_logger.level = logging.INFO
app_err_handler = output.logging.StreamHandler()
app_err_handler.setFormatter(logging.Formatter("%(message)s"))
app_err_handler.addFilter(output.FilterError())
app_err_handler.stream = STDERR
app_logger.addHandler(app_err_handler)
app_logger.propagate = False
else:
output.disable_log_handler("avocado.app")
if not os.environ.get("AVOCADO_LOG_EARLY"):
logging.getLogger("avocado.test.stdout").propagate = False
logging.getLogger("avocado.test.stderr").propagate = False
if "early" in enabled:
enable_stderr()
output.add_log_handler("", logging.StreamHandler, STDERR,
logging.DEBUG)
output.add_log_handler("avocado.test", logging.StreamHandler,
STDERR, logging.DEBUG)
else:
# TODO: When stdout/stderr is not used by avocado we should move
# this to output.start_job_logging
sys.stdout = STDOUT
sys.stderr = STDERR
output.disable_log_handler("")
output.disable_log_handler("avocado.test")
if "remote" in enabled:
output.add_log_handler("avocado.fabric", stream=STDERR)
output.add_log_handler("paramiko", stream=STDERR)
else:
output.disable_log_handler("avocado.fabric")
output.disable_log_handler("paramiko")
if not os.environ.get('AVOCADO_LOG_DEBUG'): # Not already enabled by env
if "debug" in enabled:
output.add_log_handler("avocado.app.debug", stream=STDERR)
else:
output.disable_log_handler("avocado.app.debug")
# Remove the in-memory handlers
for handler in logging.root.handlers:
if isinstance(handler, output.MemStreamHandler):
logging.root.handlers.remove(handler)
# Log early_messages
for record in output.MemStreamHandler.log:
logging.getLogger(record.name).handle(record)
...@@ -22,6 +22,12 @@ import sys ...@@ -22,6 +22,12 @@ import sys
from .settings import settings from .settings import settings
from ..utils import path as utils_path from ..utils import path as utils_path
if hasattr(logging, 'NullHandler'):
NULL_HANDLER = logging.NullHandler
else:
import logutils
NULL_HANDLER = logutils.NullHandler
class FilterError(logging.Filter): class FilterError(logging.Filter):
...@@ -58,6 +64,24 @@ class ProgressStreamHandler(logging.StreamHandler): ...@@ -58,6 +64,24 @@ class ProgressStreamHandler(logging.StreamHandler):
self.handleError(record) self.handleError(record)
class MemStreamHandler(logging.StreamHandler):
"""
Handler that stores all records in self.log (shared in all instances)
"""
log = []
def emit(self, record):
self.log.append(record)
def flush(self):
"""
This is in-mem object, it does not require flushing
"""
pass
class PagerNotFoundError(Exception): class PagerNotFoundError(Exception):
pass pass
...@@ -134,6 +158,15 @@ def add_log_handler(logger, klass=logging.StreamHandler, stream=sys.stdout, ...@@ -134,6 +158,15 @@ def add_log_handler(logger, klass=logging.StreamHandler, stream=sys.stdout,
return handler return handler
def disable_log_handler(logger):
logger = logging.getLogger(logger)
# Handlers might be reused elsewhere, can't delete them
while logger.handlers:
logger.handlers.pop()
logger.handlers.append(NULL_HANDLER())
logger.propagate = False
class TermSupport(object): class TermSupport(object):
COLOR_BLUE = '\033[94m' COLOR_BLUE = '\033[94m'
...@@ -412,6 +445,8 @@ class View(object): ...@@ -412,6 +445,8 @@ class View(object):
self.paginator = None self.paginator = None
self.throbber = Throbber() self.throbber = Throbber()
self.tests_info = {} self.tests_info = {}
self.file_handler = None
self.stream_handler = None
def cleanup(self): def cleanup(self):
if self.use_paginator: if self.use_paginator:
...@@ -478,21 +513,14 @@ class View(object): ...@@ -478,21 +513,14 @@ class View(object):
:param msg: Message to write :param msg: Message to write
:type msg: string :type msg: string
""" """
silent = False enabled = getattr(self.app_args, "log", [])
show_job_log = False if "app" in enabled and self.use_paginator and level < logging.ERROR:
if self.app_args is not None: if not skip_newline:
if hasattr(self.app_args, 'silent'): msg += '\n'
silent = self.app_args.silent self.paginator.write(msg)
if hasattr(self.app_args, 'show_job_log'): else:
show_job_log = self.app_args.show_job_log extra = {'skip_newline': skip_newline}
if not (silent or show_job_log): self.console_log.log(level=level, msg=msg, extra=extra)
if self.use_paginator and (level < logging.ERROR):
if not skip_newline:
msg += '\n'
self.paginator.write(msg)
else:
extra = {'skip_newline': skip_newline}
self.console_log.log(level=level, msg=msg, extra=extra)
def _log_ui_info(self, msg, skip_newline=False): def _log_ui_info(self, msg, skip_newline=False):
""" """
...@@ -568,6 +596,7 @@ class View(object): ...@@ -568,6 +596,7 @@ class View(object):
""" """
self.job_unique_id = unique_id self.job_unique_id = unique_id
self.debuglog = logfile self.debuglog = logfile
# File loggers
self.file_handler = logging.FileHandler(filename=logfile) self.file_handler = logging.FileHandler(filename=logfile)
self.file_handler.setLevel(loglevel) self.file_handler.setLevel(loglevel)
...@@ -582,16 +611,25 @@ class View(object): ...@@ -582,16 +611,25 @@ class View(object):
root_logger = logging.getLogger() root_logger = logging.getLogger()
root_logger.addHandler(self.file_handler) root_logger.addHandler(self.file_handler)
root_logger.setLevel(loglevel) root_logger.setLevel(loglevel)
# Console loggers
if ('test' in self.app_args.log and
'early' not in self.app_args.log):
self.stream_handler = ProgressStreamHandler()
test_logger.addHandler(self.stream_handler)
root_logger.addHandler(self.stream_handler)
self.replay_sourcejob = sourcejob self.replay_sourcejob = sourcejob
def stop_job_logging(self): def stop_job_logging(self):
""" """
Simple helper for removing a handler from the current logger. Simple helper for removing a handler from the current logger.
""" """
# File loggers
test_logger = logging.getLogger('avocado.test') test_logger = logging.getLogger('avocado.test')
linux_logger = logging.getLogger('avocado.linux')
root_logger = logging.getLogger() root_logger = logging.getLogger()
test_logger.removeHandler(self.file_handler) test_logger.removeHandler(self.file_handler)
linux_logger.removeHandler(self.file_handler)
root_logger.removeHandler(self.file_handler) root_logger.removeHandler(self.file_handler)
self.file_handler.close() self.file_handler.close()
# Console loggers
if self.stream_handler:
test_logger.removeHandler(self.stream_handler)
root_logger.removeHandler(self.stream_handler)
...@@ -29,6 +29,31 @@ PROG = 'avocado' ...@@ -29,6 +29,31 @@ PROG = 'avocado'
DESCRIPTION = 'Avocado Test Runner' DESCRIPTION = 'Avocado Test Runner'
def log_type(value):
valid_streams = ["app", "test", "debug", "remote", "early", "all", "none"]
value = value.split(',')
if any(_ not in valid_streams for _ in value):
missing = [_ for _ in value if _ not in valid_streams]
msg = ("Invalid logging stream(s): %s\n"
"Supported logging streams are:\n"
" app - application output\n"
" test - test output\n"
" debug - tracebacks and other debugging info\n"
" remote - fabric/paramiko debug\n"
" early - early logging of other streams (very verbose)\n"
" all - everything\n"
" none - disable everything\n" % ", ".join(missing))
sys.stderr.write(msg)
sys.exit(-1)
if 'all' in value:
return ["app", "test", "debug", "remote", "early"]
elif 'none' in value:
return []
else:
return value
class ArgumentParser(argparse.ArgumentParser): class ArgumentParser(argparse.ArgumentParser):
""" """
...@@ -57,6 +82,12 @@ class Parser(object): ...@@ -57,6 +82,12 @@ class Parser(object):
version='Avocado %s' % VERSION) version='Avocado %s' % VERSION)
self.application.add_argument('--config', metavar='CONFIG_FILE', self.application.add_argument('--config', metavar='CONFIG_FILE',
help='Use custom configuration from a file') help='Use custom configuration from a file')
self.application.add_argument('--log', action="store",
type=log_type,
metavar='STREAMS', default=['app'],
help="Comma separated list of logging "
"streams to be enabled (app,test,debug,"
"remote,early); By default 'app'")
def start(self): def start(self):
""" """
......
...@@ -355,11 +355,11 @@ class RunnerHumanOutputTest(unittest.TestCase): ...@@ -355,11 +355,11 @@ class RunnerHumanOutputTest(unittest.TestCase):
self.assertEqual(result.exit_status, expected_rc, self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %s:\n%s" % "Avocado did not return rc %s:\n%s" %
(expected_rc, result)) (expected_rc, result))
self.assertIn('[stdout] foo', result.stdout, result) self.assertIn('[stdout] foo', result.stderr, result)
self.assertIn('[stdout] \'"', result.stdout, result) self.assertIn('[stdout] \'"', result.stderr, result)
self.assertIn('[stdout] bar/baz', result.stdout, result) self.assertIn('[stdout] bar/baz', result.stderr, result)
self.assertIn('PASS /bin/echo -ne foo\\\\n\\\'\\"\\\\nbar/baz', self.assertIn('PASS /bin/echo -ne foo\\\\n\\\'\\"\\\\nbar/baz',
result.stdout, result) result.stderr, result)
# logdir name should escape special chars (/) # logdir name should escape special chars (/)
test_dirs = glob.glob(os.path.join(self.tmpdir, 'latest', test_dirs = glob.glob(os.path.join(self.tmpdir, 'latest',
'test-results', '*')) 'test-results', '*'))
...@@ -464,12 +464,12 @@ class RunnerSimpleTest(unittest.TestCase): ...@@ -464,12 +464,12 @@ class RunnerSimpleTest(unittest.TestCase):
self.assertEqual(result.exit_status, expected_rc, self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %s:\n%s" % "Avocado did not return rc %s:\n%s" %
(expected_rc, result)) (expected_rc, result))
self.assertIn('DEBUG| Debug message', result.stdout, result) self.assertIn('DEBUG| Debug message', result.stderr, result)
self.assertIn('INFO | Info message', result.stdout, result) self.assertIn('INFO | Info message', result.stderr, result)
self.assertIn('WARN | Warning message (should cause this test to ' self.assertIn('WARN | Warning message (should cause this test to '
'finish with warning)', result.stdout, result) 'finish with warning)', result.stderr, result)
self.assertIn('ERROR| Error message (ordinary message not changing ' self.assertIn('ERROR| Error message (ordinary message not changing '
'the results)', result.stdout, result) 'the results)', result.stderr, result)
def test_non_absolute_path(self): def test_non_absolute_path(self):
avocado_path = os.path.join(basedir, 'scripts', 'avocado') avocado_path = os.path.join(basedir, 'scripts', 'avocado')
......
...@@ -106,15 +106,15 @@ class MultiplexTests(unittest.TestCase): ...@@ -106,15 +106,15 @@ class MultiplexTests(unittest.TestCase):
msg_lines = msg.splitlines() msg_lines = msg.splitlines()
msg_header = '[stdout] Custom variable: %s' % msg_lines[0] msg_header = '[stdout] Custom variable: %s' % msg_lines[0]
self.assertIn(msg_header, result.stdout, self.assertIn(msg_header, result.stderr,
"Multiplexed variable should produce:" "Multiplexed variable should produce:"
"\n %s\nwhich is not present in the output:\n %s" "\n %s\nwhich is not present in the output:\n %s"
% (msg_header, "\n ".join(result.stdout.splitlines()))) % (msg_header, "\n ".join(result.stderr.splitlines())))
for msg_remain in msg_lines[1:]: for msg_remain in msg_lines[1:]:
self.assertIn('[stdout] %s' % msg_remain, result.stdout, self.assertIn('[stdout] %s' % msg_remain, result.stderr,
"Multiplexed variable should produce:" "Multiplexed variable should produce:"
"\n %s\nwhich is not present in the output:\n %s" "\n %s\nwhich is not present in the output:\n %s"
% (msg_remain, "\n ".join(result.stdout.splitlines()))) % (msg_remain, "\n ".join(result.stderr.splitlines())))
def tearDown(self): def tearDown(self):
shutil.rmtree(self.tmpdir) shutil.rmtree(self.tmpdir)
......
...@@ -205,10 +205,10 @@ class OutputPluginTest(unittest.TestCase): ...@@ -205,10 +205,10 @@ class OutputPluginTest(unittest.TestCase):
self.assertEqual(result.exit_status, expected_rc, self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" % "Avocado did not return rc %d:\n%s" %
(expected_rc, result)) (expected_rc, result))
job_id_list = re.findall('Job ID: (.*)', result.stdout, job_id_list = re.findall('Job ID: (.*)', result.stderr,
re.MULTILINE) re.MULTILINE)
self.assertTrue(job_id_list, 'No Job ID in stdout:\n%s' % self.assertTrue(job_id_list, 'No Job ID in stderr:\n%s' %
result.stdout) result.stderr)
job_id = job_id_list[0] job_id = job_id_list[0]
self.assertEqual(len(job_id), 40) self.assertEqual(len(job_id), 40)
......
...@@ -51,7 +51,7 @@ class StandaloneTests(unittest.TestCase): ...@@ -51,7 +51,7 @@ class StandaloneTests(unittest.TestCase):
expected_rc = exit_codes.AVOCADO_TESTS_FAIL expected_rc = exit_codes.AVOCADO_TESTS_FAIL
result = self.run_and_check(cmd_line, expected_rc, 'errortest_nasty') result = self.run_and_check(cmd_line, expected_rc, 'errortest_nasty')
exc = "NastyException: Nasty-string-like-exception" exc = "NastyException: Nasty-string-like-exception"
count = result.stdout.count("%s" % exc) count = result.stderr.count("%s" % exc)
self.assertEqual(count, 3, "Exception \\n%s should be present three " self.assertEqual(count, 3, "Exception \\n%s should be present three "
"times in the log (first from the traceback, then " "times in the log (first from the traceback, then "
"from the test log when raising the exception, and " "from the test log when raising the exception, and "
...@@ -62,14 +62,14 @@ class StandaloneTests(unittest.TestCase): ...@@ -62,14 +62,14 @@ class StandaloneTests(unittest.TestCase):
expected_rc = exit_codes.AVOCADO_TESTS_FAIL expected_rc = exit_codes.AVOCADO_TESTS_FAIL
result = self.run_and_check(cmd_line, expected_rc, 'errortest_nasty2') result = self.run_and_check(cmd_line, expected_rc, 'errortest_nasty2')
self.assertIn("Exception: Unable to get exception, check the traceback" self.assertIn("Exception: Unable to get exception, check the traceback"
" for details.", result.stdout) " for details.", result.stderr)
def test_errortest_nasty3(self): def test_errortest_nasty3(self):
cmd_line = './examples/tests/errortest_nasty3.py -r' cmd_line = './examples/tests/errortest_nasty3.py -r'
expected_rc = exit_codes.AVOCADO_TESTS_FAIL expected_rc = exit_codes.AVOCADO_TESTS_FAIL
result = self.run_and_check(cmd_line, expected_rc, 'errortest_nasty3') result = self.run_and_check(cmd_line, expected_rc, 'errortest_nasty3')
self.assertIn("TestError: <errortest_nasty3.NastyException instance at ", self.assertIn("TestError: <errortest_nasty3.NastyException instance at ",
result.stdout) result.stderr)
def test_errortest(self): def test_errortest(self):
cmd_line = './examples/tests/errortest.py -r' cmd_line = './examples/tests/errortest.py -r'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册