提交 2c571c7d 编写于 作者: A Amador Pahim

test: always execute tearDown()

Currently, when something goes wrong in setUp(), tearDown() is not
executed. This patch changes the behaviour of our Test class, making the
tearDown() to be always executed, regardless what happens in setUp().

Reference: https://trello.com/c/zSZ4xFwpSigned-off-by: NAmador Pahim <apahim@redhat.com>
上级 6b02360d
......@@ -563,47 +563,45 @@ class Test(unittest.TestCase):
stdout_check_exception = None
stderr_check_exception = None
skip_test = getattr(testMethod, '__skip_test_decorator__', False)
cancel_test = False
try:
if skip_test is False:
self.setUp()
except (exceptions.TestSetupSkip, exceptions.TestSkipError) as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise exceptions.TestSkipError(details)
except exceptions.TestCancel as details:
cancel_test = details
except: # Old-style exceptions are not inherited from Exception()
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
details = sys.exc_info()[1]
raise exceptions.TestSetupFail(details)
try:
if cancel_test:
raise exceptions.TestCancel(cancel_test)
testMethod()
except exceptions.TestSetupSkip as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
skip_illegal_msg = ('Calling skip() in places other than '
'setUp() is not allowed in avocado, you '
'must fix your test. Original skip exception: '
'%s' % details)
raise exceptions.TestError(skip_illegal_msg)
except exceptions.TestSkipError as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise
except exceptions.TestCancel as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise
except: # Old-style exceptions are not inherited from Exception()
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
details = sys.exc_info()[1]
if not isinstance(details, Exception): # Avoid passing nasty exc
details = exceptions.TestError("%r: %s" % (details, details))
test_exception = details
self.log.debug("Local variables:")
local_vars = inspect.trace()[1][0].f_locals
for key, value in local_vars.iteritems():
self.log.debug(' -> %s %s: %s', key, type(value), value)
raise exceptions.TestSetupFail(details)
else:
try:
testMethod()
except exceptions.TestSetupSkip as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
skip_illegal_msg = ('Calling skip() in places other than '
'setUp() is not allowed in avocado, you '
'must fix your test. Original skip exception: '
'%s' % details)
raise exceptions.TestError(skip_illegal_msg)
except exceptions.TestSkipError as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise
except exceptions.TestCancel as details:
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise
except: # Old-style exceptions are not inherited from Exception()
stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
details = sys.exc_info()[1]
if not isinstance(details, Exception): # Avoid passing nasty exc
details = exceptions.TestError("%r: %s" % (details, details))
test_exception = details
self.log.debug("Local variables:")
local_vars = inspect.trace()[1][0].f_locals
for key, value in local_vars.iteritems():
self.log.debug(' -> %s %s: %s', key, type(value), value)
finally:
try:
if skip_test is False:
......
......@@ -516,9 +516,11 @@ But we'd still recommend using ``avocado.main`` instead which is our main entry
Setup and cleanup methods
=========================
If you need to perform setup actions before/after your test, you may do so
in the ``setUp`` and ``tearDown`` methods, respectively. We'll give examples
in the following section.
To perform setup actions before/after your test, you may use ``setUp``
and ``tearDown`` methods. The ``tearDown`` method is always executed
even on ``setUp`` failure so don't forget to initialize your variables
early in the ``setUp``. Example of usage is in the next section
`Running third party test suites`_.
Running third party test suites
===============================
......
from avocado import Test
class StatusTest(Test):
def setUp(self):
self.log.info('setup pre')
if self.params.get('location') == 'setUp':
exec(self.params.get('command'))
self.log.info('setup post')
def test(self):
self.log.info('test pre')
if self.params.get('location') == 'test':
exec(self.params.get('command'))
self.log.info('test post')
def tearDown(self):
self.log.info('teardown pre')
if self.params.get('location') == 'tearDown':
exec(self.params.get('command'))
self.log.info('teardown post')
locations: !mux
setup:
location: setUp
test:
location: test
teardown:
location: tearDown
commands: !mux
skip:
command: self.skip()
cancel:
command: self.cancel()
fail:
command: self.fail()
warn:
command: self.log.warn('')
exception:
command: raise Exception
exit:
command: import sys; sys.exit(-1)
kill:
!filter-only : /run/locations/test
command: import os; os.kill(os.getpid(), 9)
import json
import os
import shutil
import tempfile
import unittest
from avocado.utils import process
basedir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..')
basedir = os.path.abspath(basedir)
AVOCADO = os.environ.get("UNITTEST_AVOCADO_CMD", "./scripts/avocado")
ALL_MESSAGES = ['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre',
'teardown post']
# Format: {variant1: (status,
# [msg_in, ...])
# variant2: (status,
# [msg_in, ...])
EXPECTED_RESULTS = {'skip-setup-d304': ('SKIP',
['setup pre',
'teardown pre',
'teardown post',
"[WARNING: self.skip() will be "
"deprecated. Use 'self.cancel()' "
"or the skip decorators]"]),
'skip-test-914e': ('ERROR',
['setup pre',
'setup post',
'test pre',
'teardown pre',
'teardown post',
"Calling skip() in places other "
"than setUp() is not allowed in "
"avocado, you must fix your "
"test."]),
'skip-teardown-d105': ('ERROR',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre',
"Calling skip() in places other "
"than setUp() is not allowed in "
"avocado, you must fix your "
"test."]),
'cancel-setup-965f': ('CANCEL',
['setup pre',
'teardown pre',
'teardown post']),
'cancel-test-9699': ('CANCEL',
['setup pre',
'setup post',
'test pre',
'teardown pre',
'teardown post']),
'cancel-teardown-8867': ('CANCEL',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre']),
'fail-setup-6c89': ('ERROR',
['setup pre',
'teardown pre',
'teardown post']),
'fail-test-f361': ('FAIL',
['setup pre',
'setup post',
'test pre',
'teardown pre',
'teardown post']),
'fail-teardown-a0b0': ('ERROR',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre']),
'warn-setup-0730': ('WARN',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre',
'teardown post']),
'warn-test-b0e3': ('WARN',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre',
'teardown post']),
'warn-teardown-3d38': ('WARN',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre',
'teardown post']),
'exit-setup-0eba': ('ERROR',
['setup pre',
'teardown pre',
'teardown post']),
'exit-test-f680': ('ERROR',
['setup pre',
'setup post',
'test pre',
'teardown pre',
'teardown post']),
'exit-teardown-6304': ('ERROR',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre']),
'exception-setup-37d3': ('ERROR',
['setup pre',
'teardown pre',
'teardown post']),
'exception-test-8f7d': ('ERROR',
['setup pre',
'setup post',
'test pre',
'teardown pre',
'teardown post']),
'exception-teardown-dfb1': ('ERROR',
['setup pre',
'setup post',
'test pre',
'test post',
'teardown pre']),
'kill-test-57fe': ('ERROR',
['setup pre',
'setup post',
'test pre']),
}
class TestStatuses(unittest.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp(prefix='avocado_' + __name__)
test_file = os.path.abspath(os.path.join(os.path.dirname(__file__),
os.path.pardir,
".data",
'test_statuses.py'))
yaml_file = os.path.abspath(os.path.join(os.path.dirname(__file__),
os.path.pardir,
".data",
'test_statuses.yaml'))
cmd = ('%s run %s -m %s --sysinfo=off --job-results-dir %s --json -' %
(AVOCADO, test_file, yaml_file, self.tmpdir))
results = process.run(cmd, ignore_status=True)
self.results = json.loads(results.stdout)
def test(self):
missing_tests = []
# Testing each individual test results
for test in self.results['tests']:
variant = test['id'].split(';')[1]
expected = EXPECTED_RESULTS.get(variant, False)
if not expected:
missing_tests.append(variant)
else:
self._check_test(test, expected)
# Testing if all variants were covered
missing_msg = ' '.join(missing_tests)
self.assertEqual(missing_msg, '',
"Expected results not found for variants: %s" %
missing_msg)
def _check_test(self, test, expected):
variant = test['id'].split(';')[1]
self.assertEqual(expected[0], test['status'],
"Status error: '%s' != '%s' (%s)" %
(expected[0], test['status'], variant))
debug_log = open(test['logfile'], 'r').read()
for msg in expected[1]:
self.assertIn(msg, debug_log,
"Message '%s' should be in the log (%s)."
"\nJSON results:\n%s"
"\nDebug Log:\n%s" %
(msg, variant, test, debug_log))
for msg in set(ALL_MESSAGES) - set(expected[1]):
self.assertNotIn(msg, debug_log,
"Message '%s' should not be in the log (%s)"
"\nJSON results:\n%s"
"\nDebug Log:\n%s" %
(msg, variant, test, debug_log))
def tearDown(self):
shutil.rmtree(self.tmpdir)
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册