Merge lp:~rvb/maas-test/display-maas-version into lp:maas-test

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: 104
Merged at revision: 109
Proposed branch: lp:~rvb/maas-test/display-maas-version
Merge into: lp:maas-test
Diff against target: 132 lines (+73/-2)
4 files modified
maastest/maasfixture.py (+8/-1)
maastest/tests/test_maasfixture.py (+31/-0)
maastest/tests/test_utils.py (+18/-0)
maastest/utils.py (+16/-1)
To merge this branch: bzr merge lp:~rvb/maas-test/display-maas-version
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+200863@code.launchpad.net

Commit message

Display the version of MAAS to be installed.

Description of the change

It would be nice to also display the source of the package but this is a start and should be good enough for now.

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

 review: approve

Looks good, thanks for doing this very useful change. Just a couple
of small comments:

> === modified file 'maastest/tests/test_maasfixture.py' ---
> maastest/tests/test_maasfixture.py 2013-12-18 12:04:41 +0000 +++
> maastest/tests/test_maasfixture.py 2014-01-08 16:22:42 +0000 @@
> -335,6 +335,44 @@ check_call=True), )
>
> + def test_install_maas_logs_maas_version(self): +
> fixture = self.make_kvm_fixture() + maas_fixture =
> self.make_maas_fixture(fixture) + version =
> self.getUniqueString() + mock_get_maas_version =
> mock.MagicMock(return_value=version) +
> self.patch(maas_fixture, 'get_maas_version',
> mock_get_maas_version)

Because the mock is returned from patch(), you can avoid importing
MagickMock and just do:

   self.patch(maas_fixture, 'get_maas_version').return_value = version

> + mock_logging = mock.MagicMock() +
> self.patch(maasfixture.logging, 'info', mock_logging)

And this can be:

   mock_logging = self.patch(maasfixture.logging, 'info')

> + maas_fixture.install_maas() + + self.assertEqual( +
> ( + [mock.call()], + [ +
> mock.call("Installing MAAS (version %s)..." % version), +
> mock.call("Done installing MAAS."), + ]), +
> (mock_get_maas_version.mock_calls, mock_logging.mock_calls))

I think this is definitely a case where having more than one assertion
is better than compounding them into a single call. This is extremely
hard to read and digest. And ease of reading trumps everything else!

> + + def test_get_maas_version_returns_maas_version(self): +
> fixture = self.make_kvm_fixture() + maas_fixture =
> self.make_maas_fixture(fixture) + version =
> self.getUniqueString() + policy = "Candidate: %s\n" %
> version + self.patch(fixture, 'run_command',
> mock.MagicMock( + return_value=(0, policy, b'stderr')))
> + + extracted_version = maas_fixture.get_maas_version() + +
> fixture.run_command.assert_has_call( + mock.call( +
> maas_fixture.kvm_fixture._make_apt_get_install_command( +
> ['language-pack-en']), + check_call=True), +
> )

You could make this easier to read by assigning a variable to the
result of mock.call() and using that in the assert_has_call.

Cheers!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlLN8WUACgkQWhGlTF8G/HcjiQCffd/lSuhJw3fupbpVCefJLGuQ
eSEAn1YZRK6NYjQxqqARnVYeifwSGl+/
=CJXi
-----END PGP SIGNATURE-----

review: Approve
104. By Raphaël Badin

Review fixes.

Revision history for this message
Raphaël Badin (rvb) wrote :

 > Because the mock is returned from patch(), you can avoid importing
> MagickMock and just do:
>
>[...]

Well, actually, the mock object is *not* returned by patch(…). In MAAS it is, see src/maastesting/testcase.py:MAASTestCase.patch. But in maas-test, we don't have that utility

>
> > + maas_fixture.install_maas() + + self.assertEqual( +
> > ( + [mock.call()], + [ +
> > mock.call("Installing MAAS (version %s)..." % version), +
> > mock.call("Done installing MAAS."), + ]), +
> > (mock_get_maas_version.mock_calls, mock_logging.mock_calls))
>
> I think this is definitely a case where having more than one assertion
> is better than compounding them into a single call. This is extremely
> hard to read and digest. And ease of reading trumps everything else!

All right, you know I'm a sucker for compound assertions but in this instance, you're definitely right.

> [...]
> You could make this easier to read by assigning a variable to the
> result of mock.call() and using that in the assert_has_call.

Actually, I've refactored that code a bit and it's now a bit simpler.

Thanks for the review!

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 09/01/14 18:40, Raphaël Badin wrote:
> > Because the mock is returned from patch(), you can avoid importing
>> MagickMock and just do:
>>
>> [...]
>
> Well, actually, the mock object is *not* returned by patch(…). In MAAS it is, see src/maastesting/testcase.py:MAASTestCase.patch. But in maas-test, we don't have that utility

Ah! That's probably worth adding as a small change next time you're in
this code then.

> Thanks for the review!

