Merge lp:~elopio/u1-test-utils/configglue into lp:u1-test-utils

Proposed by Leo Arias
Status: Superseded
Proposed branch: lp:~elopio/u1-test-utils/configglue
Merge into: lp:u1-test-utils
Prerequisite: lp:~elopio/u1-test-utils/make_unique_user_test
Diff against target: 516 lines (+185/-203)
10 files modified
requirements.txt (+2/-1)
u1testutils/__init__.py (+2/-51)
u1testutils/schema.py (+33/-0)
u1testutils/selftests/unit/test_settings.py (+69/-0)
u1testutils/selftests/unit/test_utils.py (+0/-96)
u1testutils/settings.py (+54/-0)
u1testutils/sso/data.py (+4/-1)
u1testutils/sso/environment.py (+4/-1)
u1testutils/sso/selftests/unit/test_data.py (+17/-52)
u1testutils/sso/sst/__init__.py (+0/-1)
To merge this branch: bzr merge lp:~elopio/u1-test-utils/configglue
Reviewer Review Type Date Requested Status
Canonical ISD hackers Pending
Review via email: mp+161373@code.launchpad.net

This proposal has been superseded by a proposal from 2013-05-03.

Commit message

If django is not installed, use u1testutils settings from the XDG config directory.

Description of the change

As we will start testing desktop applications that have nothing to do with django, we need a different way to specify the configuration parameters.
Here I propose to use a specific u1testutils file stored in one of the XDG config directories to load the values.
django_configglue doesn't depend on django, and with it we can get the values easily in the same format as we do for the django projects, so it's a nice fit.

To post a comment you must log in.
lp:~elopio/u1-test-utils/configglue updated
70. By Leo Arias

Use configglue, django_configlue is not needed.

Revision history for this message
Leo Arias (elopio) wrote :

I misuderstood configglue docs, we actually don't need django_configglue :)

lp:~elopio/u1-test-utils/configglue updated
71. By Leo Arias

Copied the last bits of django configglue.

72. By Leo Arias

Allow to get the SSO_BASE_URL from u1testutils config too.

73. By Leo Arias

Added the openid section.

74. By Leo Arias

Use a var for the settings.

75. By Leo Arias

Joined the tests. Moved the file creation to set up.

76. By Leo Arias

Cleanup.

77. By Leo Arias

Cleanup.

78. By Leo Arias

The update must be inside the patched section.

79. By Leo Arias

No reason to call it get_django_settings now.

80. By Leo Arias

Merged with prerequisite branch.

81. By Leo Arias

Added the ubuntuone server url config option.

Unmerged revisions

81. By Leo Arias

Added the ubuntuone server url config option.

80. By Leo Arias

Merged with prerequisite branch.

79. By Leo Arias

No reason to call it get_django_settings now.

78. By Leo Arias

The update must be inside the patched section.

77. By Leo Arias

Cleanup.

76. By Leo Arias

Cleanup.

75. By Leo Arias

Joined the tests. Moved the file creation to set up.

74. By Leo Arias

Use a var for the settings.

73. By Leo Arias

Added the openid section.

72. By Leo Arias

