Merge lp:~cjohnston/uci-engine/amulet-int-test-fix into lp:uci-engine

Proposed by Chris Johnston
Status: Merged
Approved by: Celso Providelo
Approved revision: 473
Merged at revision: 469
Proposed branch: lp:~cjohnston/uci-engine/amulet-int-test-fix
Merge into: lp:uci-engine
Diff against target: 570 lines (+117/-97)
10 files modified
ci-utils/ci_utils/testing/__init__.py (+4/-3)
ci-utils/ci_utils/testing/features.py (+0/-1)
ci-utils/ci_utils/tests/test_file_handler.py (+40/-39)
cli/tests/test_cli.py (+14/-13)
cli/tests/test_ticket.py (+8/-8)
juju-deployer/deploy.py (+19/-9)
juju-deployer/test_deploy.py (+13/-5)
tests/deployers.py (+4/-6)
tests/run.py (+2/-1)
tests/test_integration.py (+13/-12)
To merge this branch: bzr merge lp:~cjohnston/uci-engine/amulet-int-test-fix
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Vincent Ladeuil (community) Approve
Chris Johnston (community) Needs Resubmitting
Review via email: mp+218274@code.launchpad.net

Commit message

Fixes integration amulet tests

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:461
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/580/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/580/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:465
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/582/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/582/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:466
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/583/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/583/rebuild

review: Approve (continuous-integration)
Revision history for this message
Celso Providelo (cprov) wrote :

Nice move exposing TestCaseWithGnupg() to other test suites! I needed it in GK and had to do an ugly importing dancing.

I think it would be even better if instead of importing ci_utils.tests in callsites (and possibly dealing with name conflicts as you did) we create a ci_utils.testing domain for storing common auxiliary testing tools for UCI-E.

Just a suggestion, though. It's not a big deal to handle namespace clashing here and there, but it might get annoying when we start grouping common testing tools more aggressively.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:467
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/584/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/584/rebuild

review: Approve (continuous-integration)
Revision history for this message
Vincent Ladeuil (vila) wrote :

> Nice move exposing TestCaseWithGnupg() to other test suites! I needed it in GK
> and had to do an ugly importing dancing.
>
> I think it would be even better if instead of importing ci_utils.tests in
> callsites (and possibly dealing with name conflicts as you did) we create a
> ci_utils.testing domain for storing common auxiliary testing tools for UCI-E.

Objection your honor !

You're kicking the can, the next time we'll have two 'testing' modules and we'll have to deal with the namespace clashing anyway.

This class is part of the test infrastructure and as such, perfectly fine under (or in) the 'tests' module/hierarchy.

> Just a suggestion, though. It's not a big deal to handle namespace clashing
> here and there, but it might get annoying when we start grouping common
> testing tools more aggressively.

This will happen naturally as needed and we'll deal with the conflicts as needed. It's common to define a test class in a lower module and move it up as it's reused. Here we crossing the component boundary but it's still a test class.

Revision history for this message
Celso Providelo (cprov) wrote :

On Tue, May 6, 2014 at 3:50 AM, Vincent Ladeuil <email address hidden> wrote:
>> Nice move exposing TestCaseWithGnupg() to other test suites! I needed it in GK
>> and had to do an ugly importing dancing.
>>
>> I think it would be even better if instead of importing ci_utils.tests in
>> callsites (and possibly dealing with name conflicts as you did) we create a
>> ci_utils.testing domain for storing common auxiliary testing tools for UCI-E.
>
> Objection your honor !
>
> You're kicking the can, the next time we'll have two 'testing' modules and we'll have to deal with the namespace clashing anyway.
>
> This class is part of the test infrastructure and as such, perfectly fine under (or in) the 'tests' module/hierarchy.

Vincent,

You are obviously misunderstanding the purpose of a ci_utils.testing
submodule. It will hold tests helpers that are common to be project in
the module domain, ci_utils.tests is meant to contain context-relevant
tests not code.

