summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Lange <jml@mumak.net>2015-11-02 19:14:35 +0000
committerJonathan Lange <jml@mumak.net>2015-11-09 13:24:00 +0000
commitad518e2089ddd9051ec3beaeaaf624028efee574 (patch)
tree66c889f6251d4be482be605cacb7f20ee6a43417
parentc51fdb854ea1f7b0e473756fc42bfcf927c9652d (diff)
downloadtesttools-ad518e2089ddd9051ec3beaeaaf624028efee574.tar.gz
Aspirational documentation
-rw-r--r--requirements.txt1
-rw-r--r--testtools/testresult/real.py66
2 files changed, 67 insertions, 0 deletions
diff --git a/requirements.txt b/requirements.txt
index a944636..92adc5f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
pbr>=0.11
extras
+pyrsistent
# 'mimeparse' has not been uploaded by the maintainer with Python3 compat
# but someone kindly uploaded a fixed version as 'python-mimeparse'.
python-mimeparse
diff --git a/testtools/testresult/real.py b/testtools/testresult/real.py
index 8773c65..43edfc0 100644
--- a/testtools/testresult/real.py
+++ b/testtools/testresult/real.py
@@ -32,6 +32,8 @@ from extras import safe_hasattr, try_import, try_imports
parse_mime_type = try_import('mimeparse.parse_mime_type')
Queue = try_imports(['Queue.Queue', 'queue.Queue'])
+from pyrsistent import PRecord, field, pmap_field, pset_field
+
from testtools.compat import str_is_unicode, _u, _b
from testtools.content import (
Content,
@@ -267,6 +269,44 @@ class TestResult(unittest.TestResult):
"""
+"""Interim states:
+
+* None - no particular status is being reported, or status being reported is
+ not associated with a test (e.g. when reporting on stdout / stderr chatter).
+
+* inprogress - the test is currently running. Emitted by tests when they start
+ running and at any intermediary point they might choose to indicate their
+ continual operation.
+"""
+INTERIM_STATES = frozenset({None, 'inprogress'})
+
+"""Final states:
+
+* exists - the test exists. This is used when a test is not being executed.
+ Typically this is when querying what tests could be run in a test run (which
+ is useful for selecting tests to run).
+
+* xfail - the test failed but that was expected. This is purely informative -
+ the test is not considered to be a failure.
+
+* uxsuccess - the test passed but was expected to fail. The test will be
+ considered a failure.
+
+* success - the test has finished without error.
+
+* fail - the test failed (or errored). The test will be considered a failure.
+
+* skip - the test was selected to run but chose to be skipped. e.g. a test
+ dependency was missing. This is purely informative: the test is not
+ considered to be a failure.
+"""
+FINAL_STATES = frozenset(
+ {'exists', 'xfail', 'uxsuccess', 'success', 'fail', 'skip'})
+
+
+STATES = INTERIM_STATES | FINAL_STATES
+
+
class StreamResult(object):
"""A test result for reporting the activity of a test run.
@@ -592,6 +632,32 @@ class StreamTagger(CopyStreamResult):
super(StreamTagger, self).status(*args, **kwargs)
+class TestRecord(PRecord):
+ """Representation of a test."""
+
+ """The test id."""
+ id = field(unicode, mandatory=True)
+
+ """Tags for the test."""
+ tags = pset_field(unicode, optional=False)
+
+ """File attachments."""
+ details = pmap_field(unicode, Content, optional=False)
+
+ """One of the StreamResult status codes."""
+ status = field(unicode, mandatory=True, invariant=lambda x: x in STATES)
+
+ """Pair of timestamps (x, y).
+
+ x is the first timestamp we received for this test, y is the one that
+ triggered the notification. y can be None if the test hanged.
+
+ Timestamps are not compared - their ordering is purely order received in
+ the stream.
+ """
+ timestamps = field(tuple, mandatory=True)
+
+
class StreamToDict(StreamResult):
"""A specialised StreamResult that emits a callback as tests complete.