Merge lp:~jml/launchpad/branch-sample-data-unit-tests into lp:launchpad
- branch-sample-data-unit-tests
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Robert Collins |
Approved revision: | no longer in the source branch. |
Merged at revision: | 11124 |
Proposed branch: | lp:~jml/launchpad/branch-sample-data-unit-tests |
Merge into: | lp:launchpad |
Prerequisite: | lp:~jml/launchpad/more-login-helpers |
Diff against target: |
696 lines (+159/-132) 9 files modified
database/schema/Makefile (+2/-2) lib/canonical/launchpad/scripts/tests/test_garbo.py (+8/-1) lib/canonical/launchpad/tests/test_launchpadlib.py (+13/-10) lib/lp/code/browser/tests/test_branch.py (+9/-16) lib/lp/code/interfaces/codeimportjob.py (+0/-2) lib/lp/code/model/tests/test_codeimportjob.py (+67/-96) lib/lp/testing/factory.py (+8/-5) lib/lp/testing/sampledata.py (+18/-0) lib/lp/testing/tests/test_factory.py (+34/-0) |
To merge this branch: | bzr merge lp:~jml/launchpad/branch-sample-data-unit-tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Collins (community) | Approve | ||
Review via email: mp+29652@code.launchpad.net |
Commit message
Fix some unit tests to not need sample data. Add "sampledata" module and tests for Launchpad object factory.
Description of the change
This branch fixes up a bunch of unit tests to not use sample data.
The tests that I've changed are tests that would fail if all branch-related sample data were removed.
There's also a new "lp.testing.
I have also used this branch as an opportunity to start testing the Launchpad object factory. I haven't written complete tests, but I have written tests to cover the changes I made. Now that tests exists, I suggest that we insist on tests for any changes made to the factory.
There are some incidental cleanups:
* Change the sampledata header to have the correct copyright date, and change the Makefile to generate the correct copyright date.
* Many tests changed to use DatabaseFunctio
* Removed "verifyObject" from the lp.testing namespace. I have no idea why it was there in the first place.
Preview Diff
1 | === modified file 'database/schema/Makefile' |
2 | --- database/schema/Makefile 2010-03-26 07:37:50 +0000 |
3 | +++ database/schema/Makefile 2010-07-13 10:02:50 +0000 |
4 | @@ -1,4 +1,4 @@ |
5 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
6 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
7 | # GNU Affero General Public License version 3 (see the file LICENSE). |
8 | # |
9 | # Quick hack makefile to (re)create the Launchpad database. |
10 | @@ -42,7 +42,7 @@ |
11 | # The command we use to drop (if exists) and recreate a database. |
12 | CREATEDB=${PYTHON} ../../utilities/pgmassacre.py -t |
13 | |
14 | -HEADER="-- Copyright 2009 Canonical Ltd. This software is licensed under \ |
15 | +HEADER="-- Copyright 2010 Canonical Ltd. This software is licensed under \ |
16 | the\n-- GNU Affero General Public License version 3 (see the file \ |
17 | LICENSE)." |
18 | |
19 | |
20 | === modified file 'lib/canonical/launchpad/scripts/tests/test_garbo.py' |
21 | --- lib/canonical/launchpad/scripts/tests/test_garbo.py 2010-05-26 01:48:12 +0000 |
22 | +++ lib/canonical/launchpad/scripts/tests/test_garbo.py 2010-07-13 10:02:50 +0000 |
23 | @@ -175,11 +175,18 @@ |
24 | results_to_keep_count = ( |
25 | config.codeimport.consecutive_failure_limit - 1) |
26 | |
27 | + LaunchpadZopelessLayer.switchDbUser('testadmin') |
28 | + code_import_id = self.factory.makeCodeImport().id |
29 | + machine_id = self.factory.makeCodeImportMachine().id |
30 | + requester_id = self.factory.makePerson().id |
31 | + transaction.commit() |
32 | + |
33 | def new_code_import_result(timestamp): |
34 | LaunchpadZopelessLayer.switchDbUser('testadmin') |
35 | CodeImportResult( |
36 | date_created=timestamp, |
37 | - code_importID=1, machineID=1, requesting_userID=1, |
38 | + code_importID=code_import_id, machineID=machine_id, |
39 | + requesting_userID=requester_id, |
40 | status=CodeImportResultStatus.FAILURE, |
41 | date_job_started=timestamp) |
42 | transaction.commit() |
43 | |
44 | === modified file 'lib/canonical/launchpad/tests/test_launchpadlib.py' |
45 | --- lib/canonical/launchpad/tests/test_launchpadlib.py 2009-06-25 05:30:52 +0000 |
46 | +++ lib/canonical/launchpad/tests/test_launchpadlib.py 2010-07-13 10:02:50 +0000 |
47 | @@ -5,22 +5,22 @@ |
48 | |
49 | import unittest |
50 | |
51 | +import transaction |
52 | + |
53 | from launchpadlib.testing.helpers import salgado_with_full_permissions |
54 | from canonical.testing import AppServerLayer |
55 | - |
56 | - |
57 | -class TestLaunchpadLib(unittest.TestCase): |
58 | +from lp.testing import TestCaseWithFactory |
59 | + |
60 | + |
61 | +class TestLaunchpadLib(TestCaseWithFactory): |
62 | """Tests for the launchpadlib client for the REST API.""" |
63 | |
64 | layer = AppServerLayer |
65 | - launchpad = None |
66 | - project = None |
67 | |
68 | def setUp(self): |
69 | - if self.launchpad is None: |
70 | - self.launchpad = salgado_with_full_permissions.login() |
71 | - if self.project is None: |
72 | - self.project = self.launchpad.projects['firefox'] |
73 | + super(TestLaunchpadLib, self).setUp() |
74 | + self.launchpad = salgado_with_full_permissions.login() |
75 | + self.project = self.launchpad.projects['firefox'] |
76 | |
77 | def verifyAttributes(self, element): |
78 | """Verify that launchpadlib can parse the element's attributes.""" |
79 | @@ -43,7 +43,10 @@ |
80 | |
81 | def test_branch(self): |
82 | """Test branch attributes.""" |
83 | - branch = self.project.getBranches()[0] |
84 | + branch_name = self.factory.makeBranch().unique_name |
85 | + transaction.commit() |
86 | + branch = self.launchpad.branches.getByUniqueName( |
87 | + unique_name=branch_name) |
88 | self.verifyAttributes(branch) |
89 | |
90 | def test_milestone(self): |
91 | |
92 | === modified file 'lib/lp/code/browser/tests/test_branch.py' |
93 | --- lib/lp/code/browser/tests/test_branch.py 2010-06-14 02:37:06 +0000 |
94 | +++ lib/lp/code/browser/tests/test_branch.py 2010-07-13 10:02:50 +0000 |
95 | @@ -6,7 +6,6 @@ |
96 | from __future__ import with_statement |
97 | |
98 | __metaclass__ = type |
99 | -__all__ = ['TestBranchView', 'test_suite'] |
100 | |
101 | from datetime import datetime, timedelta |
102 | from textwrap import dedent |
103 | @@ -16,7 +15,6 @@ |
104 | import simplejson |
105 | |
106 | |
107 | -from zope.component import getUtility |
108 | from zope.security.proxy import removeSecurityProxy |
109 | |
110 | from canonical.config import config |
111 | @@ -32,9 +30,6 @@ |
112 | from lp.code.interfaces.branchtarget import IBranchTarget |
113 | from canonical.launchpad.helpers import truncate_text |
114 | from lp.code.enums import BranchLifecycleStatus, BranchType |
115 | -from lp.registry.interfaces.person import IPersonSet |
116 | -from lp.registry.interfaces.product import IProductSet |
117 | -from lp.code.interfaces.branchlookup import IBranchLookup |
118 | from lp.testing import ( |
119 | login, login_person, logout, person_logged_in, ANONYMOUS, |
120 | TestCaseWithFactory) |
121 | @@ -122,20 +117,18 @@ |
122 | |
123 | class TestBranchView(TestCaseWithFactory): |
124 | |
125 | - layer = LaunchpadFunctionalLayer |
126 | + layer = DatabaseFunctionalLayer |
127 | |
128 | def setUp(self): |
129 | super(TestBranchView, self).setUp() |
130 | - login(ANONYMOUS) |
131 | self.request = LaunchpadTestRequest() |
132 | |
133 | - def tearDown(self): |
134 | - logout() |
135 | - super(TestBranchView, self).tearDown() |
136 | - |
137 | def testMirrorStatusMessageIsTruncated(self): |
138 | """mirror_status_message is truncated if the text is overly long.""" |
139 | - branch = getUtility(IBranchLookup).get(28) |
140 | + branch = self.factory.makeBranch() |
141 | + branch.mirrorFailed( |
142 | + "on quick brown fox the dog jumps to" * |
143 | + BranchMirrorStatusView.MAXIMUM_STATUS_MESSAGE_LENGTH) |
144 | branch_view = BranchMirrorStatusView(branch, self.request) |
145 | self.assertEqual( |
146 | truncate_text(branch.mirror_status_message, |
147 | @@ -144,7 +137,7 @@ |
148 | |
149 | def testMirrorStatusMessage(self): |
150 | """mirror_status_message on the view is the same as on the branch.""" |
151 | - branch = getUtility(IBranchLookup).get(5) |
152 | + branch = self.factory.makeBranch() |
153 | branch.mirrorFailed("This is a short error message.") |
154 | branch_view = BranchMirrorStatusView(branch, self.request) |
155 | self.assertTrue( |
156 | @@ -160,8 +153,8 @@ |
157 | |
158 | def testBranchAddRequestsMirror(self): |
159 | """Registering a mirrored branch requests a mirror.""" |
160 | - arbitrary_person = getUtility(IPersonSet).get(1) |
161 | - arbitrary_product = getUtility(IProductSet).get(1) |
162 | + arbitrary_person = self.factory.makePerson() |
163 | + arbitrary_product = self.factory.makeProduct() |
164 | login(arbitrary_person.preferredemail.email) |
165 | try: |
166 | add_view = BranchAddView(arbitrary_person, self.request) |
167 | @@ -195,7 +188,7 @@ |
168 | # The merge links are shown on projects that have multiple branches. |
169 | product = self.factory.makeProduct(name='super-awesome-project') |
170 | branch1 = self.factory.makeAnyBranch(product=product) |
171 | - branch2 = self.factory.makeAnyBranch(product=product) |
172 | + self.factory.makeAnyBranch(product=product) |
173 | view = BranchView(branch1, self.request) |
174 | view.initialize() |
175 | self.assertTrue(view.show_merge_links) |
176 | |
177 | === modified file 'lib/lp/code/interfaces/codeimportjob.py' |
178 | --- lib/lp/code/interfaces/codeimportjob.py 2010-03-16 01:34:38 +0000 |
179 | +++ lib/lp/code/interfaces/codeimportjob.py 2010-07-13 10:02:50 +0000 |
180 | @@ -16,8 +16,6 @@ |
181 | 'ICodeImportJobWorkflow', |
182 | ] |
183 | |
184 | -import datetime |
185 | - |
186 | from zope.interface import Interface |
187 | from zope.schema import Choice, Datetime, Int, Object, Text |
188 | |
189 | |
190 | === modified file 'lib/lp/code/model/tests/test_codeimportjob.py' |
191 | --- lib/lp/code/model/tests/test_codeimportjob.py 2010-07-13 10:02:48 +0000 |
192 | +++ lib/lp/code/model/tests/test_codeimportjob.py 2010-07-13 10:02:50 +0000 |
193 | @@ -5,7 +5,9 @@ |
194 | |
195 | __metaclass__ = type |
196 | |
197 | -__all__ = ['NewEvents', 'test_suite'] |
198 | +__all__ = [ |
199 | + 'NewEvents', |
200 | + ] |
201 | |
202 | from datetime import datetime |
203 | from pytz import UTC |
204 | @@ -24,7 +26,6 @@ |
205 | from canonical.config import config |
206 | from canonical.database.constants import UTC_NOW |
207 | from lp.code.model.codeimportjob import CodeImportJob |
208 | -from lp.code.model.codeimportmachine import CodeImportMachine |
209 | from lp.code.model.codeimportresult import CodeImportResult |
210 | from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet |
211 | from lp.code.enums import ( |
212 | @@ -38,12 +39,14 @@ |
213 | from lp.registry.interfaces.person import IPersonSet |
214 | from lp.testing import ( |
215 | ANONYMOUS, login, login_celebrity, logout, TestCaseWithFactory) |
216 | +from lp.testing.sampledata import NO_PRIVILEGE_EMAIL, VCS_IMPORTS_MEMBER_EMAIL |
217 | from canonical.launchpad.testing.codeimporthelpers import ( |
218 | make_finished_import, make_running_import) |
219 | from canonical.launchpad.testing.pages import get_feedback_messages |
220 | from canonical.launchpad.webapp import canonical_url |
221 | from canonical.librarian.interfaces import ILibrarianClient |
222 | -from canonical.testing import LaunchpadFunctionalLayer |
223 | +from canonical.testing import ( |
224 | + DatabaseFunctionalLayer, LaunchpadFunctionalLayer) |
225 | |
226 | |
227 | def login_for_code_imports(): |
228 | @@ -52,28 +55,29 @@ |
229 | CodeImports are currently hidden from regular users currently. Members of |
230 | the vcs-imports team and can access the objects freely. |
231 | """ |
232 | - login_celebrity('vcs_imports') |
233 | - |
234 | - |
235 | -class TestCodeImportJobSet(unittest.TestCase): |
236 | + return login_celebrity('vcs_imports') |
237 | + |
238 | + |
239 | +class TestCodeImportJobSet(TestCaseWithFactory): |
240 | """Unit tests for the CodeImportJobSet utility.""" |
241 | |
242 | - layer = LaunchpadFunctionalLayer |
243 | + layer = DatabaseFunctionalLayer |
244 | |
245 | def setUp(self): |
246 | + super(TestCodeImportJobSet, self).setUp() |
247 | login_for_code_imports() |
248 | |
249 | def test_getByIdExisting(self): |
250 | # CodeImportJobSet.getById retrieves a CodeImportJob by database id. |
251 | - job = getUtility(ICodeImportJobSet).getById(1) |
252 | - self.assertNotEqual(job, None) |
253 | - self.assertEqual(job.id, 1) |
254 | + made_job = self.factory.makeCodeImportJob() |
255 | + found_job = getUtility(ICodeImportJobSet).getById(made_job.id) |
256 | + self.assertEqual(made_job, found_job) |
257 | |
258 | def test_getByIdNotExisting(self): |
259 | # CodeImportJobSet.getById returns None if there is not CodeImportJob |
260 | # with the specified id. |
261 | no_job = getUtility(ICodeImportJobSet).getById(-1) |
262 | - self.assertEqual(no_job, None) |
263 | + self.assertIs(None, no_job) |
264 | |
265 | |
266 | class TestCodeImportJobSetGetJobForMachine(TestCaseWithFactory): |
267 | @@ -88,7 +92,7 @@ |
268 | method makeJob() creates actual CodeImportJob objects from these specs. |
269 | """ |
270 | |
271 | - layer = LaunchpadFunctionalLayer |
272 | + layer = DatabaseFunctionalLayer |
273 | |
274 | def setUp(self): |
275 | # Login so we can access the code import system, delete all jobs in |
276 | @@ -115,7 +119,7 @@ |
277 | def assertJobIsSelected(self, desired_job): |
278 | """Assert that the expected job is chosen by getJobForMachine.""" |
279 | observed_job = getUtility(ICodeImportJobSet).getJobForMachine( |
280 | - self.machine.hostname, 10) |
281 | + self.machine.hostname, worker_limit=10) |
282 | self.assert_(observed_job is not None, "No job was selected.") |
283 | self.assertEqual(desired_job, observed_job, |
284 | "Expected job not selected.") |
285 | @@ -123,7 +127,7 @@ |
286 | def assertNoJobSelected(self): |
287 | """Assert that no job is selected.""" |
288 | observed_job = getUtility(ICodeImportJobSet).getJobForMachine( |
289 | - 'machine', 10) |
290 | + 'machine', worker_limit=10) |
291 | self.assert_(observed_job is None, "Job unexpectedly selected.") |
292 | |
293 | def test_nothingSelectedIfNothingCreated(self): |
294 | @@ -231,7 +235,7 @@ |
295 | class TestCodeImportJobSetGetReclaimableJobs(ReclaimableJobTests): |
296 | """Tests for the CodeImportJobSet.getReclaimableJobs method.""" |
297 | |
298 | - layer = LaunchpadFunctionalLayer |
299 | + layer = DatabaseFunctionalLayer |
300 | |
301 | def test_upToDateJob(self): |
302 | # A job that was updated recently is not considered reclaimable. |
303 | @@ -264,7 +268,7 @@ |
304 | class TestCodeImportJobSetGetJobForMachineGardening(ReclaimableJobTests): |
305 | """Test that getJobForMachine gardens stale code import jobs.""" |
306 | |
307 | - layer = LaunchpadFunctionalLayer |
308 | + layer = DatabaseFunctionalLayer |
309 | |
310 | def test_getJobForMachineGardens(self): |
311 | # getJobForMachine reclaims all reclaimable jobs each time it is |
312 | @@ -275,7 +279,7 @@ |
313 | machine = self.factory.makeCodeImportMachine(set_online=True) |
314 | login(ANONYMOUS) |
315 | getUtility(ICodeImportJobSet).getJobForMachine( |
316 | - machine.hostname, 10) |
317 | + machine.hostname, worker_limit=10) |
318 | login_for_code_imports() |
319 | # Now there are no reclaimable jobs. |
320 | self.assertReclaimableJobs([]) |
321 | @@ -364,7 +368,7 @@ |
322 | AssertFailureMixin): |
323 | """Unit tests for the CodeImportJobWorkflow.newJob method.""" |
324 | |
325 | - layer = LaunchpadFunctionalLayer |
326 | + layer = DatabaseFunctionalLayer |
327 | |
328 | def setUp(self): |
329 | super(TestCodeImportJobWorkflowNewJob, self).setUp() |
330 | @@ -373,50 +377,31 @@ |
331 | def test_wrongReviewStatus(self): |
332 | # CodeImportJobWorkflow.newJob fails if the CodeImport review_status |
333 | # is different from REVIEWED. |
334 | - new_import = getUtility(ICodeImportSet).get(2) |
335 | - # Checking sampledata expectations. |
336 | - self.assertEqual(new_import.branch.unique_name, |
337 | - '~vcs-imports/evolution/import') |
338 | - NEW = CodeImportReviewStatus.NEW |
339 | - self.assertEqual(new_import.review_status, NEW) |
340 | + new_import = self.factory.makeCodeImport() |
341 | + branch_name = new_import.branch.unique_name |
342 | # Testing newJob failure. |
343 | self.assertFailure( |
344 | - "Review status of ~vcs-imports/evolution/import " |
345 | - "is not REVIEWED: NEW", |
346 | + "Review status of %s is not REVIEWED: NEW" % (branch_name,), |
347 | getUtility(ICodeImportJobWorkflow).newJob, new_import) |
348 | |
349 | def test_existingJob(self): |
350 | # CodeImportJobWorkflow.newJob fails if the CodeImport is already |
351 | # associated to a CodeImportJob. |
352 | - reviewed_import = getUtility(ICodeImportSet).get(1) |
353 | - # Checking sampledata expectations. |
354 | - self.assertEqual(reviewed_import.branch.unique_name, |
355 | - '~vcs-imports/gnome-terminal/import') |
356 | - REVIEWED = CodeImportReviewStatus.REVIEWED |
357 | - self.assertEqual(reviewed_import.review_status, REVIEWED) |
358 | - self.assertNotEqual(reviewed_import.import_job, None) |
359 | - # Testing newJob failure. |
360 | + job = self.factory.makeCodeImportJob() |
361 | + reviewed_import = job.code_import |
362 | + branch_name = reviewed_import.branch.unique_name |
363 | self.assertFailure( |
364 | - "Already associated to a CodeImportJob: " |
365 | - "~vcs-imports/gnome-terminal/import", |
366 | + "Already associated to a CodeImportJob: %s" % (branch_name,), |
367 | getUtility(ICodeImportJobWorkflow).newJob, reviewed_import) |
368 | |
369 | def getCodeImportForDateDueTest(self): |
370 | """Return a `CodeImport` object for testing how date_due is set. |
371 | |
372 | - We check that it is not associated to any `CodeImportJob` or |
373 | - `CodeImportResult`, and we ensure its review_status is REVIEWED. |
374 | + It is not associated to any `CodeImportJob` or `CodeImportResult`, and |
375 | + its review_status is REVIEWED. |
376 | """ |
377 | - new_import = getUtility(ICodeImportSet).get(2) |
378 | - # Checking sampledata expectations. |
379 | - self.assertEqual(new_import.import_job, None) |
380 | - self.assertEqual( |
381 | - CodeImportResult.selectBy(code_importID=new_import.id).count(), 0) |
382 | - # We need to set review_status to REVIEWED before calling newJob, and |
383 | - # the interface marks review_status as read-only. |
384 | - REVIEWED = CodeImportReviewStatus.REVIEWED |
385 | - removeSecurityProxy(new_import).review_status = REVIEWED |
386 | - return new_import |
387 | + return self.factory.makeCodeImport( |
388 | + review_status=CodeImportReviewStatus.REVIEWED) |
389 | |
390 | def test_dateDueNoPreviousResult(self): |
391 | # If there is no CodeImportResult for the CodeImport, then the new |
392 | @@ -432,7 +417,7 @@ |
393 | code_import = self.getCodeImportForDateDueTest() |
394 | # Create a CodeImportResult that started a long time ago. This one |
395 | # must be superseded by the more recent one created below. |
396 | - machine = CodeImportMachine.get(1) |
397 | + machine = self.factory.makeCodeImportMachine() |
398 | FAILURE = CodeImportResultStatus.FAILURE |
399 | CodeImportResult( |
400 | code_import=code_import, machine=machine, status=FAILURE, |
401 | @@ -467,7 +452,7 @@ |
402 | # set to UTC_NOW. |
403 | code_import = self.getCodeImportForDateDueTest() |
404 | # Create a CodeImportResult that started a long time ago. |
405 | - machine = CodeImportMachine.get(1) |
406 | + machine = self.factory.makeCodeImportMachine() |
407 | FAILURE = CodeImportResultStatus.FAILURE |
408 | CodeImportResult( |
409 | code_import=code_import, machine=machine, status=FAILURE, |
410 | @@ -478,78 +463,66 @@ |
411 | self.assertSqlAttributeEqualsDate(job, 'date_due', UTC_NOW) |
412 | |
413 | |
414 | -class TestCodeImportJobWorkflowDeletePendingJob(unittest.TestCase, |
415 | +class TestCodeImportJobWorkflowDeletePendingJob(TestCaseWithFactory, |
416 | AssertFailureMixin): |
417 | """Unit tests for CodeImportJobWorkflow.deletePendingJob.""" |
418 | |
419 | - layer = LaunchpadFunctionalLayer |
420 | + layer = DatabaseFunctionalLayer |
421 | |
422 | def setUp(self): |
423 | super(TestCodeImportJobWorkflowDeletePendingJob, self).setUp() |
424 | - login_for_code_imports() |
425 | + self.import_admin = login_for_code_imports() |
426 | |
427 | def test_wrongReviewStatus(self): |
428 | # CodeImportJobWorkflow.deletePendingJob fails if the |
429 | # CodeImport review_status is equal to REVIEWED. |
430 | - reviewed_import = getUtility(ICodeImportSet).get(1) |
431 | - # Checking sampledata expectations. |
432 | - self.assertEqual(reviewed_import.branch.unique_name, |
433 | - '~vcs-imports/gnome-terminal/import') |
434 | - REVIEWED = CodeImportReviewStatus.REVIEWED |
435 | - self.assertEqual(reviewed_import.review_status, REVIEWED) |
436 | + reviewed_import = self.factory.makeCodeImport() |
437 | + reviewed_import.updateFromData( |
438 | + {'review_status': CodeImportReviewStatus.REVIEWED}, |
439 | + self.import_admin) |
440 | + branch_name = reviewed_import.branch.unique_name |
441 | # Testing deletePendingJob failure. |
442 | self.assertFailure( |
443 | - "The review status of ~vcs-imports/gnome-terminal/import " |
444 | - "is REVIEWED.", |
445 | + "The review status of %s is REVIEWED." % (branch_name,), |
446 | getUtility(ICodeImportJobWorkflow).deletePendingJob, |
447 | reviewed_import) |
448 | |
449 | def test_noJob(self): |
450 | # CodeImportJobWorkflow.deletePendingJob fails if the |
451 | # CodeImport is not associated to a CodeImportJob. |
452 | - new_import = getUtility(ICodeImportSet).get(2) |
453 | - # Checking sampledata expectations. |
454 | - self.assertEqual(new_import.branch.unique_name, |
455 | - '~vcs-imports/evolution/import') |
456 | - NEW = CodeImportReviewStatus.NEW |
457 | - self.assertEqual(new_import.review_status, NEW) |
458 | - self.assertEqual(new_import.import_job, None) |
459 | + new_import = self.factory.makeCodeImport() |
460 | + branch_name = new_import.branch.unique_name |
461 | # Testing deletePendingJob failure. |
462 | self.assertFailure( |
463 | - "Not associated to a CodeImportJob: " |
464 | - "~vcs-imports/evolution/import", |
465 | + "Not associated to a CodeImportJob: %s" % (branch_name,), |
466 | getUtility(ICodeImportJobWorkflow).deletePendingJob, |
467 | new_import) |
468 | |
469 | def test_wrongJobState(self): |
470 | # CodeImportJobWorkflow.deletePendingJob fails if the state of |
471 | # the CodeImportJob is different from PENDING. |
472 | - reviewed_import = getUtility(ICodeImportSet).get(1) |
473 | - # Checking sampledata expectations. |
474 | - self.assertEqual(reviewed_import.branch.unique_name, |
475 | - '~vcs-imports/gnome-terminal/import') |
476 | - # ICodeImport does not allow setting any attribute, so we need to use |
477 | - # removeSecurityProxy to set the review_status attribute. |
478 | + job = self.factory.makeCodeImportJob() |
479 | + code_import = job.code_import |
480 | + branch_name = job.code_import.branch.unique_name |
481 | + # ICodeImport does not allow setting 'review_status', so we must use |
482 | + # removeSecurityProxy. |
483 | INVALID = CodeImportReviewStatus.INVALID |
484 | - removeSecurityProxy(reviewed_import).review_status = INVALID |
485 | - self.assertNotEqual(reviewed_import.import_job, None) |
486 | + removeSecurityProxy(code_import).review_status = INVALID |
487 | # ICodeImportJob does not allow setting 'state', so we must |
488 | # use removeSecurityProxy. |
489 | RUNNING = CodeImportJobState.RUNNING |
490 | - removeSecurityProxy(reviewed_import.import_job).state = RUNNING |
491 | + removeSecurityProxy(code_import.import_job).state = RUNNING |
492 | # Testing deletePendingJob failure. |
493 | self.assertFailure( |
494 | - "The CodeImportJob associated to " |
495 | - "~vcs-imports/gnome-terminal/import is RUNNING.", |
496 | - getUtility(ICodeImportJobWorkflow).deletePendingJob, |
497 | - reviewed_import) |
498 | + "The CodeImportJob associated to %s is RUNNING." % (branch_name,), |
499 | + getUtility(ICodeImportJobWorkflow).deletePendingJob, code_import) |
500 | |
501 | |
502 | class TestCodeImportJobWorkflowRequestJob(TestCaseWithFactory, |
503 | AssertFailureMixin, AssertEventMixin): |
504 | """Unit tests for CodeImportJobWorkflow.requestJob.""" |
505 | |
506 | - layer = LaunchpadFunctionalLayer |
507 | + layer = DatabaseFunctionalLayer |
508 | |
509 | def setUp(self): |
510 | super(TestCodeImportJobWorkflowRequestJob, self).setUp() |
511 | @@ -641,7 +614,7 @@ |
512 | AssertFailureMixin, AssertEventMixin): |
513 | """Unit tests for CodeImportJobWorkflow.startJob.""" |
514 | |
515 | - layer = LaunchpadFunctionalLayer |
516 | + layer = DatabaseFunctionalLayer |
517 | |
518 | def setUp(self): |
519 | super(TestCodeImportJobWorkflowStartJob, self).setUp() |
520 | @@ -679,7 +652,7 @@ |
521 | AssertFailureMixin, AssertEventMixin): |
522 | """Unit tests for CodeImportJobWorkflow.updateHeartbeat.""" |
523 | |
524 | - layer = LaunchpadFunctionalLayer |
525 | + layer = DatabaseFunctionalLayer |
526 | |
527 | def setUp(self): |
528 | super(TestCodeImportJobWorkflowUpdateHeartbeat, self).setUp() |
529 | @@ -705,7 +678,7 @@ |
530 | |
531 | def setUp(self): |
532 | super(TestCodeImportJobWorkflowFinishJob, self).setUp() |
533 | - login_for_code_imports() |
534 | + self.vcs_imports = login_for_code_imports() |
535 | self.machine = self.factory.makeCodeImportMachine(set_online=True) |
536 | |
537 | def makeRunningJob(self, code_import=None): |
538 | @@ -804,10 +777,9 @@ |
539 | # unless the CodeImport has been suspended or marked invalid. |
540 | running_job = self.makeRunningJob() |
541 | code_import = running_job.code_import |
542 | - ddaa = getUtility(IPersonSet).getByEmail( |
543 | - 'david.allouche@canonical.com') |
544 | code_import.updateFromData( |
545 | - {'review_status': CodeImportReviewStatus.SUSPENDED}, ddaa) |
546 | + {'review_status': CodeImportReviewStatus.SUSPENDED}, |
547 | + self.vcs_imports) |
548 | getUtility(ICodeImportJobWorkflow).finishJob( |
549 | running_job, CodeImportResultStatus.SUCCESS, None) |
550 | self.assertTrue(code_import.import_job is None) |
551 | @@ -920,8 +892,7 @@ |
552 | log_alias = getUtility(ILibraryFileAliasSet)[log_alias_id] |
553 | result = self.getResultForJob(job, log_alias=log_alias) |
554 | |
555 | - self.assertEqual( |
556 | - result.log_file.read(), log_data) |
557 | + self.assertEqual(result.log_file.read(), log_data) |
558 | |
559 | def test_createsFinishCodeImportEvent(self): |
560 | # finishJob() creates a FINISH CodeImportEvent. |
561 | @@ -1005,7 +976,7 @@ |
562 | |
563 | # This is a dependence on the sample data: David Allouche is a member of the |
564 | # ~vcs-imports celebrity team. |
565 | -logged_in_for_code_imports = logged_in_as('david.allouche@canonical.com') |
566 | +logged_in_for_code_imports = logged_in_as(VCS_IMPORTS_MEMBER_EMAIL) |
567 | |
568 | |
569 | class TestRequestJobUIRaces(TestCaseWithFactory): |
570 | @@ -1016,7 +987,7 @@ |
571 | the button and check that appropriate notifications are displayed. |
572 | """ |
573 | |
574 | - layer = LaunchpadFunctionalLayer |
575 | + layer = DatabaseFunctionalLayer |
576 | |
577 | @logged_in_for_code_imports |
578 | def getNewCodeImportIDAndBranchURL(self): |
579 | @@ -1027,7 +998,7 @@ |
580 | code_import_id = code_import.id |
581 | return code_import_id, branch_url |
582 | |
583 | - @logged_in_as('no-priv@canonical.com') |
584 | + @logged_in_as(NO_PRIVILEGE_EMAIL) |
585 | def requestJobByUserWithDisplayName(self, code_import_id, displayname): |
586 | """Record a request for the job by a user with the given name.""" |
587 | getUtility(ICodeImportJobWorkflow).requestJob( |
588 | |
589 | === modified file 'lib/lp/testing/factory.py' |
590 | --- lib/lp/testing/factory.py 2010-07-08 11:54:57 +0000 |
591 | +++ lib/lp/testing/factory.py 2010-07-13 10:02:50 +0000 |
592 | @@ -1436,7 +1436,7 @@ |
593 | def makeCodeImport(self, svn_branch_url=None, cvs_root=None, |
594 | cvs_module=None, target=None, branch_name=None, |
595 | git_repo_url=None, hg_repo_url=None, registrant=None, |
596 | - rcs_type=None): |
597 | + rcs_type=None, review_status=None): |
598 | """Create and return a new, arbitrary code import. |
599 | |
600 | The type of code import will be inferred from the source details |
601 | @@ -1461,26 +1461,29 @@ |
602 | else: |
603 | assert rcs_type in (RevisionControlSystems.SVN, |
604 | RevisionControlSystems.BZR_SVN) |
605 | - return code_import_set.new( |
606 | + code_import = code_import_set.new( |
607 | registrant, target, branch_name, rcs_type=rcs_type, |
608 | url=svn_branch_url) |
609 | elif git_repo_url is not None: |
610 | assert rcs_type in (None, RevisionControlSystems.GIT) |
611 | - return code_import_set.new( |
612 | + code_import = code_import_set.new( |
613 | registrant, target, branch_name, |
614 | rcs_type=RevisionControlSystems.GIT, |
615 | url=git_repo_url) |
616 | elif hg_repo_url is not None: |
617 | - return code_import_set.new( |
618 | + code_import = code_import_set.new( |
619 | registrant, target, branch_name, |
620 | rcs_type=RevisionControlSystems.HG, |
621 | url=hg_repo_url) |
622 | else: |
623 | assert rcs_type in (None, RevisionControlSystems.CVS) |
624 | - return code_import_set.new( |
625 | + code_import = code_import_set.new( |
626 | registrant, target, branch_name, |
627 | rcs_type=RevisionControlSystems.CVS, |
628 | cvs_root=cvs_root, cvs_module=cvs_module) |
629 | + if review_status: |
630 | + removeSecurityProxy(code_import).review_status = review_status |
631 | + return code_import |
632 | |
633 | def makeCodeImportEvent(self): |
634 | """Create and return a CodeImportEvent.""" |
635 | |
636 | === added file 'lib/lp/testing/sampledata.py' |
637 | --- lib/lp/testing/sampledata.py 1970-01-01 00:00:00 +0000 |
638 | +++ lib/lp/testing/sampledata.py 2010-07-13 10:02:50 +0000 |
639 | @@ -0,0 +1,18 @@ |
640 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
641 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
642 | + |
643 | +"""Constants that refer to values in sampledata. |
644 | + |
645 | +If ever you use a literal in a test that refers to sample data, even if it's |
646 | +just a small number, then you should define it as a constant here. |
647 | +""" |
648 | + |
649 | +__metaclass__ = type |
650 | +__all__ = [ |
651 | + 'NO_PRIVILEGE_EMAIL', |
652 | + 'VCS_IMPORTS_MEMBER_EMAIL', |
653 | + ] |
654 | + |
655 | + |
656 | +NO_PRIVILEGE_EMAIL = 'no-priv@canonical.com' |
657 | +VCS_IMPORTS_MEMBER_EMAIL = 'david.allouche@canonical.com' |
658 | |
659 | === added file 'lib/lp/testing/tests/test_factory.py' |
660 | --- lib/lp/testing/tests/test_factory.py 1970-01-01 00:00:00 +0000 |
661 | +++ lib/lp/testing/tests/test_factory.py 2010-07-13 10:02:50 +0000 |
662 | @@ -0,0 +1,34 @@ |
663 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
664 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
665 | + |
666 | +"""Tests for the Launchpad object factory.""" |
667 | + |
668 | +__metaclass__ = type |
669 | + |
670 | +import unittest |
671 | + |
672 | +from canonical.testing.layers import DatabaseFunctionalLayer |
673 | +from lp.code.enums import CodeImportReviewStatus |
674 | +from lp.testing import TestCaseWithFactory |
675 | + |
676 | + |
677 | +class TestFactory(TestCaseWithFactory): |
678 | + |
679 | + layer = DatabaseFunctionalLayer |
680 | + |
681 | + def test_makeCodeImportNoStatus(self): |
682 | + # If makeCodeImport is not given a review status, it defaults to NEW. |
683 | + code_import = self.factory.makeCodeImport() |
684 | + self.assertEqual( |
685 | + CodeImportReviewStatus.NEW, code_import.review_status) |
686 | + |
687 | + def test_makeCodeImportReviewStatus(self): |
688 | + # If makeCodeImport is given a review status, then that is the status |
689 | + # of the created import. |
690 | + status = CodeImportReviewStatus.REVIEWED |
691 | + code_import = self.factory.makeCodeImport(review_status=status) |
692 | + self.assertEqual(status, code_import.review_status) |
693 | + |
694 | + |
695 | +def test_suite(): |
696 | + return unittest.TestLoader().loadTestsFromName(__name__) |
I think this is useful; thanks for doing it.