>> Just a suggestion, though. It's not a big deal to handle namespace clashing
>> here and there, but it might get annoying when we start grouping common
>> testing tools more aggressively.
>
> This will happen naturally as needed and we'll deal with the conflicts as needed. It's common to define a test class in a lower module and move it up as it's reused. Here we crossing the component boundary but it's still a test class.

That's the point, testing helpers are not tests, they are helpers and
when they become needed/useful in other context they need to go up to
a shared-place which is the module domain, not the tests folder.

Let's sort this on IRC.

[]

--
Celso Providelo
<email address hidden>

Revision history for this message
Chris Johnston (cjohnston) :
review: Needs Resubmitting
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:469
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/600/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/600/rebuild

review: Approve (continuous-integration)
Revision history for this message
Vincent Ladeuil (vila) wrote :

13 +def get_test_file_path(filename):

Thanks ! I think it indeed makes more sense to have that as a module
function rather than a test class method.

I've made further cleanups in lp:~vila/uci-engine/amulet-int-test-fix as
revno 470.

141 + old_path = sys.path
142 + sys.path = []
143 + with self.assertRaises(SystemExit):
144 + deploy.check_dependencies(needed_imports=['gnupg'])
145 + sys.path = old_path

If the test fails, sys.path won't be restored, bad things will happen ;)

Fixed in revno 471.

73 +def check_dependencies(needed_commands='', needed_imports=''):

Good addition, thanks for the added test !

None is a better default value, [] can't be used and adding if needed_imports
is None: needed_imports = [] seems like overkill here.

Fixed in revno 472.

191 + if and_ip:
192 + return units, ip
193 + else:
194 + return ip

Variable signature depending on input args, urgh, I don't think we need it here, if you want to ignore the port, just take the ip.

Fixed in revno 473.

Back to:

138 + def test_check_dependencies_needed_imports(self):
144 + deploy.check_dependencies(needed_imports=['gnupg'])

If gnupg is already imported, this test will (and has in my case ;) fail, so
better check for a non existing module instead.

Fixed in revno 474.

Overall, this MP was about s/ts-django/webui-apache/, with all those cleanups this is going out of hand, so let's try to land it asap as I agree the core fix should help.

review: Needs Fixing
Revision history for this message
Vincent Ladeuil (vila) wrote :

Good for me !

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:471
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/603/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/603/rebuild

review: Approve (continuous-integration)
Revision history for this message
Ubuntu CI Bot (uci-bot) wrote :

Attempt to merge into lp:uci-engine failed due to conflicts:

text conflict in juju-deployer/test_deploy.py

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:472
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/605/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/605/rebuild

review: Needs Fixing (continuous-integration)
473. By Chris Johnston