NP.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'maastest/maasfixture.py'
--- maastest/maasfixture.py 2014-01-08 17:31:43 +0000
+++ maastest/maasfixture.py 2014-01-09 08:39:45 +0000
@@ -99,14 +99,21 @@
99 # Install the English language pack first. If this is not done99 # Install the English language pack first. If this is not done
100 # before postgres is installed, on some systems it won't be able to100 # before postgres is installed, on some systems it won't be able to
101 # set up its main cluster.101 # set up its main cluster.
102 maas_version = self.get_maas_version()
103 logging.info("Installing MAAS (version %s)..." % maas_version)
102 # TODO: Is there no better way to ensure this, e.g. through a104 # TODO: Is there no better way to ensure this, e.g. through a
103 # dependency?105 # dependency?
104 logging.info("Installing MAAS...")
105 self.kvm_fixture.install_packages(['language-pack-en'])106 self.kvm_fixture.install_packages(['language-pack-en'])
106 # Now we can install maas (which also installs postgres).107 # Now we can install maas (which also installs postgres).
107 self.kvm_fixture.install_packages(['maas', 'maas-dhcp', 'maas-dns'])108 self.kvm_fixture.install_packages(['maas', 'maas-dhcp', 'maas-dns'])
108 logging.info("Done installing MAAS.")109 logging.info("Done installing MAAS.")
109110
111 def get_maas_version(self):
112 """Return the version of MAAS that is to be installed."""
113 _, policy, _ = self.kvm_fixture.run_command(
114 ['apt-cache', 'policy', 'maas'], check_call=True)
115 return utils.extract_package_version(policy)
116
110 def configure_default_maas_url(self):117 def configure_default_maas_url(self):
111 """Set `DEFAULT_MAAS_URL` in the virtual machine.118 """Set `DEFAULT_MAAS_URL` in the virtual machine.
112119
113120
=== modified file 'maastest/tests/test_maasfixture.py'
--- maastest/tests/test_maasfixture.py 2014-01-08 17:31:43 +0000
+++ maastest/tests/test_maasfixture.py 2014-01-09 08:39:45 +0000
@@ -335,6 +335,37 @@
335 check_call=True),335 check_call=True),
336 )336 )
337337
338 def test_install_maas_logs_maas_version(self):
339 fixture = self.make_kvm_fixture()
340 maas_fixture = self.make_maas_fixture(fixture)
341 version = self.getUniqueString()
342 mock_get_maas_version = mock.MagicMock(return_value=version)
343 self.patch(maas_fixture, 'get_maas_version', mock_get_maas_version)
344 mock_logging = mock.MagicMock()
345 self.patch(maasfixture.logging, 'info', mock_logging)
346
347 maas_fixture.install_maas()
348
349 self.assertEqual([mock.call()], mock_get_maas_version.mock_calls)
350 self.assertEqual(
351 [
352 mock.call("Installing MAAS (version %s)..." % version),
353 mock.call("Done installing MAAS."),
354 ],
355 mock_logging.mock_calls)
356
357 def test_get_maas_version_returns_maas_version(self):
358 fixture = self.make_kvm_fixture()
359 maas_fixture = self.make_maas_fixture(fixture)
360 version = self.getUniqueString()
361 policy = "Candidate: %s\n" % version
362 self.patch(fixture, 'run_command', mock.MagicMock(
363 return_value=(0, policy, b'stderr')))
364
365 extracted_version = maas_fixture.get_maas_version()
366
367 self.assertEqual(version, extracted_version)
368
338 def test_install_maas_installs_language_pack_followed_by_maas(self):369 def test_install_maas_installs_language_pack_followed_by_maas(self):
339 # We need to do it in this order, or postgres (and other things) may370 # We need to do it in this order, or postgres (and other things) may
340 # break during installation.371 # break during installation.
341372
=== modified file 'maastest/tests/test_utils.py'
--- maastest/tests/test_utils.py 2014-01-08 17:49:09 +0000
+++ maastest/tests/test_utils.py 2014-01-09 08:39:45 +0000
@@ -412,3 +412,21 @@
412 stream.foo_bar_baz = mock.MagicMock(return_value=some_string)412 stream.foo_bar_baz = mock.MagicMock(return_value=some_string)
413 caching_stream = utils.CachingOutputStream(stream)413 caching_stream = utils.CachingOutputStream(stream)
414 self.assertEqual(some_string, caching_stream.foo_bar_baz())414 self.assertEqual(some_string, caching_stream.foo_bar_baz())
415
416
417class TestExtractPackageVersion(testtools.TestCase):
418
419 def test_extracts_package_version(self):
420 version = '1.4+bzr1693+dfsg-0ubuntu2.2'
421 policy = dedent("""
422 maas:
423 Installed: (none)
424 Candidate: %s
425 Version table:
426 1.4+bzr1693+dfsg-0ubuntu2.2 0
427 500 http://example.com/ubuntu/ saucy/main amd64 Packages
428 """) % version
429 self.assertEqual(version, utils.extract_package_version(policy))
430
431 def test_returns_None_if_policy_is_unparseable(self):
432 self.assertIsNone(utils.extract_package_version("unparsable"))
415433
=== modified file 'maastest/utils.py'
--- maastest/utils.py 2014-01-09 07:19:20 +0000
+++ maastest/utils.py 2014-01-09 08:39:45 +0000
@@ -25,11 +25,12 @@
25 ]25 ]
2626
2727
28import inspect
28from io import BytesIO29from io import BytesIO
29import inspect
30import logging30import logging
31from pipes import quote31from pipes import quote
32import platform32import platform
33import re
33from subprocess import (34from subprocess import (
34 PIPE,35 PIPE,
35 Popen,36 Popen,
@@ -256,6 +257,20 @@
256 return True257 return True
257258
258259
260def extract_package_version(policy):
261 """Get the version of the package to be installed from policy settings.
262
263 The given policy is assumed to be of the form returned by running:
264 `apt-cache policy <packagename>`. This method returns None if the
265 given policy string cannot be parsed.
266 """
267 match = re.search('Candidate: (.*)\n', policy)
268 if match is not None:
269 return match.group(1)
270 else:
271 return None
272
273
259def virtualization_type():274def virtualization_type():
260 """Returns the name of the virtualization type of this machine.275 """Returns the name of the virtualization type of this machine.
261276

Subscribers

People subscribed via source and target branches