Merge lp:~elachuni/u1-test-utils/migration-tests into lp:u1-test-utils

Proposed by Anthony Lenton
Status: Rejected
Rejected by: Vincent Ladeuil
Proposed branch: lp:~elachuni/u1-test-utils/migration-tests
Merge into: lp:u1-test-utils
Diff against target: 104 lines (+76/-6)
3 files modified
canonical/__init__.py (+0/-5)
isdutils/tests/migrations.py (+75/-0)
setup.py (+1/-1)
To merge this branch: bzr merge lp:~elachuni/u1-test-utils/migration-tests
Reviewer Review Type Date Requested Status
Vincent Ladeuil (community) Needs Fixing
Review via email: mp+55551@code.launchpad.net

Description of the change

Overview
========
This branch adds a drop-in migration test case that can be applied to all our projects.

Details
=======
The new MigrationTestCase basically runs all migrations forwards and backwards again, to ensure that they run correctly.
A future improvement would be to add frozen fixtures that can be loaded after each migration, to ensure that the DB schema is left in a sane state.

While I was there, I renamed canonical.isd to isdutils, so that we're not using namespace packages as agreed in our team tech call.

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

Unfortunately this mp seems to be abandoned, marking as rejected to clear the queue, feel free to mark needs review with an explanation if needed.

review: Needs Fixing

Unmerged revisions

2. By Anthony Lenton

Renamed canonical.isd package to isdutils.

Added MigrationTestCase, that should be a drop-in test for migrations in all our projects.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed directory 'canonical'
2=== removed file 'canonical/__init__.py'
3--- canonical/__init__.py 2011-02-07 16:48:09 +0000
4+++ canonical/__init__.py 1970-01-01 00:00:00 +0000
5@@ -1,5 +0,0 @@
6-from pkgutil import extend_path
7-
8-
9-# denote package as namespace package
10-__path__ = extend_path(__path__, __name__)
11
12=== renamed directory 'canonical/isd' => 'isdutils'
13=== added file 'isdutils/tests/migrations.py'
14--- isdutils/tests/migrations.py 1970-01-01 00:00:00 +0000
15+++ isdutils/tests/migrations.py 2011-03-30 14:26:01 +0000
16@@ -0,0 +1,75 @@
17+# A standard test case for checking migrations. Just import MigrationTestCase
18+# from your tests' __init__.py
19+
20+from __future__ import absolute_import
21+
22+__all__ = [
23+ 'MigrationTestCase',
24+]
25+
26+import os
27+
28+from django.conf import settings
29+from django.core import management
30+from django.db import connection
31+from south import migration, orm
32+
33+from isdutils.tests.django import switch_settings
34+from isdutils.tests.logging import LogHandlerTestCase
35+
36+class MigrationTestCase(LogHandlerTestCase):
37+ def setUp(self):
38+ self.test_db_name = '/tmp/migrations_test.sql'
39+ patched_settings = {
40+ 'DATABASE_NAME': self.test_db_name,
41+ 'DATABASE_ENGINE': 'sqlite3',
42+ }
43+ self.orig_settings = switch_settings(**patched_settings)
44+ connection.settings_dict.update(patched_settings)
45+ self.orig_connection = connection.connection
46+ connection.connection = None
47+ management._commands['syncdb'] = 'south'
48+
49+ def patch_hacky_sqlite3_cludge(self):
50+ """Work around a South sqlite3 hack with another even hackier one.
51+
52+ As Sqlite3 doesn't support altering or deleting a column, South
53+ simulates this by creating a new table with the new columns, copying
54+ over the data and then putting the new table in the old one's place.
55+
56+ South 0.6 does this at most once for each migration, so the new table
57+ is remade the first time any column is deleted or altered.
58+
59+ So's to remember that it has already remade a table it stores a class
60+ attribute *on the orm model itself*. As South's orm stores one model
61+ per migration, this works fine as long as each migration is run
62+ at most once per process, in any direction.
63+
64+ To be able to run migrations multiple times here, we invalidate the
65+ orm's cache after any run.
66+
67+ Luckily this hack won't be needed in South 0.7.
68+ """
69+ orm._orm_cache = {}
70+
71+ def tearDown(self):
72+ switch_settings(**self.orig_settings)
73+ connection.settings_dict.update(self.orig_settings)
74+ connection.connection = self.orig_connection
75+ if os.path.exists(self.test_db_name):
76+ os.remove(self.test_db_name)
77+ management._commands['syncdb'] = 'django.core'
78+
79+ def test_migrations_straight_forwards(self):
80+ """Run migrations forwards from an empty DB"""
81+ management.call_command('syncdb', migrate=True, interactive=False,
82+ verbosity=0)
83+ self.patch_hacky_sqlite3_cludge()
84+
85+ def test_migrations_straight_backwards(self):
86+ """Run migrations backwards, from an fully migrated DB"""
87+ management.call_command('syncdb', migrate=True, interactive=False,
88+ verbosity=0)
89+ self.patch_hacky_sqlite3_cludge()
90+ management.call_command('migrate', target='zero', verbosity=0)
91+ self.patch_hacky_sqlite3_cludge()
92
93=== modified file 'setup.py'
94--- setup.py 2011-02-08 20:15:31 +0000
95+++ setup.py 2011-03-30 14:26:01 +0000
96@@ -8,7 +8,7 @@
97 def get_version():
98 version = [
99 (line.split('=')[1]).strip().strip('"').strip("'")
100- for line in open(os.path.join('canonical', 'isd', '__init__.py'))
101+ for line in open(os.path.join('isdutils', '__init__.py'))
102 if line.startswith( '__version__' )
103 ][0]
104 return version

Subscribers

People subscribed via source and target branches

to all changes: