Merge lp:~deryck/launchpad/better-testing-for-status-changes into lp:launchpad
- better-testing-for-status-changes
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Deryck Hodge | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 11754 | ||||
Proposed branch: | lp:~deryck/launchpad/better-testing-for-status-changes | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
534 lines (+366/-146) 2 files modified
lib/lp/bugs/doc/bugtask-status-changes.txt (+51/-131) lib/lp/bugs/tests/test_bugtask_status.py (+315/-15) |
||||
To merge this branch: | bzr merge lp:~deryck/launchpad/better-testing-for-status-changes | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Abel Deuring (community) | code | Approve | |
Review via email: mp+38552@code.launchpad.net |
Commit message
Refactor doctest for bugtask status changes into separate unit test and documentation.
Description of the change
This branch is the first toward a fix for Bug #126516, or more specifically for a fix to limit transitioning away from Fix Released status. Before this branch the tests for bugtask status changes was a mix of a unit test and doctest, both living under lp.bugs.tests.
The branch refactors that mess, opting to do a complete unit test of BugTask.
To test, run:
./bin/test -cvvt bugtask-
./bin/test -cvvt test_bugtask_status
Thanks for the review!
Abel Deuring (adeuring) wrote : | # |
Abel Deuring (adeuring) wrote : | # |
Hi Deryck,
thanks for the refactoring. r=me.
Just a few nitpicks:
could you add TestCases for the celebrities bug_watch_updater,
bug_importer, janitor?
> +class TestBugTaskStat
> + """Base class used to test privileged users and status transitions."""
> +
> + layer = LaunchpadFuncti
> +
> + def setUp(self):
> + super(TestBugTa
> + # Creation of task and target are deferred to subclasses.
> + self.task = None
> + self.person = None
> + self.makePerson
> +
> + def makePersonAndTa
> + """Create a bug task and privileged person for this task.
> +
> + This method is user by subclasses to correctly setup
> + each test.
> + """
I think this should be something like "is (overloaded|
subclasses"
cheers
Abel
Preview Diff
1 | === renamed file 'lib/lp/bugs/tests/test_bugtask_status.txt' => 'lib/lp/bugs/doc/bugtask-status-changes.txt' |
2 | --- lib/lp/bugs/tests/test_bugtask_status.txt 2010-10-09 16:36:22 +0000 |
3 | +++ lib/lp/bugs/doc/bugtask-status-changes.txt 2010-10-19 13:36:54 +0000 |
4 | @@ -1,137 +1,57 @@ |
5 | -= Setting Bug Statuses = |
6 | - |
7 | - >>> from canonical.launchpad.interfaces import ( |
8 | - ... CreateBugParams, IPersonSet, IProductSet) |
9 | +Changing Bug Task Status |
10 | +======================== |
11 | + |
12 | +Restrictions |
13 | +------------ |
14 | + |
15 | +There are a few simple rules around who can change the status of a |
16 | +bug task. There are three statuses that can only be set by either |
17 | +the project registrant or the bug supervisor: |
18 | + |
19 | + * Won't Fix |
20 | + * Expired |
21 | + * Triaged |
22 | + |
23 | + >>> owner = factory.makePerson() |
24 | + >>> product = factory.makeProduct(owner=owner) |
25 | + >>> bugtask = factory.makeBugTask(target=product) |
26 | + >>> user = factory.makePerson() |
27 | + |
28 | >>> from lp.bugs.interfaces.bugtask import BugTaskStatus |
29 | - |
30 | - >>> firefox = getUtility(IProductSet).getByName('firefox') |
31 | - >>> nopriv_user = getUtility(IPersonSet).getByName('no-priv') |
32 | - >>> login('foo.bar@canonical.com') |
33 | - >>> firefox.setBugSupervisor(nopriv_user, nopriv_user) |
34 | - >>> login('no-priv@canonical.com') |
35 | - >>> bug_params = CreateBugParams( |
36 | - ... nopriv_user, 'Test bug', 'Something') |
37 | - >>> firefox_bug = firefox.createBug(bug_params) |
38 | - |
39 | -Bug Supervisors can transition bugs to the Won't Fix, Expired and |
40 | -Triaged statuses. |
41 | - |
42 | - >>> [firefox_bugtask] = firefox_bug.bugtasks |
43 | - >>> firefox_bugtask.transitionToStatus( |
44 | - ... BugTaskStatus.WONTFIX, nopriv_user) |
45 | - >>> print firefox_bugtask.status.title |
46 | - Won't Fix |
47 | - |
48 | - >>> firefox_bugtask.transitionToStatus( |
49 | - ... BugTaskStatus.EXPIRED, nopriv_user) |
50 | - >>> print firefox_bugtask.status.title |
51 | - Expired |
52 | - |
53 | - >>> firefox_bugtask.transitionToStatus( |
54 | - ... BugTaskStatus.TRIAGED, nopriv_user) |
55 | - >>> print firefox_bugtask.status.title |
56 | - Triaged |
57 | - |
58 | -The product registrant can transition to the Won't Fix, Expired and |
59 | -Triaged statuses too. |
60 | - |
61 | - >>> firefox_bugtask.transitionToStatus( |
62 | - ... BugTaskStatus.CONFIRMED, nopriv_user) |
63 | - >>> print firefox_bugtask.status.title |
64 | - Confirmed |
65 | - |
66 | - >>> firefox.owner.inTeam(firefox.bug_supervisor) |
67 | - False |
68 | - |
69 | - >>> firefox_bugtask.transitionToStatus( |
70 | - ... BugTaskStatus.WONTFIX, firefox.owner) |
71 | - >>> print firefox_bugtask.status.title |
72 | - Won't Fix |
73 | - |
74 | - >>> firefox_bugtask.transitionToStatus( |
75 | - ... BugTaskStatus.EXPIRED, firefox.owner) |
76 | - >>> print firefox_bugtask.status.title |
77 | - Expired |
78 | - |
79 | - >>> firefox_bugtask.transitionToStatus( |
80 | - ... BugTaskStatus.TRIAGED, firefox.owner) |
81 | - >>> print firefox_bugtask.status.title |
82 | - Triaged |
83 | - |
84 | -Users who are not bug supervisors or product registrants cannot |
85 | -transition the status to Won't Fix or Triaged. The option is not |
86 | -exposed in the UI, but we also enforce this rule at the database level |
87 | -to ensure that all call sites adhere to this. |
88 | - |
89 | - >>> login('foo.bar@canonical.com') |
90 | - >>> firefox.setBugSupervisor(None, None) |
91 | - |
92 | - >>> login('no-priv@canonical.com') |
93 | - |
94 | - >>> firefox_bugtask.transitionToStatus( |
95 | - ... BugTaskStatus.WONTFIX, nopriv_user) |
96 | - Traceback (most recent call last): |
97 | - ... |
98 | - UserCannotEditBugTaskStatus: Only Bug Supervisors may change status to Won't Fix. |
99 | - |
100 | - >>> firefox_bugtask.transitionToStatus( |
101 | - ... BugTaskStatus.EXPIRED, nopriv_user) |
102 | - Traceback (most recent call last): |
103 | - ... |
104 | - UserCannotEditBugTaskStatus: Only Bug Supervisors may change status to Expired. |
105 | - |
106 | - >>> firefox_bugtask.transitionToStatus( |
107 | - ... BugTaskStatus.TRIAGED, nopriv_user) |
108 | - Traceback (most recent call last): |
109 | - ... |
110 | - UserCannotEditBugTaskStatus: Only Bug Supervisors may change status to Triaged. |
111 | - |
112 | -Users who are not bug supervisors or product registrants cannot |
113 | -transition the status from Won't Fix to anything else. |
114 | - |
115 | - >>> login('foo.bar@canonical.com') |
116 | - >>> foo_bar = getUtility(ILaunchBag).user |
117 | - >>> firefox.setBugSupervisor(foo_bar, foo_bar) |
118 | - >>> firefox_bugtask.transitionToStatus( |
119 | - ... BugTaskStatus.WONTFIX, foo_bar) |
120 | - |
121 | - >>> login('no-priv@canonical.com') |
122 | - >>> firefox_bugtask.transitionToStatus( |
123 | - ... BugTaskStatus.NEW, nopriv_user) |
124 | - Traceback (most recent call last): |
125 | - ... |
126 | - UserCannotEditBugTaskStatus: Only Bug Supervisors may change status to New. |
127 | + >>> login_person(owner) |
128 | + >>> bugtask.transitionToStatus(BugTaskStatus.WONTFIX, owner) |
129 | + >>> print bugtask.status.title |
130 | + Won't Fix |
131 | + |
132 | +Regular users of Launchpad cannot transition a bug task to any of |
133 | +these statuses. |
134 | + |
135 | +An additional restraint is added to Won't Fix. Only the product |
136 | +registrant or bug supervisor can change from this status to any |
137 | +other status. |
138 | + |
139 | + >>> login_person(user) |
140 | + >>> bugtask.transitionToStatus(BugTaskStatus.CONFIRMED, user) |
141 | + Traceback (most recent call last): |
142 | + ... |
143 | + UserCannotEditBugTaskStatus... |
144 | + |
145 | +This is fully tested in |
146 | +lp.bugs.tests.test_bugtask_status.TestBugTaskStatusSetting. |
147 | + |
148 | +Testing for Permission |
149 | +---------------------- |
150 | |
151 | The method IBugTask.canTransitionToStatus comes in handy here. It |
152 | tells us if a transition to a status is permitted. It is *not* a |
153 | -dry-run of transitionToStatus, but is good enough and fast enough to |
154 | -be used by UI code, e.g. to display only those statuses to which a |
155 | -user can transition a particular bugtask. |
156 | - |
157 | - >>> login('foo.bar@canonical.com') |
158 | - >>> firefox_bugtask.transitionToStatus( |
159 | - ... BugTaskStatus.TRIAGED, foo_bar) |
160 | - |
161 | - >>> login('no-priv@canonical.com') |
162 | - |
163 | - >>> firefox_bugtask.canTransitionToStatus( |
164 | - ... BugTaskStatus.WONTFIX, nopriv_user) |
165 | - False |
166 | - |
167 | - >>> firefox_bugtask.canTransitionToStatus( |
168 | - ... BugTaskStatus.TRIAGED, nopriv_user) |
169 | - False |
170 | - |
171 | - >>> firefox_bugtask.canTransitionToStatus( |
172 | - ... BugTaskStatus.INCOMPLETE, nopriv_user) |
173 | +dry-run of IBugTask.transitionToStatus, but is good enough and fast |
174 | +enough to be used by UI code, e.g. to display only those statuses to |
175 | +which a user can transition a particular bugtask. |
176 | + |
177 | + >>> bugtask.canTransitionToStatus(BugTaskStatus.TRIAGED, owner) |
178 | True |
179 | - |
180 | - >>> login('foo.bar@canonical.com') |
181 | - >>> firefox_bugtask.transitionToStatus( |
182 | - ... BugTaskStatus.WONTFIX, getUtility(ILaunchBag).user) |
183 | - |
184 | - >>> login('no-priv@canonical.com') |
185 | - |
186 | - >>> firefox_bugtask.canTransitionToStatus( |
187 | - ... BugTaskStatus.NEW, nopriv_user) |
188 | + >>> bugtask.canTransitionToStatus(BugTaskStatus.TRIAGED, user) |
189 | False |
190 | + |
191 | +This method is fully tested in |
192 | +lp.bugs.tests.test_bugtask_status.TestCanTransitionToStatus. |
193 | |
194 | === modified file 'lib/lp/bugs/tests/test_bugtask_status.py' |
195 | --- lib/lp/bugs/tests/test_bugtask_status.py 2010-10-04 19:50:45 +0000 |
196 | +++ lib/lp/bugs/tests/test_bugtask_status.py 2010-10-19 13:36:54 +0000 |
197 | @@ -1,22 +1,322 @@ |
198 | # Copyright 2009 Canonical Ltd. This software is licensed under the |
199 | # GNU Affero General Public License version 3 (see the file LICENSE). |
200 | |
201 | -"""Test for choosing the request and publication.""" |
202 | +"""Tests for bug task status transitions.""" |
203 | |
204 | __metaclass__ = type |
205 | |
206 | -from canonical.launchpad.testing.systemdocs import ( |
207 | - LayeredDocFileSuite, |
208 | - setUp, |
209 | - tearDown, |
210 | +from zope.component import getUtility |
211 | +from zope.security.proxy import removeSecurityProxy |
212 | + |
213 | +from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
214 | +from canonical.testing.layers import LaunchpadFunctionalLayer |
215 | +from lp.bugs.interfaces.bugtask import UserCannotEditBugTaskStatus |
216 | +from lp.bugs.model.bugtask import BugTaskStatus |
217 | +from lp.testing import ( |
218 | + person_logged_in, |
219 | + TestCaseWithFactory, |
220 | ) |
221 | -from canonical.testing.layers import LaunchpadFunctionalLayer |
222 | - |
223 | - |
224 | -def test_suite(): |
225 | - suite = LayeredDocFileSuite( |
226 | - 'test_bugtask_status.txt', |
227 | - layer=LaunchpadFunctionalLayer, setUp=setUp, tearDown=tearDown, |
228 | - ) |
229 | - return suite |
230 | - |
231 | + |
232 | + |
233 | +class TestBugTaskStatusTransitionForUser(TestCaseWithFactory): |
234 | + """Test bugtask status transitions for a regular logged in user.""" |
235 | + |
236 | + layer = LaunchpadFunctionalLayer |
237 | + |
238 | + def setUp(self): |
239 | + super(TestBugTaskStatusTransitionForUser, self).setUp() |
240 | + self.user = self.factory.makePerson() |
241 | + self.task = self.factory.makeBugTask() |
242 | + |
243 | + def test_user_transition_all_statuses(self): |
244 | + # A regular user should not be able to set statuses in |
245 | + # BUG_SUPERVISOR_BUGTASK_STATUSES, but can set any |
246 | + # other status. |
247 | + self.assertEqual(self.task.status, BugTaskStatus.NEW) |
248 | + with person_logged_in(self.user): |
249 | + self.assertRaises( |
250 | + UserCannotEditBugTaskStatus, self.task.transitionToStatus, |
251 | + BugTaskStatus.WONTFIX, self.user) |
252 | + self.assertRaises( |
253 | + UserCannotEditBugTaskStatus, self.task.transitionToStatus, |
254 | + BugTaskStatus.EXPIRED, self.user) |
255 | + self.assertRaises( |
256 | + UserCannotEditBugTaskStatus, self.task.transitionToStatus, |
257 | + BugTaskStatus.TRIAGED, self.user) |
258 | + self.task.transitionToStatus(BugTaskStatus.NEW, self.user) |
259 | + self.assertEqual(self.task.status, BugTaskStatus.NEW) |
260 | + self.task.transitionToStatus( |
261 | + BugTaskStatus.INCOMPLETE, self.user) |
262 | + self.assertEqual(self.task.status, BugTaskStatus.INCOMPLETE) |
263 | + self.task.transitionToStatus(BugTaskStatus.OPINION, self.user) |
264 | + self.assertEqual(self.task.status, BugTaskStatus.OPINION) |
265 | + self.task.transitionToStatus(BugTaskStatus.INVALID, self.user) |
266 | + self.assertEqual(self.task.status, BugTaskStatus.INVALID) |
267 | + self.task.transitionToStatus(BugTaskStatus.CONFIRMED, self.user) |
268 | + self.assertEqual(self.task.status, BugTaskStatus.CONFIRMED) |
269 | + self.task.transitionToStatus( |
270 | + BugTaskStatus.INPROGRESS, self.user) |
271 | + self.assertEqual(self.task.status, BugTaskStatus.INPROGRESS) |
272 | + self.task.transitionToStatus( |
273 | + BugTaskStatus.FIXCOMMITTED, self.user) |
274 | + self.assertEqual(self.task.status, BugTaskStatus.FIXCOMMITTED) |
275 | + self.task.transitionToStatus( |
276 | + BugTaskStatus.FIXRELEASED, self.user) |
277 | + self.assertEqual(self.task.status, BugTaskStatus.FIXRELEASED) |
278 | + |
279 | + def test_user_cannot_unset_wont_fix_status(self): |
280 | + # A regular user should not be able to transition a bug away |
281 | + # from Won't Fix. |
282 | + removeSecurityProxy(self.task).status = BugTaskStatus.WONTFIX |
283 | + with person_logged_in(self.user): |
284 | + self.assertRaises( |
285 | + UserCannotEditBugTaskStatus, self.task.transitionToStatus, |
286 | + BugTaskStatus.CONFIRMED, self.user) |
287 | + |
288 | + def test_user_canTransitionToStatus(self): |
289 | + # Regular user cannot transition to BUG_SUPERVISOR_BUGTASK_STATUSES, |
290 | + # but can transition to any other status. |
291 | + self.assertEqual( |
292 | + self.task.canTransitionToStatus( |
293 | + BugTaskStatus.WONTFIX, self.user), |
294 | + False) |
295 | + self.assertEqual( |
296 | + self.task.canTransitionToStatus( |
297 | + BugTaskStatus.EXPIRED, self.user), |
298 | + False) |
299 | + self.assertEqual( |
300 | + self.task.canTransitionToStatus( |
301 | + BugTaskStatus.TRIAGED, self.user), |
302 | + False) |
303 | + self.assertEqual( |
304 | + self.task.canTransitionToStatus( |
305 | + BugTaskStatus.NEW, self.user), |
306 | + True) |
307 | + self.assertEqual( |
308 | + self.task.canTransitionToStatus( |
309 | + BugTaskStatus.INCOMPLETE, self.user), True) |
310 | + self.assertEqual( |
311 | + self.task.canTransitionToStatus( |
312 | + BugTaskStatus.OPINION, self.user), |
313 | + True) |
314 | + self.assertEqual( |
315 | + self.task.canTransitionToStatus( |
316 | + BugTaskStatus.INVALID, self.user), |
317 | + True) |
318 | + self.assertEqual( |
319 | + self.task.canTransitionToStatus( |
320 | + BugTaskStatus.CONFIRMED, self.user), |
321 | + True) |
322 | + self.assertEqual( |
323 | + self.task.canTransitionToStatus( |
324 | + BugTaskStatus.INPROGRESS, self.user), |
325 | + True) |
326 | + self.assertEqual( |
327 | + self.task.canTransitionToStatus( |
328 | + BugTaskStatus.FIXCOMMITTED, self.user), |
329 | + True) |
330 | + self.assertEqual( |
331 | + self.task.canTransitionToStatus( |
332 | + BugTaskStatus.FIXRELEASED, self.user), |
333 | + True) |
334 | + |
335 | + def test_user_canTransitionToStatus_from_wontfix(self): |
336 | + # A regular user cannot transition away from Won't Fix, |
337 | + # so canTransitionToStatus should return False. |
338 | + removeSecurityProxy(self.task).status = BugTaskStatus.WONTFIX |
339 | + self.assertEqual( |
340 | + self.task.canTransitionToStatus( |
341 | + BugTaskStatus.NEW, self.user), |
342 | + False) |
343 | + |
344 | + |
345 | +class TestBugTaskStatusTransitionForPrivilegedUserBase: |
346 | + """Base class used to test privileged users and status transitions.""" |
347 | + |
348 | + layer = LaunchpadFunctionalLayer |
349 | + |
350 | + def setUp(self): |
351 | + super(TestBugTaskStatusTransitionForPrivilegedUserBase, self).setUp() |
352 | + # Creation of task and target are deferred to subclasses. |
353 | + self.task = None |
354 | + self.person = None |
355 | + self.makePersonAndTask() |
356 | + |
357 | + def makePersonAndTask(self): |
358 | + """Create a bug task and privileged person for this task. |
359 | + |
360 | + This method is implemented by subclasses to correctly setup |
361 | + each test. |
362 | + """ |
363 | + raise NotImplementedError(self.makePersonAndTask) |
364 | + |
365 | + def test_privileged_user_transition_any_status(self): |
366 | + # Privileged users (like owner or bug supervisor) should |
367 | + # be able to set any status. |
368 | + with person_logged_in(self.person): |
369 | + self.task.transitionToStatus(BugTaskStatus.WONTFIX, self.person) |
370 | + self.assertEqual(self.task.status, BugTaskStatus.WONTFIX) |
371 | + self.task.transitionToStatus(BugTaskStatus.EXPIRED, self.person) |
372 | + self.assertEqual(self.task.status, BugTaskStatus.EXPIRED) |
373 | + self.task.transitionToStatus(BugTaskStatus.TRIAGED, self.person) |
374 | + self.assertEqual(self.task.status, BugTaskStatus.TRIAGED) |
375 | + self.task.transitionToStatus(BugTaskStatus.NEW, self.person) |
376 | + self.assertEqual(self.task.status, BugTaskStatus.NEW) |
377 | + self.task.transitionToStatus( |
378 | + BugTaskStatus.INCOMPLETE, self.person) |
379 | + self.assertEqual(self.task.status, BugTaskStatus.INCOMPLETE) |
380 | + self.task.transitionToStatus(BugTaskStatus.OPINION, self.person) |
381 | + self.assertEqual(self.task.status, BugTaskStatus.OPINION) |
382 | + self.task.transitionToStatus(BugTaskStatus.INVALID, self.person) |
383 | + self.assertEqual(self.task.status, BugTaskStatus.INVALID) |
384 | + self.task.transitionToStatus(BugTaskStatus.CONFIRMED, self.person) |
385 | + self.assertEqual(self.task.status, BugTaskStatus.CONFIRMED) |
386 | + self.task.transitionToStatus( |
387 | + BugTaskStatus.INPROGRESS, self.person) |
388 | + self.assertEqual(self.task.status, BugTaskStatus.INPROGRESS) |
389 | + self.task.transitionToStatus( |
390 | + BugTaskStatus.FIXCOMMITTED, self.person) |
391 | + self.assertEqual(self.task.status, BugTaskStatus.FIXCOMMITTED) |
392 | + self.task.transitionToStatus( |
393 | + BugTaskStatus.FIXRELEASED, self.person) |
394 | + self.assertEqual(self.task.status, BugTaskStatus.FIXRELEASED) |
395 | + |
396 | + def test_privileged_user_can_unset_wont_fix_status(self): |
397 | + # Privileged users can transition away from Won't Fix. |
398 | + removeSecurityProxy(self.task).status = BugTaskStatus.WONTFIX |
399 | + with person_logged_in(self.person): |
400 | + self.task.transitionToStatus(BugTaskStatus.CONFIRMED, self.person) |
401 | + self.assertEqual(self.task.status, BugTaskStatus.CONFIRMED) |
402 | + |
403 | + def test_privileged_user_canTransitionToStatus(self): |
404 | + # Privileged users (like owner or bug supervisor) should |
405 | + # be able to set any status, so canTransitionToStatus should |
406 | + # always return True. |
407 | + self.assertEqual( |
408 | + self.task.canTransitionToStatus( |
409 | + BugTaskStatus.WONTFIX, self.person), |
410 | + True) |
411 | + self.assertEqual( |
412 | + self.task.canTransitionToStatus( |
413 | + BugTaskStatus.EXPIRED, self.person), |
414 | + True) |
415 | + self.assertEqual( |
416 | + self.task.canTransitionToStatus( |
417 | + BugTaskStatus.TRIAGED, self.person), |
418 | + True) |
419 | + self.assertEqual( |
420 | + self.task.canTransitionToStatus( |
421 | + BugTaskStatus.NEW, self.person), |
422 | + True) |
423 | + self.assertEqual( |
424 | + self.task.canTransitionToStatus( |
425 | + BugTaskStatus.INCOMPLETE, self.person), |
426 | + True) |
427 | + self.assertEqual( |
428 | + self.task.canTransitionToStatus( |
429 | + BugTaskStatus.OPINION, self.person), |
430 | + True) |
431 | + self.assertEqual( |
432 | + self.task.canTransitionToStatus( |
433 | + BugTaskStatus.INVALID, self.person), |
434 | + True) |
435 | + self.assertEqual( |
436 | + self.task.canTransitionToStatus( |
437 | + BugTaskStatus.CONFIRMED, self.person), |
438 | + True) |
439 | + self.assertEqual( |
440 | + self.task.canTransitionToStatus( |
441 | + BugTaskStatus.INPROGRESS, self.person), |
442 | + True) |
443 | + self.assertEqual( |
444 | + self.task.canTransitionToStatus( |
445 | + BugTaskStatus.FIXCOMMITTED, self.person), |
446 | + True) |
447 | + self.assertEqual( |
448 | + self.task.canTransitionToStatus( |
449 | + BugTaskStatus.FIXRELEASED, self.person), |
450 | + True) |
451 | + |
452 | + def test_privileged_user_canTransitionToStatus_from_wontfix(self): |
453 | + # A privileged user can transition away from Won't Fix, so |
454 | + # canTransitionToStatus should return True. |
455 | + removeSecurityProxy(self.task).status = BugTaskStatus.WONTFIX |
456 | + self.assertEqual( |
457 | + self.task.canTransitionToStatus( |
458 | + BugTaskStatus.NEW, self.person), |
459 | + True) |
460 | + |
461 | + |
462 | +class TestBugTaskStatusTransitionOwnerPerson( |
463 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
464 | + """Tests to ensure owner person can transition to any status..""" |
465 | + |
466 | + def makePersonAndTask(self): |
467 | + self.person = self.factory.makePerson() |
468 | + self.product = self.factory.makeProduct(owner=self.person) |
469 | + self.task = self.factory.makeBugTask(target=self.product) |
470 | + |
471 | + |
472 | +class TestBugTaskStatusTransitionOwnerTeam( |
473 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
474 | + """Tests to ensure owner team can transition to any status..""" |
475 | + |
476 | + def makePersonAndTask(self): |
477 | + self.person = self.factory.makePerson() |
478 | + self.team = self.factory.makeTeam(members=[self.person]) |
479 | + self.product = self.factory.makeProduct(owner=self.team) |
480 | + self.task = self.factory.makeBugTask(target=self.product) |
481 | + |
482 | + |
483 | +class TestBugTaskStatusTransitionBugSupervisorPerson( |
484 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
485 | + """Tests to ensure bug supervisor person can transition to any status.""" |
486 | + |
487 | + def makePersonAndTask(self): |
488 | + self.owner = self.factory.makePerson() |
489 | + self.person = self.factory.makePerson() |
490 | + self.product = self.factory.makeProduct(owner=self.owner) |
491 | + self.task = self.factory.makeBugTask(target=self.product) |
492 | + with person_logged_in(self.owner): |
493 | + self.product.setBugSupervisor(self.person, self.person) |
494 | + |
495 | + |
496 | +class TestBugTaskStatusTransitionBugSupervisorTeamMember( |
497 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
498 | + """Tests to ensure bug supervisor team can transition to any status.""" |
499 | + |
500 | + def makePersonAndTask(self): |
501 | + self.owner = self.factory.makePerson() |
502 | + self.person = self.factory.makePerson() |
503 | + self.team = self.factory.makeTeam(members=[self.person]) |
504 | + self.product = self.factory.makeProduct(owner=self.owner) |
505 | + self.task = self.factory.makeBugTask(target=self.product) |
506 | + with person_logged_in(self.owner): |
507 | + self.product.setBugSupervisor(self.team, self.team) |
508 | + |
509 | + |
510 | +class TestBugTaskStatusTransitionBugWatchUpdater( |
511 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
512 | + """Tests to ensure bug_watch_updater can transition to any status.""" |
513 | + |
514 | + def makePersonAndTask(self): |
515 | + self.person = getUtility(ILaunchpadCelebrities).bug_watch_updater |
516 | + self.task = self.factory.makeBugTask() |
517 | + |
518 | + |
519 | +class TestBugTaskStatusTransitionBugImporter( |
520 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
521 | + """Tests to ensure bug_importer can transition to any status.""" |
522 | + |
523 | + def makePersonAndTask(self): |
524 | + self.person = getUtility(ILaunchpadCelebrities).bug_importer |
525 | + self.task = self.factory.makeBugTask() |
526 | + |
527 | + |
528 | +class TestBugTaskStatusTransitionJanitor( |
529 | + TestBugTaskStatusTransitionForPrivilegedUserBase, TestCaseWithFactory): |
530 | + """Tests to ensure lp janitor can transition to any status.""" |
531 | + |
532 | + def makePersonAndTask(self): |
533 | + self.person = getUtility(ILaunchpadCelebrities).janitor |
534 | + self.task = self.factory.makeBugTask() |
(17:52:07) adeuring: deryck: I think it might make sense to change the test setup so that the product owner is not a member of the bug supervisor team; right now, the term "or user.inTeam( pillar. owner)" in canTransitionTo Status( ) is not executed bug_watch_ updater, celebrities. bug_importer, celebrities. janitor. You could add these tests quickly by definig a base class for tests of "extended permissions", where you do not define the user who is tested, then derive the "real" test classes for supervisor, owner and the celebrities.
(17:52:53) deryck: adeuring, ok, that's a good idea. I can do that.
(17:53:07) adeuring: deryck: thanks! another suggestion, before you start ;)
(17:53:16) deryck: sure
(17:55:28) salgado heißt jetzt salgado-lunch
(17:55:30) adeuring: deryck: you don't test at all for celebrities.
(17:55:45) adeuring: That should make the tests a bit shorter and more comprehensive
(17:57:44) deryck: sure, I like that idea. I can do that, too.
(17:57:59) adeuring: deryck: cool, thanks!