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,解决这次单元测试问题。