OpenStack中的测试
原作者:张华
原文链接: http://blog.csdn.net/quqi99
如需再次转载,请注明原作者信息!
在openstack中写一个扩展API之后要写哪些测试代码呢?https://jenkins.openstack.org/view/Nova/?列出来了提交代码后jenkins所要做的测试。
2)不带隔离的真实环境的测试,包括功能测试(在真实环境中针对一个个具体的API一一测试),和集成测试(在真实环境中将多个API串起来测试),代码位于tempest工程 。
至于如何写扩展API (位于目录$nova/nova/api/openstack/compute/contrib),请参见我的上一篇博文(Openstack extension api ( by quqi99 ) http://blog.csdn.net/quqi99/article/details/8502034) .
1, Mock单元测试, (位于目录$nova/nova/tests/api/openstack/compute/contrib) 可以参见文档:http://wiki.openstack.org/SmallTestingGuide
Mock单元测试,就是经常说的Small Testing, 它强调隔离,也就是说我们只将精力集中在我们要测试的方法内,如果该方法调用了其他方法,都可以让它做Mock即返回一些假值。
代码隔离有两种方法:
1)一种是依赖注入,如下例子,想要测试FalilyTree类的话,应集中精力测试FalilyTree本身是否有错,至于它所依赖的PersonGateway可以做一个假的FakePersonGateway注入进去。
class FamilyTree(object):
def __init__(self, person_gateway):
self._person_gateway = person_gateway
person_gateway = FakePersonGateway()
# ...
tree = FamilyTree(person_gateway)
2) Monkey Patching, 如下例子,例用python脚本语言的特性,在运行时可以动态替换命名空间的方法,用FakePersonGateway替换掉命名空间mylibrary.dataaccess.PersonGateway
class FamilyTree(object):
def __init__(self):
self._person_gateway = mylibrary.dataaccess.PersonGateway()
mylibrary.dataaccess.PersonGateway = FakePersonGateway
# ...
tree = FamilyTree()
所以,相应地,也就有了下列几类实际隔离的方法:
1) Test Stub,打桩
比如在扩展API中调用了authorize这个函数,如下:
authorize = extensions.extension_authorizer('compute', 'flavor_dynamic')
class FlavorDynamicController(servers.Controller):
@wsgi.extends
def create(self, req, body):
context = req.environ['nova.context']
authorize(context)
那么在为它写单元测试时,对authorize函数打桩替换的代码如下:
def authorize(context):
pass
class FlavorDynamicTest(test.TestCase):
def setUp(self):
super(FlavorDynamicTest, self).setUp()
self.controller = flavor_dynamic.FlavorDynamicController()
self.stubs.Set(flavor_dynamic, 'authorize', authorize)
2) Mock对象,例如要测试的方法中调用了
inst_type = instance_types. get_instance_type_by_name(flavor_name, context)
现在可以用下面的方法将其替换:
self.mox.StubOutWithMock(flavor_dynamic.instance_types,
'get_instance_type_by_name')
flavor_dynamic.instance_types.get_instance_type_by_name(
mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None)
flavor_dynamic.instance_types.get_instance_type_by_name(
mox.IgnoreArg(), mox.IgnoreArg()).AndReturn("{'a'='1'")
self.mox.ReplayAll()
3) Fake对象,即创建大量的假对象。
2, 除了上面的单元测试,还有针对api和samples的功能测试,位于$nova/nova/tests/integrated/api_samples目录,它们和集成测试的区别在于集成测试采用的是真实环境,而它仍然需要做Mock隔离。
https://blueprints.launchpad.net/nova/+spec/nova-api-samples 介绍了如何写这种测试
https://review.openstack.org/#/c/17003/ 是一个这种测试的具体例子
3, 集成测试,位于tempest工程中, 一个好的例子, https://review.openstack.org/#/c/9507/