Fix conflicts - from cprov

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:473
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/607/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/607/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ci-utils/ci_utils/testing/__init__.py'
2--- ci-utils/ci_utils/testing/__init__.py 2014-05-06 14:52:19 +0000
3+++ ci-utils/ci_utils/testing/__init__.py 2014-05-07 16:48:40 +0000
4@@ -70,6 +70,7 @@
5 def _destroy_gnupg_env(self):
6 shutil.rmtree(self.gnupg_home)
7
8- def get_test_file_path(self, filename):
9- """Return the absolute path of a given testing file."""
10- return os.path.join(TEST_DATA_ROOT, filename)
11+
12+def get_test_file_path(filename):
13+ """Return the absolute path of a given testing file."""
14+ return os.path.join(TEST_DATA_ROOT, filename)
15
16=== modified file 'ci-utils/ci_utils/testing/features.py'
17--- ci-utils/ci_utils/testing/features.py 2014-05-06 14:16:05 +0000
18+++ ci-utils/ci_utils/testing/features.py 2014-05-07 16:48:40 +0000
19@@ -21,7 +21,6 @@
20 from ucitests import features
21 import yaml
22
23-
24 # Provide a shorcut so users don't have to import from ucitests
25 requires = features.requires
26
27
28=== modified file 'ci-utils/ci_utils/tests/test_file_handler.py'
29--- ci-utils/ci_utils/tests/test_file_handler.py 2014-05-06 16:53:31 +0000
30+++ ci-utils/ci_utils/tests/test_file_handler.py 2014-05-07 16:48:40 +0000
31@@ -27,13 +27,11 @@
32 FileToUploadNotFound,
33 UploadDirNotFound
34 )
35-from ci_utils.testing import (
36- TestCaseWithGnupg,
37- TEST_DATA_ROOT,
38-)
39-
40-
41-class ChangesProcessorTestCase(TestCaseWithGnupg):
42+from ci_utils import testing
43+
44+
45+class ChangesProcessorTestCase(testing.TestCaseWithGnupg):
46+
47 def setUp(self):
48 super(ChangesProcessorTestCase, self).setUp()
49 self.create_test_info()
50@@ -58,8 +56,8 @@
51 self.source_version)
52
53 def test_parse(self):
54- processor = ChangesProcessor(self.get_test_file_path(
55- self.changes_file))
56+ tf_path = testing.get_test_file_path
57+ processor = ChangesProcessor(tf_path(self.changes_file))
58 processor.parse()
59 self.assertIsInstance(processor.changes, Changes)
60 self.assertEqual(processor.changes.get_package_name(),
61@@ -68,87 +66,90 @@
62 self.assertEqual(processor.source_package_name, self.source_name)
63 self.assertEqual(processor.source_version, self.full_version)
64
65- self.assertEqual(self.get_test_file_path(self.dsc_file),
66- processor.changes.get_dsc())
67- self.assertEqual(self.get_test_file_path(self.debian_tar_gz_file),
68+ self.assertEqual(tf_path(self.dsc_file), processor.changes.get_dsc())
69+ self.assertEqual(tf_path(self.debian_tar_gz_file),
70 processor.changes.get_diff())
71- self.assertTrue(self.get_test_file_path(self.orig_file) in
72- processor.changes.get_files())
73+ self.assertTrue(tf_path(self.orig_file)
74+ in processor.changes.get_files())
75
76 def test_parse_changes_file_not_found(self):
77- self.assertRaises(ChangesFileNotFound, ChangesProcessor,
78- "barbaz_source.changes")
79+ with self.assertRaises(ChangesFileNotFound):
80+ ChangesProcessor("barbaz_source.changes")
81
82 def test_parse_changes_file_is_a_dsc(self):
83 # We're only able to tell a file is a real .changes during parsing.
84 processor = ChangesProcessor(
85- self.get_test_file_path("foobar_0.1-1_dsc.changes"))
86- self.assertRaises(ChangesParseError, processor.parse)
87+ testing.get_test_file_path("foobar_0.1-1_dsc.changes"))
88+ with self.assertRaises(ChangesParseError):
89+ processor.parse()
90
91 def test_parse_changes_file_is_something_else(self):
92 # We're only able to tell a file is a real .changes during parsing.
93 processor = ChangesProcessor(
94- self.get_test_file_path("foobar_0.1-1_random.changes"))
95- self.assertRaises(ChangesFileException, processor.parse)
96+ testing.get_test_file_path("foobar_0.1-1_random.changes"))
97+ with self.assertRaises(ChangesFileException):
98+ processor.parse()
99
100 def test_upload_dir_not_found(self):
101- self.assertRaises(UploadDirNotFound, ChangesProcessor,
102- self.get_test_file_path(self.changes_file),
103- "foo/bar/baz")
104+ with self.assertRaises(UploadDirNotFound):
105+ ChangesProcessor(testing.get_test_file_path(self.changes_file),
106+ "foo/bar/baz")
107
108 def test_files_to_upload_dir_found(self):
109 processor = ChangesProcessor(
110- self.get_test_file_path(self.changes_file),
111- files_to_upload_dir=TEST_DATA_ROOT)
112- self.assertEquals(processor.files_to_upload_dir, TEST_DATA_ROOT)
113+ testing.get_test_file_path(self.changes_file),
114+ files_to_upload_dir=testing.TEST_DATA_ROOT)
115+ self.assertEquals(testing.TEST_DATA_ROOT,
116+ processor.files_to_upload_dir)
117
118 def test_file_to_upload_not_found(self):
119 processor = ChangesProcessor(
120- self.get_test_file_path(self.changes_file),
121- files_to_upload_dir=".")
122+ testing.get_test_file_path(self.changes_file),
123+ files_to_upload_dir="/tmp")
124 self.assertRaises(FileToUploadNotFound, processor.parse)
125
126 def test_all_files_found(self):
127 processor = ChangesProcessor(
128- self.get_test_file_path(self.changes_file))
129- self.assertEqual(len(processor.files_to_upload), 0)
130+ testing.get_test_file_path(self.changes_file))
131+ self.assertEqual(0, len(processor.files_to_upload))
132 processor.parse()
133 # The three files (dsc, debian.tar.gz and orig) plus changes file
134- self.assertEqual(len(processor.files_to_upload), 4)
135+ self.assertEqual(4, len(processor.files_to_upload))
136 processor.validate()
137 self.assertTrue(
138 processor.changes.get_dsc() in processor.files_to_upload)
139 self.assertTrue(
140 processor.changes.get_diff() in processor.files_to_upload)
141 self.assertTrue(
142- self.get_test_file_path(self.orig_file) in
143+ testing.get_test_file_path(self.orig_file) in
144 processor.files_to_upload)
145
146 def test_files_to_upload_dir_not_provided(self):
147 processor = ChangesProcessor(
148- self.get_test_file_path(self.changes_file))
149- self.assertEqual(processor.files_to_upload_dir, TEST_DATA_ROOT)
150+ testing.get_test_file_path(self.changes_file))
151+ self.assertEqual(testing.TEST_DATA_ROOT, processor.files_to_upload_dir)
152
153 def test_signature_check_fails(self):
154 processor = ChangesProcessor(
155- self.get_test_file_path("foobar_0.1-1_unsigned.changes"))
156+ testing.get_test_file_path("foobar_0.1-1_unsigned.changes"))
157 processor.parse()
158 self.assertRaises(ChangesValidationError, processor.validate)
159
160 def test_validate_distribution_unreleased(self):
161 processor = ChangesProcessor(
162- self.get_test_file_path("foobar_0.1-1_unreleased.changes"))
163+ testing.get_test_file_path("foobar_0.1-1_unreleased.changes"))
164 processor.parse()
165- self.assertRaises(ChangesValidationError, processor.validate)
166+ with self.assertRaises(ChangesValidationError):
167+ processor.validate()
168
169 def test_process(self):
170 # Simple test to guarantee minimum integrity of this method, as the
171 # parts are being tested elsewhere.
172 processor = ChangesProcessor(
173- self.get_test_file_path(self.changes_file))
174+ testing.get_test_file_path(self.changes_file))
175 processor.process()
176 self.assertIsInstance(processor.changes, Changes)
177 self.assertEqual(processor.changes.get_package_name(),
178 self.source_name)
179
180- self.assertEqual(len(processor.files_to_upload), 4)
181+ self.assertEqual(4, len(processor.files_to_upload))
182
183=== modified file 'cli/tests/test_cli.py'
184--- cli/tests/test_cli.py 2014-05-06 16:53:31 +0000
185+++ cli/tests/test_cli.py 2014-05-07 16:48:40 +0000
186@@ -32,18 +32,18 @@
187 capture_stdout,
188 mock_load_config,
189 )
190-from ci_utils.testing import TestCaseWithGnupg
191+from ci_utils import testing
192 from ci_utils.ticket_states import (
193 TicketWorkflowStep,
194 TicketWorkflowStepStatus,
195 )
196
197
198-class MainScriptTestCase(TestCaseWithGnupg):
199+class MainScriptTestCase(testing.TestCaseWithGnupg):
200
201 def setUp(self):
202 super(MainScriptTestCase, self).setUp()
203- curdir = os.path.dirname(__file__)
204+ curdir = os.path.abspath(os.path.dirname(__file__))
205 self.main_script = os.path.join(curdir, "../ubuntu-ci")
206 self.cli = imp.load_source(
207 "ubuntu-ci",
208@@ -128,7 +128,7 @@
209 @mock.patch('ci_libs.utils.patch')
210 def test_add_new_ticket(self, mock_patch, mock_post, mock_process):
211 """Verify cli create_ticket command for one .changes."""
212- changes = self.get_test_file_path('foobar_0.1-1_source.changes')
213+ changes = testing.get_test_file_path('foobar_0.1-1_source.changes')
214 args = ['create_ticket', '-t', 'New feature', '-b', '1234', '-o',
215 'someone@example.com', '-d', 'This is a cool new feature',
216 '-a', 'foo', '-r', 'bar,baz', '-s', changes]
217@@ -148,8 +148,8 @@
218 def test_add_new_ticket_multiple_subtickets(self, mock_patch, mock_post,
219 mock_process):
220 """Verify cli create_ticket command for multiple .changes."""
221- changes_1 = self.get_test_file_path('foobar_0.1-1_source.changes')
222- changes_2 = self.get_test_file_path('barfoo_0.1-1_source.changes')
223+ changes_1 = testing.get_test_file_path('foobar_0.1-1_source.changes')
224+ changes_2 = testing.get_test_file_path('barfoo_0.1-1_source.changes')
225
226 args = ['create_ticket', '-t', '"New feature"', '-b', '4321', '-o',
227 'someone@example.com', '-d', '"This is a cool new feature"',
228@@ -289,7 +289,7 @@
229
230 def test_cli_only_source_files_pass(self):
231 """Verify cli fails in case file isn't prefixed .changes."""
232- wrong_changes = self.get_test_file_path('foobar_0.1-1.dsc')
233+ wrong_changes = testing.get_test_file_path('foobar_0.1-1.dsc')
234 args = ['create_ticket', '-t', '"New feature"', '-d',
235 '"This is a cool new feature"', '-o', 'someone@example.com',
236 '-a', 'foo', '-s', wrong_changes]
237@@ -306,7 +306,7 @@
238 return_value='http://www.example.com/api/v1/ticket/39/')
239 def test_is_valid_package_list_add_space(self, mock_patch):
240 """Test a ticket adding test binaries and not removing any fails."""
241- changes = self.get_test_file_path('foobar_0.1-1_source.changes')
242+ changes = testing.get_test_file_path('foobar_0.1-1_source.changes')
243 args = ['create_ticket', '-t', '"New feature"', '-d',
244 '"This is a cool new feature"', '-o', 'someone@example.com',
245 '-a', 'foo, bar', '-s', changes]
246@@ -323,7 +323,7 @@
247 return_value='http://www.example.com/api/v1/ticket/39/')
248 def test_is_valid_package_list_remove_space(self, mock_patch):
249 """Test a ticket removing two test binaries fails."""
250- changes = self.get_test_file_path('foobar_0.1-1_source.changes')
251+ changes = testing.get_test_file_path('foobar_0.1-1_source.changes')
252 args = ['create_ticket', '-t', '"New feature"', '-d',
253 '"This is a cool new feature"', '-o', 'someone@example.com',
254 '-a', 'foo', '-r', 'bar, baz', '-s', changes]
255@@ -345,7 +345,7 @@
256 return_value='http://www.example.com/api/v1/ticket/39/')
257 def test_cli_dsc_file_in_disguise(self, mock_patch, mock_load_config):
258 """Verify cli behavior when .changes file is a .dsc."""
259- wrong_changes = self.get_test_file_path('foobar_0.1-1_dsc.changes')
260+ wrong_changes = testing.get_test_file_path('foobar_0.1-1_dsc.changes')
261 args = ['create_ticket', '-t', '"New feature"', '-d',
262 '"This is a cool new feature"', '-o', 'someone@example.com',
263 '-a', 'foo', '-s', wrong_changes]
264@@ -364,7 +364,8 @@
265 def test_cli_changes_file_is_something_else(self, mock_patch,
266 mock_load_config):
267 """Verify cli behavior when provided .changes file isn't a .changes."""
268- wrong_changes = self.get_test_file_path('foobar_0.1-1_random.changes')
269+ wrong_changes = testing.get_test_file_path(
270+ 'foobar_0.1-1_random.changes')
271 args = ['create_ticket', '-t', '"New feature"', '-d',
272 '"This is a cool new feature"', '-o', 'someone@example.com',
273 '-a', 'foo', '-s', wrong_changes]
274@@ -383,7 +384,7 @@
275 def test_cli_changes_file_unsigned_fails(self, mock_patch,
276 mock_load_config):
277 """Verify cli behavior when provided .changes isn't signed."""
278- unsigned_changes = self.get_test_file_path(
279+ unsigned_changes = testing.get_test_file_path(
280 'foobar_0.1-1_unsigned.changes')
281 args = ['create_ticket', '-t', '"New feature"', '-d',
282 '"This is a cool new feature"', '-o', 'someone@example.com',
283@@ -403,7 +404,7 @@
284 def test_cli_changes_file_is_unreleased(self, mock_patch,
285 mock_load_config):
286 """Verify cli behavior when provided .changes file is UNRELEASED."""
287- wrong_changes = self.get_test_file_path(
288+ wrong_changes = testing.get_test_file_path(
289 'foobar_0.1-1_unreleased.changes')
290 args = ['create_ticket', '-t', '"New feature"', '-d',
291 '"This is a cool new feature"', '-o', 'someone@example.com',
292
293=== modified file 'cli/tests/test_ticket.py'
294--- cli/tests/test_ticket.py 2014-05-06 16:53:31 +0000
295+++ cli/tests/test_ticket.py 2014-05-07 16:48:40 +0000
296@@ -19,18 +19,18 @@
297 import mock
298 import imp
299
300+from ci_utils import testing
301 from ci_libs.ticket import (
302 SubTicket,
303 Ticket,
304 )
305-from ci_utils.testing import TestCaseWithGnupg
306-
307-
308-class SubTicketTestCase(TestCaseWithGnupg):
309-
310+
311+
312+class SubTicketTestCase(testing.TestCaseWithGnupg):
313 def setUp(self):
314 super(SubTicketTestCase, self).setUp()
315- self.changes = self.get_test_file_path('foobar_0.1-1_source.changes')
316+ self.changes = testing.get_test_file_path(
317+ 'foobar_0.1-1_source.changes')
318
319 @mock.patch('ci_libs.utils.post',
320 return_value='http://www.example.com/api/v1/sourcepackage/4/')
321@@ -79,7 +79,7 @@
322 new_subticket._create_subticket()
323
324
325-class TicketTestCase(TestCaseWithGnupg):
326+class TicketTestCase(testing.TestCaseWithGnupg):
327
328 def setUp(self):
329 super(TicketTestCase, self).setUp()
330@@ -91,7 +91,7 @@
331 @mock.patch('ci_libs.utils.post',
332 return_value='http://www.example.com/api/v1/ticket/38/')
333 def test_create_ticket(self, mock_post):
334- changes = self.get_test_file_path('foobar_0.1-1_source.changes')
335+ changes = testing.get_test_file_path('foobar_0.1-1_source.changes')
336 args = ['create_ticket', '-t', 'New feature', '-b', '1234', '-o',
337 'someone@example.com', '-d', 'This is a cool new feature',
338 '-a', 'foo', '-r', 'baz', '-s', changes]
339
340=== modified file 'juju-deployer/deploy.py'
341--- juju-deployer/deploy.py 2014-05-07 00:44:08 +0000
342+++ juju-deployer/deploy.py 2014-05-07 16:48:40 +0000
343@@ -17,8 +17,9 @@
344 import argparse
345 import atexit
346 import base64
347-from distutils import spawn
348+from distutils import spawn
349 import hashlib
350+import importlib
351 import itertools
352 import logging
353 import os
354@@ -375,15 +376,24 @@
355 sys.exit(1)
356
357
358-def check_dependencies():
359+def check_dependencies(needed_commands=None, needed_imports=None):
360 '''Exit the application if we are missing any dependency programs'''
361
362- needed_commands = ['cheetah']
363- for cmd in needed_commands:
364- if not spawn.find_executable(cmd):
365- err = "%s is missing. Please install it before continuing." % cmd
366- print >>sys.stderr, err
367- sys.exit(1)
368+ err = "%s is missing. Please install it before continuing."
369+ if needed_commands:
370+ for cmd in needed_commands:
371+ if not spawn.find_executable(cmd):
372+ err = err % cmd
373+ print >>sys.stderr, err
374+ sys.exit(1)
375+ if needed_imports:
376+ for impt in needed_imports:
377+ try:
378+ importlib.import_module(impt)
379+ except:
380+ err = err % impt
381+ print >>sys.stderr, err
382+ sys.exit(1)
383
384
385 def populate_all_templates():
386@@ -771,7 +781,7 @@
387 if args.private_ppas_only:
388 os.environ['CI_PRIVATE_PPAS_ONLY'] = '1'
389
390- check_dependencies()
391+ check_dependencies(needed_commands=['cheetah'])
392
393 if not args.build_only:
394 check_bootstrapped()
395
396=== modified file 'juju-deployer/test_deploy.py'
397--- juju-deployer/test_deploy.py 2014-05-06 21:33:18 +0000
398+++ juju-deployer/test_deploy.py 2014-05-07 16:48:40 +0000
399@@ -14,8 +14,9 @@
400 # You should have received a copy of the GNU Affero General Public License
401 # along with this program. If not, see <http://www.gnu.org/licenses/>.
402
403+import os
404+import sys
405 import mock
406-import os
407 import tempfile
408 import shutil
409 import subprocess
410@@ -108,13 +109,20 @@
411 super(TestCheckDependencies, self).setUp()
412 fixtures.set_uniq_cwd(self)
413
414- def test_check_dependencies_fails(self):
415- # check_dependencies bails out if it can't find the (executables)
416- # project dependencies.
417+ def test_check_dependencies_needed_commands(self):
418+ # If we cannot find any of our dependencies, this program should bail
419+ # out.
420 fixtures.isolate_from_env(self, dict(PATH=''))
421 with mock.patch('sys.stderr'):
422 with self.assertRaises(SystemExit):
423- deploy.check_dependencies()
424+ deploy.check_dependencies(needed_commands=['cheetah'])
425+
426+ def test_check_dependencies_needed_imports(self):
427+ # If we cannot find any of our import dependencies, this program should
428+ # bail out.
429+ with mock.patch('sys.stderr'):
430+ with self.assertRaises(SystemExit):
431+ deploy.check_dependencies(needed_imports=['IDONTEXIST'])
432
433
434 class TestBootStrap(unittest.TestCase):
435
436=== modified file 'tests/deployers.py'
437--- tests/deployers.py 2014-04-29 16:03:15 +0000
438+++ tests/deployers.py 2014-05-07 16:48:40 +0000
439@@ -17,17 +17,15 @@
440 import os
441 import subprocess
442 import sys
443-import unittest
444
445+import yaml
446+import amulet
447
448 HERE = os.path.abspath(os.path.dirname(__file__))
449 # We need access to ci_utils
450 sys.path.append(os.path.join(HERE, '..', 'ci-utils'))
451
452-import amulet
453-from ci_utils.tests import features
454-import yaml
455-
456+from ci_utils.testing import features, TestCaseWithGnupg
457
458
459 class AmuletDeployment(object):
460@@ -65,7 +63,7 @@
461
462
463 @features.requires(features.bootstrapped_juju)
464-class DeployerTest(unittest.TestCase):
465+class DeployerTest(TestCaseWithGnupg):
466 '''Base class for building juju deployer based tests.'''
467
468 deployer_cfg = None
469
470=== modified file 'tests/run.py'
471--- tests/run.py 2014-04-28 14:45:39 +0000
472+++ tests/run.py 2014-05-07 16:48:40 +0000
473@@ -139,7 +139,7 @@
474 # named like the component, we keep matching on that.
475 for one in only:
476 file_name = 'test_{}.py'.format(one)
477- if file_name in tests:
478+ if file_name in tests:
479 selected.append(file_name)
480 else:
481 msg = "Skipping {} as {} does not exist in {}"
482@@ -219,6 +219,7 @@
483
484 def main():
485 check_nova_env()
486+ deploy.check_dependencies(needed_imports=['gnupg'])
487
488 test_dir = os.path.dirname(sys.argv[0])
489 tests = get_tests(test_dir)
490
491=== modified file 'tests/test_integration.py'
492--- tests/test_integration.py 2014-04-16 18:36:03 +0000
493+++ tests/test_integration.py 2014-05-07 16:48:40 +0000
494@@ -15,6 +15,7 @@
495 # along with this program. If not, see <http://www.gnu.org/licenses/>.
496
497 import os
498+import sys
499 import json
500 import tempfile
501 import subprocess
502@@ -25,8 +26,10 @@
503
504 import deployers
505
506-
507 HERE = os.path.abspath(os.path.dirname(__file__))
508+sys.path.append(os.path.join(HERE, '..', 'ci-utils'))
509+
510+from ci_utils import testing
511
512
513 def create_virtual_env():
514@@ -42,8 +45,7 @@
515 def run_virtual_env(temp_dir, args, cwd=None):
516 if args is 'create':
517 cwd = os.path.join(HERE, '../cli')
518- changes = os.path.abspath(os.path.join(HERE,
519- '../cli/tests/data/foobar_0.1-1_source.changes'))
520+ changes = testing.get_test_file_path('foobar_0.1-1_source.changes')
521 args = ('python ubuntu-ci create_ticket -t "New feature" -b 1234 -o '
522 'someone@example.com -d "This is a cool new feature" -a foo '
523 '-s %s' % changes)
524@@ -69,8 +71,8 @@
525 p = os.path.join(HERE, '../cli/setup.py')
526 args = '%s develop' % p
527 run_virtual_env(self.temp_dir, args)
528- config_url = 'http://{}:{}'
529- config_url = config_url.format(*self.get_ip_and_port('ts-django'))
530+ config_url = 'http://{}'.format(
531+ self.get_ip_and_port('webui-apache')[0])
532 config = os.path.join(os.environ["HOME"], '.ubuntu-ci')
533 with open(config, 'a') as fp:
534 fp.write('ci_url: "{}"\n'.format(config_url))
535@@ -78,8 +80,8 @@
536 run_virtual_env(self.temp_dir, args='create')
537 self.addCleanup(delete_virtual_env, self.temp_dir)
538
539- def get_server_status_and_content(self, url, service='ts-django'):
540- final_url = url.format(*self.get_ip_and_port(service))
541+ def get_server_status_and_content(self, url, service='webui-apache'):
542+ final_url = url.format(self.get_ip_and_port(service)[0])
543
544 client = httplib2.Http()
545 resp, content = client.request(final_url, 'GET')
546@@ -91,7 +93,7 @@
547 up with the proper status when viewed via the API.
548 """
549
550- url = 'http://{}:{}/api/v1/ticket/1/'
551+ url = 'http://{}/api/v1/ticket/1/'
552 resp, content = self.get_server_status_and_content(url)
553 content = json.loads(content)
554 self.assertEqual(resp['status'], '200')
555@@ -103,12 +105,11 @@
556 This tests that the WebUI main page shows the ticket that we created
557 via the CLI
558 """
559- url = 'http://{}:{}/'
560- resp, content = self.get_server_status_and_content(
561- url, service='webui-apache')
562+ url = 'http://{}/'
563+ resp, content = self.get_server_status_and_content(url)
564
565 self.assertEqual(resp['status'], '200')
566- self.assertIn('<a href="/" class="first ">Ticket List</a>', content)
567+ self.assertIn('<a href="/" class="first active">Tickets</a>', content)
568
569
570 if __name__ == "__main__":

Subscribers

People subscribed via source and target branches