summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2008-12-13 15:36:46 +1100
committerRobert Collins <robertc@robertcollins.net>2008-12-13 15:36:46 +1100
commit6bd993aaf9d5e9bea1295125f2a503731df5e1c3 (patch)
tree3966e2222d3f300be4eb411c1823d6b02abc0fc5 /python
parent37e5905d6caf96f70e9e3af5aa476aa754ccd3f0 (diff)
parent0c09f4a34ac3d4f75292306839709bc18762f8ac (diff)
downloadsubunit-git-6bd993aaf9d5e9bea1295125f2a503731df5e1c3.tar.gz
Merge tags support.
Diffstat (limited to 'python')
-rw-r--r--python/subunit/__init__.py39
-rw-r--r--python/subunit/tests/test_test_protocol.py53
2 files changed, 88 insertions, 4 deletions
diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py
index f52dbaa..05e4297 100644
--- a/python/subunit/__init__.py
+++ b/python/subunit/__init__.py
@@ -1,5 +1,5 @@
#
-# subunit: extensions to python unittest to get test results from subprocesses.
+# subunit: extensions to Python unittest to get test results from subprocesses.
# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net>
#
# This program is free software; you can redistribute it and/or modify
@@ -43,7 +43,10 @@ def join_dir(base_path, path):
class TestProtocolServer(object):
- """A class for receiving results from a TestProtocol client."""
+ """A class for receiving results from a TestProtocol client.
+
+ :ivar tags: The current tags associated with the protocol stream.
+ """
OUTSIDE_TEST = 0
TEST_STARTED = 1
@@ -64,6 +67,7 @@ class TestProtocolServer(object):
self.state = TestProtocolServer.OUTSIDE_TEST
self.client = client
self._stream = stream
+ self.tags = set()
def _addError(self, offset, line):
if (self.state == TestProtocolServer.TEST_STARTED and
@@ -128,6 +132,23 @@ class TestProtocolServer(object):
else:
self.stdOutLineReceived(line)
+ def _handleTags(self, offset, line):
+ """Process a tags command."""
+ tags = line[offset:].split()
+ new_tags = set()
+ gone_tags = set()
+ for tag in tags:
+ if tag[0] == '-':
+ gone_tags.add(tag[1:])
+ else:
+ new_tags.add(tag)
+ if self.state == TestProtocolServer.OUTSIDE_TEST:
+ update_tags = self.tags
+ else:
+ update_tags = self._current_test.tags
+ update_tags.update(new_tags)
+ update_tags.difference_update(gone_tags)
+
def lineReceived(self, line):
"""Call the appropriate local method for the received line."""
if line == "]\n":
@@ -149,6 +170,8 @@ class TestProtocolServer(object):
self._addFailure(offset, line)
elif cmd in ('success', 'successful'):
self._addSuccess(offset, line)
+ elif cmd in ('tags'):
+ self._handleTags(offset, line)
else:
self.stdOutLineReceived(line)
else:
@@ -188,6 +211,7 @@ class TestProtocolServer(object):
self._current_test = RemotedTestCase(line[offset:-1])
self.current_test_description = line[offset:-1]
self.client.startTest(self._current_test)
+ self._current_test.tags = set(self.tags)
else:
self.stdOutLineReceived(line)
@@ -196,7 +220,7 @@ class TestProtocolServer(object):
class RemoteException(Exception):
- """An exception that occured remotely to python."""
+ """An exception that occured remotely to Python."""
def __eq__(self, other):
try:
@@ -242,7 +266,14 @@ def RemoteError(description=""):
class RemotedTestCase(unittest.TestCase):
- """A class to represent test cases run in child processes."""
+ """A class to represent test cases run in child processes.
+
+ Instances of this class are used to provide the Python test API a TestCase
+ that can be printed to the screen, introspected for metadata and so on.
+ However, as they are a simply a memoisation of a test that was actually
+ run in the past by a separate process, they cannot perform any interactive
+ actions.
+ """
def __eq__ (self, other):
try:
diff --git a/python/subunit/tests/test_test_protocol.py b/python/subunit/tests/test_test_protocol.py
index 0b9fc77..52b33c8 100644
--- a/python/subunit/tests/test_test_protocol.py
+++ b/python/subunit/tests/test_test_protocol.py
@@ -521,6 +521,59 @@ class TestTestProtocolServerAddSuccess(unittest.TestCase):
self.simple_success_keyword("successful:")
+class TestTestProtocolServerStreamTags(unittest.TestCase):
+ """Test managing tags on the protocol level."""
+
+ def setUp(self):
+ self.client = MockTestProtocolServerClient()
+ self.protocol = subunit.TestProtocolServer(self.client)
+
+ def test_initial_tags(self):
+ self.protocol.lineReceived("tags: foo bar:baz quux\n")
+ self.assertEqual(set(["foo", "bar:baz", "quux"]),
+ self.protocol.tags)
+
+ def test_minus_removes_tags(self):
+ self.protocol.lineReceived("tags: foo bar\n")
+ self.protocol.lineReceived("tags: -bar quux\n")
+ self.assertEqual(set(["foo", "quux"]),
+ self.protocol.tags)
+
+ def test_tags_get_set_on_test_no_tags(self):
+ self.protocol.lineReceived("test mcdonalds farm\n")
+ test = self.client.start_calls[-1]
+ self.assertEqual(set(), test.tags)
+
+ def test_tags_get_set_on_test_protocol_tags_only(self):
+ self.protocol.lineReceived("tags: foo bar\n")
+ self.protocol.lineReceived("test mcdonalds farm\n")
+ test = self.client.start_calls[-1]
+ self.assertEqual(set(["foo", "bar"]), test.tags)
+
+ def test_tags_get_set_on_test_simple(self):
+ self.protocol.lineReceived("test mcdonalds farm\n")
+ test = self.client.start_calls[-1]
+ self.protocol.lineReceived("tags: foo bar\n")
+ self.assertEqual(set(["foo", "bar"]), test.tags)
+ self.assertEqual(set(), self.protocol.tags)
+
+ def test_tags_get_set_on_test_minus_removes(self):
+ self.protocol.lineReceived("test mcdonalds farm\n")
+ test = self.client.start_calls[-1]
+ self.protocol.lineReceived("tags: foo bar\n")
+ self.protocol.lineReceived("tags: -bar quux\n")
+ self.assertEqual(set(["foo", "quux"]), test.tags)
+ self.assertEqual(set(), self.protocol.tags)
+
+ def test_test_tags_inherit_protocol_tags(self):
+ self.protocol.lineReceived("tags: foo bar\n")
+ self.protocol.lineReceived("test mcdonalds farm\n")
+ test = self.client.start_calls[-1]
+ self.protocol.lineReceived("tags: -bar quux\n")
+ self.assertEqual(set(["foo", "quux"]), test.tags)
+ self.assertEqual(set(["foo", "bar"]), self.protocol.tags)
+
+
class TestRemotedTestCase(unittest.TestCase):
def test_simple(self):