tox -e py27时, 单元测试报错。
DB Migration 348 does not have a test. Please add one!
首先我是添加了一个db version为348的db版本,我本来想不添加单元测试,就不会影响到新添加的db version,结果尽然这个报了个db version单元测试的错。
还是想搞明白为什么会这样,毕竟我以前用ironic的时候,并没有这样的情况。
跟代码:
nova/tests/unit/db/test_migrations.py test_walk_versions(self):
oslo_db/sqlalchemy/test_migrations.py walk_versions()
查看 walk_version()里代码
189
versions = range(
int
(self.INIT_VERSION) +
1
,
190
int
(self.REPOSITORY.latest) +
1
) #version = [init_version, latest_version]
191
192
for
version in versions: #遍历所有版本并执行 migrate_up,于是查看migrate_up代码
193
# upgrade -> downgrade -> upgrade
194
self.migrate_up(version, with_data=True)
195
if
snake_walk:
196
downgraded = self.migrate_down(version -
1
, with_data=True)
197
if
downgraded:
198
self.migrate_up(version)
|
def _skippable_migrations(self): #这个是可跳过migrations的版本,大概就是之前稳定的版本的
special = [ #比如现在是
0
版,所以可跳过的版本感觉大概都是
0
版之前版本,初始版本是大概h上一版。
216
, # Havana
272
, # NOOP migration due to revert
]
havana_placeholders = list(range(
217
,
227
))
icehouse_placeholders = list(range(
235
,
244
))
juno_placeholders = list(range(
255
,
265
))
kilo_placeholders = list(range(
281
,
291
))
liberty_placeholders = list(range(
303
,
313
))
mitaka_placeholders = list(range(
320
,
330
))
newton_placeholders = list(range(
335
,
345
))
return
(special +
havana_placeholders +
icehouse_placeholders +
juno_placeholders +
kilo_placeholders +
liberty_placeholders +
mitaka_placeholders +
newton_placeholders)
def migrate_up(self, version, with_data=False):
if
with_data:
check = getattr(self,
"_check_%03d"
% version, None) #这个大概是第一个version都会有一个_check_
if
version not in self._skippable_migrations(): #如果没在可跳过的version里就会报错,可跳过的version是上面函数里有解释
self.assertIsNotNone(check, #我后面加的肯定没在可跳过的里面,所以肯定报错。
(
'DB Migration %i does not have a '
'test. Please add one!'
) % version)
# NOTE(danms): This is a list of migrations where we allow dropping
# things. The rules
for
adding things here are very very specific.
# Chances are you don't meet the critera.
# Reviewers: DO NOT ALLOW THINGS TO BE ADDED HERE
exceptions = [
#
267
enforces non-nullable instance.uuid. This was mostly
# a special
case
because instance.uuid shouldn't be able
# to be nullable
267
,
#
278
removes a FK restriction, so it's an alter operation
# that doesn't
break
existing users
278
,
#
280
enforces non-
null
keypair name. This is really not
# something we should allow, but it's in the past
280
,
#
292
drops completely orphaned tables with no users, so
# it can be done without affecting anything.
292
,
#
346
Drops column scheduled_at from instances table since it
# is no longer used. The field value is always NULL so
# it does not affect anything.
346
,
]
# Reviewers: DO NOT ALLOW THINGS TO BE ADDED HERE
# NOTE(danms): We only started requiring things be additive in
# kilo, so ignore all migrations before that point.
KILO_START =
265
if
version >= KILO_START and version not in exceptions:
banned = [
'Table'
,
'Column'
]
else
:
banned = None
with nova_fixtures.BannedDBSchemaOperations(banned):
super
(NovaMigrationsCheckers, self).migrate_up(version, with_data)
|
根据分析,于是在 nova/tests/unit/db/test_migrations.py 里加上单元测试代码。
def _check_347(self, engine, data):
self.assertIndexMembers(engine,
'instances'
,
'instances_project_id_idx'
,
[
'project_id'
])
self.assertIndexMembers(engine,
'instances'
,
'instances_updated_at_project_id_idx'
,
[
'updated_at'
,
'project_id'
])
def _check_348(self, engine, data):
self.assertIndexMembers(engine,
'instances'
,
'instances_project_id_idx'
,
[
'project_id'
])
self.assertIndexMembers(engine,
'instances'
,
'instances_updated_at_project_id_idx'
,
[
'updated_at'
,
'project_id'
])
|
可是还是报错,报如下错误:
nova.exception.DBNotAllowed: Operation Column.alter() is not allowed in a database migration
|
这就更恼火了,怎么竟然alter都不被允许了。于是细跟代码发现
if
version >= KILO_START and version not in exceptions: # 如果version不在 exceptions里 branned,banned = [
'Table'
,
'Column'
]
banned = [
'Table'
,
'Column'
]
else
:
banned = None
with nova_fixtures.BannedDBSchemaOperations(banned):
super
(NovaMigrationsCheckers, self).migrate_up(version, with_data)
|
class
BannedDBSchemaOperations(fixtures.Fixture):
""
"Ban some operations for migrations"
""
def __init__(self, banned_resources=None):
super
(BannedDBSchemaOperations, self).__init__()
self._banned_resources = banned_resources or [] #self._banned_resources 就是上面 with nova_fixtures.BannedDBSchemaOperations(banned): 传过来的
@staticmethod
def _explode(resource, op):
raise exception.DBNotAllowed(
'Operation %s.%s() is not allowed in a database migration'
% (
resource, op))
def setUp(self):
super
(BannedDBSchemaOperations, self).setUp()
for
thing in self._banned_resources: #如果有self._banned_resources,就会把_banned_resources里的东西,以patch的方式重新定义一次,
self.useFixture(fixtures.MonkeyPatch( #大概就是 sqlalcheymy.Table.drop = lambda *a, **k: self._explode(thing,
'drop'
)
'sqlalchemy.%s.drop'
% thing, #直接patch成一个异常了,大概知道原因了,把_banned_resources置为None就可以了
lambda *a, **k: self._explode(thing,
'drop'
)))
self.useFixture(fixtures.MonkeyPatch(
'sqlalchemy.%s.alter'
% thing,
lambda *a, **k: self._explode(thing,
'alter'
)))
|
于是在 exceptions 里加入 348,解决这次单元测试问题。