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