Allow to get the SSO_BASE_URL from u1testutils config too.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'requirements.txt'
2--- requirements.txt 2013-05-03 03:02:25 +0000
3+++ requirements.txt 2013-05-03 03:02:25 +0000
4@@ -1,10 +1,11 @@
5 # Packages.
6 beautifulsoup4
7+configglue
8+dirspec
9 django==1.4
10 mock
11 pep8
12 pyflakes
13-testtools
14 Twisted
15 bzr+ssh://bazaar.launchpad.net/~bloodearnest/localmail/trunk
16 bzr+http://bazaar.launchpad.net/~ubuntuone-hackers/payclient/trunk@4
17
18=== modified file 'u1testutils/__init__.py'
19--- u1testutils/__init__.py 2013-05-03 03:02:25 +0000
20+++ u1testutils/__init__.py 2013-05-03 03:02:25 +0000
21@@ -1,4 +1,4 @@
22-# Copyright 2013 Canonical Ltd.
23+# Copyright 2012, 2013 Canonical Ltd.
24 #
25 # This program is free software: you can redistribute it and/or modify it
26 # under the terms of the GNU Lesser General Public License version 3, as
27@@ -10,55 +10,6 @@
28 # PURPOSE. See the GNU Lesser General Public License for more details.
29 #
30 # You should have received a copy of the GNU General Public License along
31-# with this program. If not, see <http://www.gnu.org/licenses/>.
32+# with this program. If not, see <http://www.gnu.org/licenses/
33
34 __version__ = '0.3.1'
35-
36-import importlib
37-import os
38-import shutil
39-import sys
40-import tempfile
41-
42-import mock
43-
44-
45-def set_cwd_to_tmp(test):
46- """Create a temp dir an cd into it for the test duration.
47-
48- This is generally called during a test setup.
49-
50- The code for this function was taken from
51- https://code.launchpad.net/selenium=simple-test
52- """
53- test.test_base_dir = tempfile.mkdtemp(prefix='mytests-', suffix='.tmp')
54- test.addCleanup(shutil.rmtree, test.test_base_dir, True)
55- current_dir = os.getcwdu()
56- test.addCleanup(os.chdir, current_dir)
57- os.chdir(test.test_base_dir)
58-
59-
60-def protect_imports(test):
61- """Protect sys.modules and sys.path for the test duration.
62-
63- This is useful to test imports which modifies sys.modules or requires
64- modifying sys.path.
65-
66- The code for this function was based on the protect_imports from
67- https://code.launchpad.net/~vila/selenium-simple-test/test-loader
68- """
69- # Protect sys.modules and sys.path to be able to test imports
70- patcher = mock.patch('sys.path', list(sys.path))
71- test.addCleanup(patcher.stop)
72- patcher.start()
73- orig_modules = sys.modules.copy()
74-
75- def cleanup_modules():
76- # Remove all added modules
77- added = [m for m in sys.modules.keys() if m not in orig_modules]
78- if added:
79- for m in added:
80- del sys.modules[m]
81- # Restore deleted or modified modules
82- sys.modules.update(orig_modules)
83- test.addCleanup(cleanup_modules)
84
85=== added file 'u1testutils/schema.py'
86--- u1testutils/schema.py 1970-01-01 00:00:00 +0000
87+++ u1testutils/schema.py 2013-05-03 03:02:25 +0000
88@@ -0,0 +1,33 @@
89+# Copyright 2013 Canonical Ltd.
90+#
91+# This program is free software: you can redistribute it and/or modify it
92+# under the terms of the GNU Lesser General Public License version 3, as
93+# published by the Free Software Foundation.
94+#
95+# This program is distributed in the hope that it will be useful, but
96+# WITHOUT ANY WARRANTY; without even the implied warranties of
97+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
98+# PURPOSE. See the GNU Lesser General Public License for more details.
99+#
100+# You should have received a copy of the GNU General Public License along
101+# with this program. If not, see <http://www.gnu.org/licenses/
102+
103+from configglue import schema
104+
105+
106+class SSOSchema(schema.Schema):
107+
108+ class testing(schema.Section):
109+ sso_test_account_full_name = schema.StringOption()
110+ sso_test_account_email = schema.StringOption()
111+ sso_test_account_password = schema.StringOption()
112+ email_address_pattern = schema.StringOption(raw=True)
113+
114+
115+class U1TestUtilsSchema(schema.Schema):
116+
117+ class openid(schema.Section):
118+ openid_sso_server_url = schema.StringOption()
119+
120+
121+schema = schema.merge(SSOSchema, U1TestUtilsSchema)
122
123=== added file 'u1testutils/selftests/unit/test_settings.py'
124--- u1testutils/selftests/unit/test_settings.py 1970-01-01 00:00:00 +0000
125+++ u1testutils/selftests/unit/test_settings.py 2013-05-03 03:02:25 +0000
126@@ -0,0 +1,69 @@
127+# Copyright 2013 Canonical Ltd.
128+#
129+# This program is free software: you can redistribute it and/or modify it
130+# under the terms of the GNU Lesser General Public License version 3, as
131+# published by the Free Software Foundation.
132+#
133+# This program is distributed in the hope that it will be useful, but
134+# WITHOUT ANY WARRANTY; without even the implied warranties of
135+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
136+# PURPOSE. See the GNU Lesser General Public License for more details.
137+#
138+# You should have received a copy of the GNU General Public License along
139+# with this program. If not, see <http://www.gnu.org/licenses/>.
140+
141+import importlib
142+import os
143+import shutil
144+import sys
145+import tempfile
146+import unittest
147+
148+import mock
149+
150+from u1testutils import schema
151+
152+
153+class SettingsTestCase(unittest.TestCase):
154+
155+ def setUp(self):
156+ super(SettingsTestCase, self).setUp()
157+ settings = (
158+ '[testing]\n'
159+ 'sso_test_account_full_name = Test name\n'
160+ 'sso_test_account_email = email@example.com\n'
161+ 'sso_test_account_password = test password\n'
162+ 'email_address_pattern = email+%s@example.com\n'
163+ '[openid]\n'
164+ 'openid_sso_server_url = http://example.com\n'
165+ )
166+ self.config_home = tempfile.mkdtemp()
167+ self.addCleanup(shutil.rmtree, self.config_home)
168+ self._make_home_config_file(settings)
169+
170+ def _make_home_config_file(self, settings):
171+ config_directory = os.path.join(self.config_home, 'u1testutils')
172+ os.mkdir(config_directory)
173+ self.config_file_path = os.path.join(
174+ config_directory, 'u1testutils.conf')
175+ with open(self.config_file_path, 'w') as config_file:
176+ config_file.write(settings)
177+
178+ def _update_settings(self, settings):
179+ settings.configglue(schema.schema, settings.get_config_file())
180+
181+ def test_options(self):
182+ needs_update = 'u1testutils.settings' in sys.modules
183+ with mock.patch.dict(
184+ 'os.environ', {'XDG_CONFIG_HOME': self.config_home}):
185+ settings = importlib.import_module('u1testutils.settings')
186+ if needs_update:
187+ self.addCleanup(self._update_settings, settings)
188+ self._update_settings(settings)
189+
190+ self.assertEqual(settings.SSO_TEST_ACCOUNT_FULL_NAME, 'Test name')
191+ self.assertEqual(settings.SSO_TEST_ACCOUNT_EMAIL, 'email@example.com')
192+ self.assertEqual(settings.SSO_TEST_ACCOUNT_PASSWORD, 'test password')
193+ self.assertEqual(
194+ settings.EMAIL_ADDRESS_PATTERN, 'email+%s@example.com')
195+ self.assertEqual(settings.OPENID_SSO_SERVER_URL, 'http://example.com')
196
197=== removed file 'u1testutils/selftests/unit/test_utils.py'
198--- u1testutils/selftests/unit/test_utils.py 2013-05-03 03:02:25 +0000
199+++ u1testutils/selftests/unit/test_utils.py 1970-01-01 00:00:00 +0000
200@@ -1,96 +0,0 @@
201-import os
202-import sys
203-import tempfile
204-
205-import testtools
206-from testtools.matchers import MatchesRegex
207-
208-import u1testutils
209-
210-
211-class TestTempCurrentWorkDirectory(testtools.TestCase):
212-
213- def setUp(self):
214- super(TestTempCurrentWorkDirectory, self).setUp()
215- self.original_cwd = os.getcwdu()
216-
217- def test_cwd_set_to_tmp(self):
218- self.addCleanup(self._assert_cwd_restored)
219- self.addCleanup(self._assert_tmp_directory_deleted)
220- u1testutils.set_cwd_to_tmp(self)
221-
222- cwd = os.getcwdu()
223- expected_regex = '{0}/mytests-.+\.tmp'.format(tempfile.gettempdir())
224- self.assertThat(cwd, MatchesRegex(expected_regex))
225-
226- def _assert_cwd_restored(self):
227- cwd = os.getcwdu()
228- self.assertEqual(cwd, self.original_cwd)
229-
230- def _assert_tmp_directory_deleted(self):
231- self.assertFalse(os.path.isdir(self.test_base_dir))
232-
233-
234-class TestProtectImports(testtools.TestCase):
235- # The code for this test case was taken from
236- # https://code.launchpad.net/~vila/selenium-simple-test/test-loader
237-
238- def setUp(self):
239- super(TestProtectImports, self).setUp()
240- u1testutils.protect_imports(self)
241-
242- def run_successful_test(self, test):
243- result = testtools.TestResult()
244- test.run(result)
245- self.assertTrue(result.wasSuccessful())
246-
247- def test_add_module(self):
248- self.assertIs(None, sys.modules.get('foo', None))
249-
250- class Test(testtools.TestCase):
251-
252- def test_it(self):
253- u1testutils.protect_imports(self)
254- sys.modules['foo'] = 'bar'
255-
256- self.run_successful_test(Test('test_it'))
257- self.assertIs(None, sys.modules.get('foo', None))
258-
259- def test_remove_module(self):
260- self.assertIs(None, sys.modules.get('I_dont_exist', None))
261- sys.modules['I_dont_exist'] = 'bar'
262-
263- class Test(testtools.TestCase):
264-
265- def test_it(self):
266- u1testutils.protect_imports(self)
267- self.assertEqual('bar', sys.modules['I_dont_exist'])
268- del sys.modules['I_dont_exist']
269- self.run_successful_test(Test('test_it'))
270- self.assertEqual('bar', sys.modules['I_dont_exist'])
271-
272- def test_modify_module(self):
273- self.assertIs(None, sys.modules.get('I_dont_exist', None))
274- sys.modules['I_dont_exist'] = 'bar'
275-
276- class Test(testtools.TestCase):
277-
278- def test_it(self):
279- u1testutils.protect_imports(self)
280- self.assertEqual('bar', sys.modules['I_dont_exist'])
281- sys.modules['I_dont_exist'] = 'qux'
282- self.run_successful_test(Test('test_it'))
283- self.assertEqual('bar', sys.modules['I_dont_exist'])
284-
285- def test_sys_path_restored(self):
286- u1testutils.set_cwd_to_tmp(self)
287- inserted = self.test_base_dir
288- self.assertFalse(inserted in sys.path)
289-
290- class Test(testtools.TestCase):
291-
292- def test_it(self):
293- u1testutils.protect_imports(self)
294- sys.path.insert(0, inserted)
295- self.run_successful_test(Test('test_it'))
296- self.assertFalse(inserted in sys.path)
297
298=== added file 'u1testutils/settings.py'
299--- u1testutils/settings.py 1970-01-01 00:00:00 +0000
300+++ u1testutils/settings.py 2013-05-03 03:02:25 +0000
301@@ -0,0 +1,54 @@
302+# Copyright 2013 Canonical Ltd.
303+#
304+# This program is free software: you can redistribute it and/or modify it
305+# under the terms of the GNU Lesser General Public License version 3, as
306+# published by the Free Software Foundation.
307+#
308+# This program is distributed in the hope that it will be useful, but
309+# WITHOUT ANY WARRANTY; without even the implied warranties of
310+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
311+# PURPOSE. See the GNU Lesser General Public License for more details.
312+#
313+# You should have received a copy of the GNU General Public License along
314+# with this program. If not, see <http://www.gnu.org/licenses/
315+
316+import os.path
317+import sys
318+
319+from dirspec import basedir
320+from configglue import parser
321+
322+from u1testutils import schema
323+
324+
325+CONFIG_FILE = 'u1testutils.conf'
326+SETTINGS_ENCODING = 'utf-8'
327+
328+
329+def configglue(schema_class, configs):
330+ scp = parser.SchemaConfigParser(schema_class())
331+ scp.read(configs)
332+ _update_settings(scp)
333+
334+
335+def _update_settings(parser):
336+ settings = _get_uppercase_settings(parser)
337+ target = sys.modules[__name__]
338+ for name, value in settings.items():
339+ setattr(target, name, value)
340+
341+
342+def _get_uppercase_settings(parser):
343+ result = {}
344+ for section, data in parser.values().items():
345+ for option, value in data.items():
346+ result[option.upper()] = value.encode(SETTINGS_ENCODING)
347+ return result
348+
349+
350+def get_config_file():
351+ xdg_config_dir = basedir.load_first_config('u1testutils')
352+ return os.path.join(xdg_config_dir, CONFIG_FILE)
353+
354+
355+configglue(schema.schema, get_config_file())
356
357=== modified file 'u1testutils/sso/data.py'
358--- u1testutils/sso/data.py 2013-04-09 19:06:01 +0000
359+++ u1testutils/sso/data.py 2013-05-03 03:02:25 +0000
360@@ -14,7 +14,10 @@
361
362 import uuid
363
364-from django.conf import settings
365+try:
366+ from django.conf import settings
367+except ImportError:
368+ from u1testutils import settings
369
370 from u1testutils.sso import client
371
372
373=== modified file 'u1testutils/sso/environment.py'
374--- u1testutils/sso/environment.py 2013-04-09 19:06:01 +0000
375+++ u1testutils/sso/environment.py 2013-05-03 03:02:25 +0000
376@@ -12,7 +12,10 @@
377 # You should have received a copy of the GNU General Public License along
378 # with this program. If not, see <http://www.gnu.org/licenses/>.
379
380-from django.conf import settings
381+try:
382+ from django.conf import settings
383+except ImportError:
384+ from u1testutils import settings
385
386
387 def get_sso_base_url(default='http://localhost:8000'):
388
389=== modified file 'u1testutils/sso/selftests/unit/test_data.py'
390--- u1testutils/sso/selftests/unit/test_data.py 2013-05-03 03:02:25 +0000
391+++ u1testutils/sso/selftests/unit/test_data.py 2013-05-03 03:02:25 +0000
392@@ -14,14 +14,11 @@
393 # You should have received a copy of the GNU General Public License along
394 # with this program. If not, see <http://www.gnu.org/licenses/
395
396-import os
397-import sys
398-import tempfile
399 import unittest
400
401 from mock import patch
402
403-import u1testutils
404+import u1testutils.django
405 from u1testutils.sso import data
406
407
408@@ -36,62 +33,32 @@
409 self.assertEqual(user.email, 'test+test_uuid@example.com')
410 self.assertEqual(user.password, 'Hola123*')
411
412- def _make_django_settings_file(self, settings):
413- u1testutils.set_cwd_to_tmp(self)
414- cwd = os.getcwdu()
415- sys.path.insert(0, cwd)
416- settings_file = tempfile.NamedTemporaryFile(
417- suffix='.py', dir=cwd, delete=False)
418- with settings_file:
419- settings_file.write(settings)
420- settings_module_name = os.path.splitext(
421- os.path.basename(settings_file.name))[0]
422- return settings_module_name
423-
424- def _reload_data_module(self):
425- for module in (
426- 'u1testutils.sso.data',
427- 'django.conf',
428- 'django.conf.global_settings'):
429- if module in sys.modules:
430- del sys.modules[module]
431- import u1testutils.sso.data
432- return u1testutils.sso.data
433-
434 def test_make_exising_user_from_configuration(self):
435- u1testutils.protect_imports(self)
436- settings = ('SSO_TEST_ACCOUNT_FULL_NAME = "Test existing name"\n'
437- 'SSO_TEST_ACCOUNT_EMAIL = "existingemail@test.com"\n'
438- 'SSO_TEST_ACCOUNT_PASSWORD = "test existing password"\n')
439- settings_module = self._make_django_settings_file(settings)
440- with patch.dict(
441- 'os.environ', {'DJANGO_SETTINGS_MODULE': settings_module}):
442- data = self._reload_data_module()
443+ with u1testutils.django.patch_settings(
444+ SSO_TEST_ACCOUNT_FULL_NAME='Test existing name',
445+ SSO_TEST_ACCOUNT_EMAIL='existingemail@example.com',
446+ SSO_TEST_ACCOUNT_PASSWORD='existing password'):
447 user = data.User.make_from_configuration()
448
449 self.assertEqual(user.full_name, 'Test existing name')
450- self.assertEqual(user.email, 'existingemail@test.com')
451- self.assertEqual(user.password, 'test existing password')
452+ self.assertEqual(user.email, 'existingemail@example.com')
453+ self.assertEqual(user.password, 'existing password')
454
455 def test_make_new_user_from_configuration(self):
456- u1testutils.protect_imports(self)
457- settings = ('EMAIL_ADDRESS_PATTERN = "newemail+%s@test.com"\n'
458- 'SSO_TEST_ACCOUNT_PASSWORD = "test new password"\n')
459- settings_module = self._make_django_settings_file(settings)
460- with patch.dict(
461- 'os.environ', {'DJANGO_SETTINGS_MODULE': settings_module}):
462+ with u1testutils.django.patch_settings(
463+ EMAIL_ADDRESS_PATTERN='newemail+%s@example.com',
464+ SSO_TEST_ACCOUNT_PASSWORD='new password'):
465 with patch('uuid.uuid1') as mock_uuid:
466 mock_uuid.return_value = 'test_uuid'
467- data = self._reload_data_module()
468 user = data.User.make_from_configuration(new_user=True)
469
470 self.assertEqual(user.full_name, 'Test user test_uuid')
471- self.assertEqual(user.email, 'newemail+test_uuid@test.com')
472- self.assertEqual(user.password, 'test new password')
473+ self.assertEqual(user.email, 'newemail+test_uuid@example.com')
474+ self.assertEqual(user.password, 'new password')
475
476
477 class UserTestCase(unittest.TestCase):
478-
479+
480 def setUp(self):
481 self.user = data.User.make_from_configuration()
482
483@@ -99,17 +66,15 @@
484 self.assertIsNone(self.user._openid)
485
486 def test_openid_for_valid_account(self):
487- name = 'u1testutils.sso.data.client.get_account_openid'
488- with patch(name) as mock_client:
489- mock_client.return_value = 'foo1234'
490+ with patch('u1testutils.sso.data.client') as mock_client:
491+ mock_client.get_account_openid.return_value = 'foo1234'
492
493 self.assertEqual(self.user.openid, 'foo1234')
494 self.assertEqual(self.user._openid, 'foo1234')
495
496 def test_openid_for_invalid_account(self):
497- name = 'u1testutils.sso.data.client.get_account_openid'
498- with patch(name) as mock_client:
499- mock_client.return_value = None
500+ with patch('u1testutils.sso.data.client') as mock_client:
501+ mock_client.get_account_openid.return_value = None
502
503 self.assertEqual(self.user.openid, None)
504 self.assertIsNone(self.user._openid, None)
505
506=== modified file 'u1testutils/sso/sst/__init__.py'
507--- u1testutils/sso/sst/__init__.py 2013-05-03 03:02:25 +0000
508+++ u1testutils/sso/sst/__init__.py 2013-04-24 04:03:24 +0000
509@@ -11,7 +11,6 @@
510 #
511 # You should have received a copy of the GNU General Public License along
512 # with this program. If not, see <http://www.gnu.org/licenses/>.
513-
514 import sst.actions
515
516 from u1testutils.sso import mail

Subscribers

People subscribed via source and target branches

to all changes: