Merge lp:~jml/launchpad/branch-sample-data-doctests into lp:launchpad

Proposed by Jonathan Lange
Status: Merged
Approved by: Deryck Hodge
Approved revision: no longer in the source branch.
Merged at revision: 11261
Proposed branch: lp:~jml/launchpad/branch-sample-data-doctests
Merge into: lp:launchpad
Diff against target: 471 lines (+206/-223)
5 files modified
lib/lp/bugs/configure.zcml (+1/-2)
lib/lp/bugs/doc/bug-branch.txt (+0/-187)
lib/lp/bugs/doc/bug.txt (+0/-33)
lib/lp/bugs/model/bugbranch.py (+0/-1)
lib/lp/bugs/tests/test_bugbranch.py (+205/-0)
To merge this branch: bzr merge lp:~jml/launchpad/branch-sample-data-doctests
Reviewer Review Type Date Requested Status
Deryck Hodge (community) code Approve
Review via email: mp+31317@code.launchpad.net

Description of the change

One day, I would like to get rid of all the sample data in our test suite. Today is not that day.

However, this branch does remove one sampledata-using doctest and replaces it with a suite of unit tests which provide the same level of coverage but use the factory instead. It also removes some similar code from another doctest.

There are no behavioral changes in this branch.

To post a comment you must log in.
Revision history for this message
Deryck Hodge (deryck) wrote :

