On Mon, 2010-10-11 at 15:18 +0200, Kamil Páral wrote:
This patch will allow test creators to decide whether they want to
have
some error reported as CRASHED or as ABORTED. The difference is that
CRASHED tests should indicate programming errors in our code, and ABORTED
tests should indicate errors of third parties (that we don't control,
like network communication with Koji, Bodhi, etc). Then we can simply
decide to re-run ABORTED tests without closer inspection, we will want
to examine CRASHED tests more carefully.
All uncaught exceptions are reported as CRASHED. If you want to have
your test reported as ABORTED, you must set self.result to 'ABORTED' and
then re-raise the original exception, or raise a new one (error.TestFail
is preferred).
This is a code snippet where we guard some code and end the test as
ABORTED if something fails:
try:
//download from Koji
except IOError, e: //or some other error
self.result = 'ABORTED'
raise
(self.summary will be extracted from exception value.)
This is a code snippet where you don't have any original exception, but
still want to report the test as ABORTED:
foo = //do some stuff
if foo == None:
self.result = 'ABORTED'
self.summary = 'No result returned from service bar'
raise error.TestFail
You should either fill in self.summary or provide that information as an
exception argument. So this is equivalent:
foo = //do some stuff
if foo == None:
self.result = 'ABORTED'
raise error.TestFail('No result returned from service bar')
So this means the only time we are recommending raising error.TestFail
is when a test has identified a test failure/exception?
I like how this clarifies how error.TestFail should be used by autoqa
tests. It's not intended for testers to mark when a test has discovered
failures, but when the test itself has failed (couldn't download package
or something). Hopefully I've re-phrased this properly.
Once again, this patch does not force us to write this stuff
everywhere.
It just enables us to do so. That means we will probably use that for
code snippets that communicate with external services and fail often.
For other code parts we may be completely satisfied with default
behavior.
Thanks,
James
---
lib/python/test.py | 21 ++++++++++++++-------
1 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/lib/python/test.py b/lib/python/test.py
index eccbb09..d509283 100644
--- a/lib/python/test.py
+++ b/lib/python/test.py
@@ -19,6 +19,7 @@
from autotest_lib.client.bin import test, utils
from autotest_lib.client.bin.test_config import config_loader
+from autotest_lib.client.common_lib import error
from decorators import ExceptionCatcher
from util import make_autotest_url
@@ -48,16 +49,22 @@ class AutoQATest(test.test, object):
def run_once(self, **kwargs):
pass
- def process_exception(self, exc = None):
+ def process_exception(self, exc):
self._convert_list_variables()
- self.result = "CRASHED"
- if exc is not None:
- self.summary = "%s: %s" % (exc[1].__class__.__name__, exc[1])
- self.outputs += '\n%s\n%s' % ('-'*70,
- ''.join(traceback.format_exception(exc[0], exc[1], exc[2])))
+ if self.result == 'ABORTED':
+ # the exception is raised intentionally, don't override anything,
+ # only if empty
+ if not self.summary:
+ self.summary = "%s: %s" % (exc[1].__class__.__name__, exc[1])
else:
- self.summary = "Exception: Unknown exception"
+ self.result = "CRASHED"
+ self.summary = "%s: %s" % (exc[1].__class__.__name__, exc[1])
+
+ # append traceback
+ self.outputs += '\n%s\n%s' % ('-'*70,
+ ''.join(traceback.format_exception(exc[0], exc[1], exc[2])))
+
try:
self.postprocess_iteration()
except Exception: