Merge lp:~jml/subunit/tag-collapsing-rigor into lp:~subunit/subunit/trunk

Proposed by Jonathan Lange
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: 165
Merged at revision: 163
Proposed branch: lp:~jml/subunit/tag-collapsing-rigor
Merge into: lp:~subunit/subunit/trunk
Diff against target: 175 lines (+98/-26)
2 files modified
python/subunit/test_results.py (+30/-20)
python/subunit/tests/test_test_results.py (+68/-6)
To merge this branch: bzr merge lp:~jml/subunit/tag-collapsing-rigor
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+102838@code.launchpad.net

Description of the change

TagCollapsingDecorator was not forwarding tags correctly.
  * was sending tags() event after addSuccess() etc. so the generated subunit stream turned local tags into global tags
  * was not collapsing global tags

This caused problems for my tag filtering branch. This branch fixes those problems.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
Robert Collins (lifeless) wrote :

You should be able to land this yourself.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'python/subunit/test_results.py'
2--- python/subunit/test_results.py 2012-03-25 14:58:44 +0000
3+++ python/subunit/test_results.py 2012-04-20 11:56:19 +0000
4@@ -205,35 +205,48 @@
5 return self.decorated.time(a_datetime)
6
7
8-class TagCollapsingDecorator(TestResultDecorator):
9+class TagCollapsingDecorator(HookedTestResultDecorator):
10 """Collapses many 'tags' calls into one where possible."""
11
12 def __init__(self, result):
13 super(TagCollapsingDecorator, self).__init__(result)
14- # The (new, gone) tags for the current test.
15+ self._clear_tags()
16+
17+ def _clear_tags(self):
18+ self._global_tags = set(), set()
19 self._current_test_tags = None
20
21+ def _get_current_tags(self):
22+ if self._current_test_tags:
23+ return self._current_test_tags
24+ return self._global_tags
25+
26+ def startTestRun(self):
27+ super(TagCollapsingDecorator, self).startTestRun()
28+ self._clear_tags()
29+
30 def startTest(self, test):
31 """Start a test.
32
33 Not directly passed to the client, but used for handling of tags
34 correctly.
35 """
36- self.decorated.startTest(test)
37+ super(TagCollapsingDecorator, self).startTest(test)
38 self._current_test_tags = set(), set()
39
40 def stopTest(self, test):
41- """Stop a test.
42-
43- Not directly passed to the client, but used for handling of tags
44- correctly.
45- """
46- # Tags to output for this test.
47- if self._current_test_tags[0] or self._current_test_tags[1]:
48- self.decorated.tags(*self._current_test_tags)
49- self.decorated.stopTest(test)
50+ super(TagCollapsingDecorator, self).stopTest(test)
51 self._current_test_tags = None
52
53+ def _before_event(self):
54+ new_tags, gone_tags = self._get_current_tags()
55+ if new_tags or gone_tags:
56+ self.decorated.tags(new_tags, gone_tags)
57+ if self._current_test_tags:
58+ self._current_test_tags = set(), set()
59+ else:
60+ self._global_tags = set(), set()
61+
62 def tags(self, new_tags, gone_tags):
63 """Handle tag instructions.
64
65@@ -243,14 +256,11 @@
66 :param new_tags: Tags to add,
67 :param gone_tags: Tags to remove.
68 """
69- if self._current_test_tags is not None:
70- # gather the tags until the test stops.
71- self._current_test_tags[0].update(new_tags)
72- self._current_test_tags[0].difference_update(gone_tags)
73- self._current_test_tags[1].update(gone_tags)
74- self._current_test_tags[1].difference_update(new_tags)
75- else:
76- return self.decorated.tags(new_tags, gone_tags)
77+ current_new_tags, current_gone_tags = self._get_current_tags()
78+ current_new_tags.update(new_tags)
79+ current_new_tags.difference_update(gone_tags)
80+ current_gone_tags.update(gone_tags)
81+ current_gone_tags.difference_update(new_tags)
82
83
84 class TimeCollapsingDecorator(HookedTestResultDecorator):
85
86=== modified file 'python/subunit/tests/test_test_results.py'
87--- python/subunit/tests/test_test_results.py 2012-03-25 14:58:44 +0000
88+++ python/subunit/tests/test_test_results.py 2012-04-20 11:56:19 +0000
89@@ -201,12 +201,55 @@
90
91 class TestTagCollapsingDecorator(TestCase):
92
93- def test_tags_forwarded_outside_of_tests(self):
94- result = ExtendedTestResult()
95- tag_collapser = subunit.test_results.TagCollapsingDecorator(result)
96- tag_collapser.tags(set(['a', 'b']), set())
97- self.assertEquals(
98- [('tags', set(['a', 'b']), set([]))], result._events)
99+ def test_tags_collapsed_outside_of_tests(self):
100+ result = ExtendedTestResult()
101+ tag_collapser = subunit.test_results.TagCollapsingDecorator(result)
102+ tag_collapser.tags(set(['a']), set())
103+ tag_collapser.tags(set(['b']), set())
104+ tag_collapser.startTest(self)
105+ self.assertEquals(
106+ [('tags', set(['a', 'b']), set([])),
107+ ('startTest', self),
108+ ], result._events)
109+
110+ def test_tags_collapsed_outside_of_tests_are_flushed(self):
111+ result = ExtendedTestResult()
112+ tag_collapser = subunit.test_results.TagCollapsingDecorator(result)
113+ tag_collapser.startTestRun()
114+ tag_collapser.tags(set(['a']), set())
115+ tag_collapser.tags(set(['b']), set())
116+ tag_collapser.startTest(self)
117+ tag_collapser.addSuccess(self)
118+ tag_collapser.stopTest(self)
119+ tag_collapser.stopTestRun()
120+ self.assertEquals(
121+ [('startTestRun',),
122+ ('tags', set(['a', 'b']), set([])),
123+ ('startTest', self),
124+ ('addSuccess', self),
125+ ('stopTest', self),
126+ ('stopTestRun',),
127+ ], result._events)
128+
129+ def test_tags_forwarded_after_tests(self):
130+ test = subunit.RemotedTestCase('foo')
131+ result = ExtendedTestResult()
132+ tag_collapser = subunit.test_results.TagCollapsingDecorator(result)
133+ tag_collapser.startTestRun()
134+ tag_collapser.startTest(test)
135+ tag_collapser.addSuccess(test)
136+ tag_collapser.stopTest(test)
137+ tag_collapser.tags(set(['a']), set(['b']))
138+ tag_collapser.stopTestRun()
139+ self.assertEqual(
140+ [('startTestRun',),
141+ ('startTest', test),
142+ ('addSuccess', test),
143+ ('stopTest', test),
144+ ('tags', set(['a']), set(['b'])),
145+ ('stopTestRun',),
146+ ],
147+ result._events)
148
149 def test_tags_collapsed_inside_of_tests(self):
150 result = ExtendedTestResult()
151@@ -238,6 +281,25 @@
152 ('stopTest', test)],
153 result._events)
154
155+ def test_tags_sent_before_result(self):
156+ # Because addSuccess and friends tend to send subunit output
157+ # immediately, and because 'tags:' before a result line means
158+ # something different to 'tags:' after a result line, we need to be
159+ # sure that tags are emitted before 'addSuccess' (or whatever).
160+ result = ExtendedTestResult()
161+ tag_collapser = subunit.test_results.TagCollapsingDecorator(result)
162+ test = subunit.RemotedTestCase('foo')
163+ tag_collapser.startTest(test)
164+ tag_collapser.tags(set(['a']), set())
165+ tag_collapser.addSuccess(test)
166+ tag_collapser.stopTest(test)
167+ self.assertEquals(
168+ [('startTest', test),
169+ ('tags', set(['a']), set()),
170+ ('addSuccess', test),
171+ ('stopTest', test)],
172+ result._events)
173+
174
175 class TestTimeCollapsingDecorator(TestCase):
176

Subscribers

People subscribed via source and target branches