With the changes to remove the section that you marked as XXX in the diff I reviewed, consider this r=me. The former tests for checking that ObjectModified events for linked branches is a bad test, since we don't do this and shouldn't change a bug's date_last_updated date even if the branch could be modified.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/configure.zcml'
2--- lib/lp/bugs/configure.zcml 2010-07-23 01:15:17 +0000
3+++ lib/lp/bugs/configure.zcml 2010-07-29 19:50:21 +0000
4@@ -474,8 +474,7 @@
5 <require
6 permission="launchpad.Edit"
7 attributes="
8- destroySelf"
9- set_attributes="fixed_in_revision_id"/>
10+ destroySelf"/>
11 </class>
12 <adapter
13 for="lp.bugs.interfaces.bugbranch.IBugBranch"
14
15=== removed file 'lib/lp/bugs/doc/bug-branch.txt'
16--- lib/lp/bugs/doc/bug-branch.txt 2010-03-29 12:57:20 +0000
17+++ lib/lp/bugs/doc/bug-branch.txt 1970-01-01 00:00:00 +0000
18@@ -1,187 +0,0 @@
19-= Bugs and Branches =
20-
21-Branches can be linked to Bugs, to track work in progress on branches,
22-and when fixes are committed.
23-
24- >>> from canonical.launchpad.webapp.testing import verifyObject
25- >>> from canonical.launchpad.interfaces import IBugBranch, IBugBranchSet
26- >>> from canonical.launchpad.database import BugBranch, BugBranchSet
27- >>> verifyObject(IBugBranch, BugBranch.get(1))
28- True
29- >>> verifyObject(IBugBranchSet, BugBranchSet())
30- True
31-
32-
33-== BugBranch ==
34-
35-BugBranch links a bug and a branch.
36-
37- >>> from canonical.launchpad.interfaces import (
38- ... IBugSet, IPersonSet)
39- >>> from lp.code.interfaces.branchlookup import IBranchLookup
40- >>> from canonical.database.sqlbase import flush_database_updates
41-
42- >>> login("no-priv@canonical.com")
43-
44- >>> bugset = getUtility(IBugSet)
45- >>> bug = bugset.get(1)
46- >>> branch = getUtility(IBranchLookup).get(10)
47-
48-Adding a branch to a bug returns an IBugBranch.
49-
50- >>> user = getUtility(IPersonSet).getByEmail("no-priv@canonical.com")
51- >>> bug_branch = bug.linkBranch(branch, user)
52-
53- >>> flush_database_updates()
54-
55-The bug and branch fields of the returned bug_branch should reflect our
56-sample data.
57-
58- >>> bug_branch.bug.id
59- 1
60- >>> bug_branch.branch.id
61- 10
62- >>> print bug_branch.registrant.displayname
63- No Privileges Person
64-
65- >>> [bug_branch.branch.name for bug_branch in
66- ... bug.linked_branches]
67- [u'release-0.9.2']
68-
69-Trying to add a branch that is already linked to a bug will simply
70-return the existing BugBranch.
71-
72- >>> bug_branch_two = bug.linkBranch(branch, user)
73- >>> bug_branch_two == bug_branch
74- True
75-
76-You can check if a branch is linked to a bug:
77-
78- >>> bug.hasBranch(branch)
79- True
80-
81- >>> bug_two = bugset.get(2)
82- >>> bug_two.hasBranch(branch)
83- False
84- >>> branch = getUtility(IBranchLookup).get(1)
85- >>> bug_branch_three = bug.linkBranch(branch, user)
86-
87-If we make the bug private, no-priv won't be allowed to edit either
88-the bug or the BugBranch.
89-
90- >>> login('foo.bar@canonical.com')
91- >>> bug.setPrivate(True, getUtility(ILaunchBag).user)
92- True
93- >>> login('no-priv@canonical.com')
94-
95- >>> bug.description = 'Yet another description.'
96- Traceback (most recent call last):
97- ...
98- Unauthorized:...
99-
100- >>> bug.unlinkBranch(branch, getUtility(ILaunchBag).user)
101- Traceback (most recent call last):
102- ...
103- Unauthorized:...
104-
105- >>> another_branch = factory.makeAnyBranch()
106- >>> bug.linkBranch(another_branch, getUtility(ILaunchBag).user)
107- Traceback (most recent call last):
108- ...
109- Unauthorized:...
110-
111- >>> login('foo.bar@canonical.com')
112- >>> bug.setPrivate(False, getUtility(ILaunchBag).user)
113- True
114-
115-Likewise, anonymous users cannot link or unlink branches.
116-
117- >>> login(ANONYMOUS)
118-
119- >>> bug.unlinkBranch(branch, getUtility(ILaunchBag).user)
120- Traceback (most recent call last):
121- ...
122- Unauthorized:...
123-
124- >>> bug.linkBranch(another_branch, getUtility(ILaunchBag).user)
125- Traceback (most recent call last):
126- ...
127- Unauthorized:...
128-
129- >>> login('no-priv@canonical.com')
130-
131-You can unlink a branch from a bug using unlinkBranch().
132-
133- >>> bug.hasBranch(branch)
134- True
135- >>> bug.unlinkBranch(branch, getUtility(ILaunchBag).user)
136- >>> bug.hasBranch(branch)
137- False
138-
139-Calling unlinkBranch() once again is a noop.
140-
141- >>> bug.unlinkBranch(branch, getUtility(ILaunchBag).user)
142-
143- >>> bug_branch = bug.linkBranch(branch, user)
144-
145-
146-== Bugs Related to Branches ==
147-
148-The bugs related to a branch are accessible via the linked_bugs
149-property.
150-
151- >>> sorted([bug.id for bug in branch.linked_bugs])
152- [1, 4, 5]
153-
154-
155-== Getting bug branches associated with multiple branches ==
156-
157-Sometimes we want to get the associated bug branch links for a set of branches.
158-The getBugBranchesForBranches method can do this.
159-
160-Firstly we need to get the branches.
161-
162- >>> from canonical.launchpad.interfaces import IBugBranchSet
163- >>> branches = [getUtility(IBranchLookup).getByUniqueName(
164- ... '~carlos/iso-codes/0.35'),
165- ... getUtility(IBranchLookup).getByUniqueName(
166- ... '~mark/firefox/release-0.9.2')]
167-
168-The bug branches returned are only those where the user can see the
169-bugs that are associated. This way if there are bugs associated with
170-a branch that the user cannot see, then they are not shown.
171-
172- >>> from canonical.launchpad.interfaces import IPersonSet
173- >>> user = getUtility(IPersonSet).getByEmail('test@canonical.com')
174- >>> bugbranches = getUtility(IBugBranchSet).getBugBranchesForBranches(
175- ... branches, user)
176- >>> for bugbranch in sorted(bugbranches,
177- ... key=lambda b: (b.branch.id, b.bug.id)):
178- ... print "%s <-> %s" % (
179- ... bugbranch.branch.unique_name, bugbranch.bug.id)
180- ~mark/firefox/release-0.9.2 <-> 1
181- ~mark/firefox/release-0.9.2 <-> 4
182-
183-
184-== Getting bug branches associated with multiple bugs ==
185-
186-Sometimes we want to get the associated bug branch links for a set of bugs.
187-The getBugBranchesForBugs method can do this.
188-
189-Firstly we need to get the branches. We'll look up the relationships
190-for bugs 1, 2, 3 and 4.
191-
192- >>> bugtasks = list(getUtility(IBugSet).get(1).bugtasks)
193- >>> bugtasks.extend(getUtility(IBugSet).get(2).bugtasks)
194- >>> bugtasks.extend(getUtility(IBugSet).get(3).bugtasks)
195- >>> bugtasks.extend(getUtility(IBugSet).get(4).bugtasks)
196- >>> bugbranches2 = getUtility(IBugBranchSet).getBugBranchesForBugTasks(
197- ... bugtasks)
198- >>> for bugbranch2 in sorted(bugbranches2,
199- ... key=lambda b: (b.branch.id, b.bug.id)):
200- ... print "%s <-> %s" % (bugbranch2.branch.unique_name, bugbranch2.bug.id)
201- ~name12/firefox/main <-> 1
202- ~name12/firefox/main <-> 4
203- ~mark/firefox/release-0.9.2 <-> 1
204- ~mark/firefox/release-0.9.2 <-> 4
205-
206
207=== modified file 'lib/lp/bugs/doc/bug.txt'
208--- lib/lp/bugs/doc/bug.txt 2010-07-22 12:17:41 +0000
209+++ lib/lp/bugs/doc/bug.txt 2010-07-29 19:50:21 +0000
210@@ -834,39 +834,6 @@
211 >>> firefox_bug.date_last_updated > current_date_last_updated
212 True
213
214-Adding a branch.
215-
216- >>> from lp.code.interfaces.branchlookup import IBranchLookup
217- >>> firefox_bug.linked_branches.count()
218- 0
219-
220- >>> branch_one = getUtility(IBranchLookup).get(1)
221- >>> current_date_last_updated = firefox_bug.date_last_updated
222-
223- >>> bug_branch = firefox_bug.linkBranch(branch_one, foobar)
224-
225- >>> firefox_bug.linked_branches.count()
226- 1
227- >>> firefox_bug.date_last_updated > current_date_last_updated
228- True
229-
230-Editing a branch.
231-
232- >>> from lp.bugs.interfaces.bugbranch import IBugBranch
233-
234- >>> branch_before_modification = Snapshot(
235- ... bug_branch, providing=IBugBranch)
236-
237- >>> bug_branch_changed = ObjectModifiedEvent(
238- ... bug_branch, branch_before_modification, ["status"])
239-
240- >>> current_date_last_updated = firefox_bug.date_last_updated
241-
242- >>> notify(bug_branch_changed)
243-
244- >>> firefox_bug.date_last_updated > current_date_last_updated
245- True
246-
247 Linking to a CVE.
248
249 >>> from lp.bugs.interfaces.cve import ICveSet
250
251=== modified file 'lib/lp/bugs/model/bugbranch.py'
252--- lib/lp/bugs/model/bugbranch.py 2009-07-17 00:26:05 +0000
253+++ lib/lp/bugs/model/bugbranch.py 2010-07-29 19:50:21 +0000
254@@ -18,7 +18,6 @@
255 from canonical.database.constants import UTC_NOW
256 from canonical.database.datetimecol import UtcDateTimeCol
257 from canonical.database.sqlbase import SQLBase, sqlvalues
258-from canonical.database.enumcol import EnumCol
259
260 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
261 from lp.bugs.interfaces.bugbranch import IBugBranch, IBugBranchSet
262
263=== added file 'lib/lp/bugs/tests/test_bugbranch.py'
264--- lib/lp/bugs/tests/test_bugbranch.py 1970-01-01 00:00:00 +0000
265+++ lib/lp/bugs/tests/test_bugbranch.py 2010-07-29 19:50:21 +0000
266@@ -0,0 +1,205 @@
267+# Copyright 2010 Canonical Ltd. This software is licensed under the
268+# GNU Affero General Public License version 3 (see the file LICENSE).
269+
270+from __future__ import with_statement
271+
272+"""Tests for bug-branch linking from the bugs side."""
273+
274+__metaclass__ = type
275+
276+from zope.component import getUtility
277+from zope.security.interfaces import Unauthorized
278+
279+from canonical.testing import DatabaseFunctionalLayer
280+from lp.bugs.model.bugbranch import BugBranch, BugBranchSet
281+from lp.bugs.interfaces.bugbranch import IBugBranch, IBugBranchSet
282+from lp.testing import (
283+ anonymous_logged_in,
284+ celebrity_logged_in,
285+ TestCaseWithFactory,
286+ )
287+
288+
289+class TestBugBranchSet(TestCaseWithFactory):
290+
291+ layer = DatabaseFunctionalLayer
292+
293+ def test_bugbranchset_provides_IBugBranchSet(self):
294+ # BugBranchSet objects provide IBugBranchSet.
295+ self.assertProvides(BugBranchSet(), IBugBranchSet)
296+
297+ def test_getBugBranchesForBranches_no_branches(self):
298+ bug_branches = getUtility(IBugBranchSet)
299+ links = bug_branches.getBugBranchesForBranches(
300+ [], self.factory.makePerson())
301+ self.assertEqual([], list(links))
302+
303+ def test_getBugBranchesForBranches(self):
304+ # IBugBranchSet.getBugBranchesForBranches returns all of the BugBranch
305+ # objects associated with the given branches.
306+ branch_1 = self.factory.makeBranch()
307+ branch_2 = self.factory.makeBranch()
308+ bug_a = self.factory.makeBug()
309+ bug_b = self.factory.makeBug()
310+ self.factory.loginAsAnyone()
311+ link_1 = bug_a.linkBranch(branch_1, self.factory.makePerson())
312+ link_2 = bug_a.linkBranch(branch_2, self.factory.makePerson())
313+ link_3 = bug_b.linkBranch(branch_2, self.factory.makePerson())
314+ self.assertEqual(
315+ set([link_1, link_2, link_3]),
316+ set(getUtility(IBugBranchSet).getBugBranchesForBranches(
317+ [branch_1, branch_2], self.factory.makePerson())))
318+
319+ def test_getBugBranchesForBranches_respects_bug_privacy(self):
320+ # IBugBranchSet.getBugBranchesForBranches returns only the BugBranch
321+ # objects that are visible by the user who is asking for them.
322+ branch = self.factory.makeBranch()
323+ user = self.factory.makePerson()
324+ public_bug = self.factory.makeBug()
325+ private_visible_bug = self.factory.makeBug(private=True)
326+ private_invisible_bug = self.factory.makeBug(private=True)
327+ with celebrity_logged_in('admin'):
328+ public_bug.linkBranch(branch, user)
329+ private_visible_bug.subscribe(user, user)
330+ private_visible_bug.linkBranch(branch, user)
331+ private_invisible_bug.linkBranch(branch, user)
332+ bug_branches = getUtility(IBugBranchSet).getBugBranchesForBranches(
333+ [branch], user)
334+ self.assertEqual(
335+ set([public_bug, private_visible_bug]),
336+ set([link.bug for link in bug_branches]))
337+
338+ def test_getBugBranchesForBugTasks(self):
339+ # IBugBranchSet.getBugBranchesForBugTasks returns all of the BugBranch
340+ # objects associated with the given bug tasks.
341+ bug_a = self.factory.makeBug()
342+ bug_b = self.factory.makeBug()
343+ bugtasks = bug_a.bugtasks + bug_b.bugtasks
344+ branch = self.factory.makeBranch()
345+ self.factory.loginAsAnyone()
346+ link_1 = bug_a.linkBranch(branch, self.factory.makePerson())
347+ link_2 = bug_b.linkBranch(branch, self.factory.makePerson())
348+ found_links = getUtility(IBugBranchSet).getBugBranchesForBugTasks(
349+ bugtasks)
350+ self.assertEqual(set([link_1, link_2]), set(found_links))
351+
352+
353+class TestBugBranch(TestCaseWithFactory):
354+
355+ layer = DatabaseFunctionalLayer
356+
357+ def setUp(self):
358+ super(TestBugBranch, self).setUp()
359+ # Bug branch linking is generally available to any logged in user.
360+ self.factory.loginAsAnyone()
361+
362+ def test_bugbranch_provides_IBugBranch(self):
363+ # BugBranch objects provide IBugBranch.
364+ bug_branch = BugBranch(
365+ branch=self.factory.makeBranch(), bug=self.factory.makeBug(),
366+ registrant=self.factory.makePerson())
367+ self.assertProvides(bug_branch, IBugBranch)
368+
369+ def test_linkBranch_returns_IBugBranch(self):
370+ # Bug.linkBranch returns an IBugBranch linking the bug to the branch.
371+ bug = self.factory.makeBug()
372+ branch = self.factory.makeBranch()
373+ registrant = self.factory.makePerson()
374+ bug_branch = bug.linkBranch(branch, registrant)
375+ self.assertEqual(branch, bug_branch.branch)
376+ self.assertEqual(bug, bug_branch.bug)
377+ self.assertEqual(registrant, bug_branch.registrant)
378+
379+ def test_bug_start_with_no_linked_branches(self):
380+ # Bugs have a linked_branches attribute which is initially an empty
381+ # collection.
382+ bug = self.factory.makeBug()
383+ self.assertEqual([], list(bug.linked_branches))
384+
385+ def test_linkBranch_adds_to_linked_branches(self):
386+ # Bug.linkBranch populates the Bug.linked_branches with the created
387+ # BugBranch object.
388+ bug = self.factory.makeBug()
389+ branch = self.factory.makeBranch()
390+ bug_branch = bug.linkBranch(branch, self.factory.makePerson())
391+ self.assertEqual([bug_branch], list(bug.linked_branches))
392+
393+ def test_linking_branch_twice_returns_same_IBugBranch(self):
394+ # Calling Bug.linkBranch twice with the same parameters returns the
395+ # same object.
396+ bug = self.factory.makeBug()
397+ branch = self.factory.makeBranch()
398+ bug_branch = bug.linkBranch(branch, self.factory.makePerson())
399+ bug_branch_2 = bug.linkBranch(branch, self.factory.makePerson())
400+ self.assertEqual(bug_branch, bug_branch_2)
401+
402+ def test_linking_branch_twice_different_registrants(self):
403+ # Calling Bug.linkBranch twice with the branch but different
404+ # registrants returns the existing bug branch object rather than
405+ # creating a new one.
406+ bug = self.factory.makeBug()
407+ branch = self.factory.makeBranch()
408+ bug_branch = bug.linkBranch(branch, self.factory.makePerson())
409+ bug_branch_2 = bug.linkBranch(branch, self.factory.makePerson())
410+ self.assertEqual(bug_branch, bug_branch_2)
411+
412+ def test_bug_has_no_branches(self):
413+ # Bug.hasBranch returns False for any branch that it is not linked to.
414+ bug = self.factory.makeBug()
415+ self.assertFalse(bug.hasBranch(self.factory.makeBranch()))
416+
417+ def test_bug_has_branch(self):
418+ # Bug.hasBranch returns False for any branch that it is linked to.
419+ bug = self.factory.makeBug()
420+ branch = self.factory.makeBranch()
421+ bug.linkBranch(branch, self.factory.makePerson())
422+ self.assertTrue(bug.hasBranch(branch))
423+
424+ def test_unlink_branch(self):
425+ # Bug.unlinkBranch removes the bug<->branch link.
426+ bug = self.factory.makeBug()
427+ branch = self.factory.makeBranch()
428+ bug.linkBranch(branch, self.factory.makePerson())
429+ bug.unlinkBranch(branch, self.factory.makePerson())
430+ self.assertEqual([], list(bug.linked_branches))
431+ self.assertFalse(bug.hasBranch(branch))
432+
433+ def test_unlink_not_linked_branch(self):
434+ # When unlinkBranch is called with a branch that isn't already linked,
435+ # nothing discernable happens.
436+ bug = self.factory.makeBug()
437+ branch = self.factory.makeBranch()
438+ bug.unlinkBranch(branch, self.factory.makePerson())
439+ self.assertEqual([], list(bug.linked_branches))
440+ self.assertFalse(bug.hasBranch(branch))
441+
442+ def test_the_unwashed_cannot_link_branch_to_private_bug(self):
443+ # Those who cannot see a bug are forbidden to link a branch to it.
444+ bug = self.factory.makeBug(private=True)
445+ self.assertRaises(Unauthorized, getattr, bug, 'linkBranch')
446+
447+ def test_the_unwashed_cannot_unlink_branch_from_private_bug(self):
448+ # Those who cannot see a bug are forbidden to unlink branches from it.
449+ bug = self.factory.makeBug(private=True)
450+ self.assertRaises(Unauthorized, getattr, bug, 'unlinkBranch')
451+
452+ def test_anonymous_users_cannot_link_branches(self):
453+ # Anonymous users cannot link branches to bugs, even public bugs.
454+ bug = self.factory.makeBug()
455+ with anonymous_logged_in():
456+ self.assertRaises(Unauthorized, getattr, bug, 'linkBranch')
457+
458+ def test_anonymous_users_cannot_unlink_branches(self):
459+ # Anonymous users cannot unlink branches from bugs, even public bugs.
460+ bug = self.factory.makeBug()
461+ with anonymous_logged_in():
462+ self.assertRaises(Unauthorized, getattr, bug, 'unlinkBranch')
463+
464+ def test_adding_branch_changes_date_last_updated(self):
465+ # Adding a branch to a bug changes IBug.date_last_updated.
466+ bug = self.factory.makeBug()
467+ last_updated = bug.date_last_updated
468+ branch = self.factory.makeBranch()
469+ self.factory.loginAsAnyone()
470+ bug.linkBranch(branch, self.factory.makePerson())
471+ self.assertTrue(bug.date_last_updated > last_updated)