扩展nova api UT编写注意事项




扩展nova api时最大困难就是UT的修改,nova api的UT比较全面,主要涉及到如下几个方面的验证:
1)api response:你的扩展后的api的返回内容,这个就是涉及到的代码改动
2)api sample:api说明文档,或者说示例,这个部分在nova/doc目录下,比如

nova/doc/api_samples/all_extensions/extensions-get-resp.json

3)api template:api模板,主要用来正则匹配上面两个方面的值是否一致,忽略掉易变内容,这部分在nova/nova/tests目录下,比如

nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl

如果你扩展了某个,那么nova的UT就会验证这个api上面三个部分的内容是否匹配,任意两个不匹配单元测试都会不通过。
验证分为两个部分,一部分是对扩展本身的验证,比如调用获取扩展api插件能不能获取到新增的这个api插件,另一部分是对新增的api插件的响应做的验证,验证新增api返回结果是否与sample和template中的匹配。
具体例子说明:
我扩展了server detail接口(GET http://IP:PORT/v2/TENANT_ID/servers/UUID),
之前返回的是:
{
“server”: {
“status”: “ACTIVE”,
“updated”: “2014-10-15T01:32:16Z”,
“hostId”: “1ca9490db6fa17273f48b94d5824a021ed07a4f94112fe80da1216cb”,
……
“accessIPv6”: “”,
“progress”: 0,
“OS-EXT-STS:power_state”: 1,
“config_drive”: “”,
}
}
扩展后
{
“server”: {
“status”: “ACTIVE”,
“updated”: “2014-10-15T01:32:16Z”,
“hostId”: “1ca9490db6fa17273f48b94d5824a021ed07a4f94112fe80da1216cb”,
……
“accessIPv6”: “”,
“progress”: 0,
“OS-EXT-STS:power_state”: 1,
“config_drive”: “”,
“vncPass”: “abc123EDF”  # 增加了这个属性,管理员可见
}
}
这个时候你就要保证api sample和api template两个部分的文档里面也有这个新增的vncPass属性,并且要保证响应和sample经过template规则后二者能匹配通过,
另外因为这个接口是管理员可见,普通用户不可见,所以某些sample和template是不用改动的,要找到哪些不需要改动的需要具体看下sample和template文件的内容,看看之前只有管理员可见的属性是否在这些文件里面,如果有,那就要增加vncPass这个,没有则不用。
具体来说要改掉的文件主要位于api_samples目录下,因为是管理员可见,所以子目录为

OS-EXT-SRV-ATTR:

api sample:
doc/api_samples/OS-EXT-SRV-ATTR/server-get-resp.json
doc/api_samples/OS-EXT-SRV-ATTR/servers-detail-resp.json
api template:
nova/tests/integrated/api_samples/OS-EXT-SRV-ATTR/server-get-resp.json.tpl
nova/tests/integrated/api_samples/OS-EXT-SRV-ATTR/servers-detail-resp.json.tpl
改动的内容也比较简单,OS-EXT-SRV-ATTR这个目录下的文件只要把vncPass属性加上就好了,比如”vncPass”: null,表示返回的是内容为空,
如果响应是易变的字符串,可以用%s来匹配。
另外我还扩展了一个server action的api(POST  ‘http://IP:PORT/v2/TENANT_ID/servers/UUID/action’ -X -d ‘{“changeVNCPassword”: {“vncPass”: “123456”, “oldPass”: “654321”}}’),
新增的文件:nova/api/openstack/compute/contrib/change_vnc_password.py,内容就不列出来了,
要改掉的文件主要位于api_samples目录下,因为是测试扩展本身的,所以位于all_extensions子目录下:
api sample:
doc/api_samples/all_extensions/extensions-get-resp.json
doc/api_samples/all_extensions/extensions-get-resp.xml
doc/api_samples/all_extensions/server-get-resp.json
doc/api_samples/all_extensions/servers-details-resp.json
api template:
nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
nova/tests/integrated/api_samples/all_extensions/server-get-resp.json.tpl
nova/tests/integrated/api_samples/all_extensions/servers-details-resp.json.tpl
extensions目录下表示是验证扩展本身的sample或者template,需要根据xml或者JSON类型来添加,比如JSON的:
{
“alias”: “change-vnc-password”,
“description”: “%(text)s”,
“links”: [],
“name”: “ChangeVncPassword”,
“namespace”: “http://docs.openstack.org/compute/ext/change-vnc-password/api/v1.1“,
“updated”: “%(timestamp)s”
}
xml的:
<extension alias=”change-vnc-password” updated=”2014-10-31T00:00:00+00:00″ namespace=”http://docs.openstack.org/compute/ext/change-vnc-password/api/v1.1” name=”ChangeVncPassword”>
 <description>Change vnc password for a given server, need hard reboot to enable.</description>
</extension>
如果还有UT错误,可以根据UT错误TRACE具体分析下,比如错误是:
Traceback (most recent call last):
  File “nova/tests/integrated/test_api_samples.py”, line 972, in test_detail
    self._verify_response(‘servers-detail-resp’, subs, response, 200)
  File “nova/tests/integrated/api_samples_test_base.py”, line 243, in _verify_response
    response_data, “Response”)
  File “nova/tests/integrated/api_samples_test_base.py”, line 137, in _compare_result
    result_str)
  File “nova/tests/integrated/api_samples_test_base.py”, line 171, in _compare_result
    raise NoMatch(‘\n’.join(error))
那么应该是servers-detail-resp.xml/json的api sample和或者api template缺少了你新增的属性,可以根据与你新增的属性同类的属性搜索一下相关目录的文件,比如你新增了一个newattr属性,与之前的oldattr属性是一个权限和api返回的,那么所有有oldattr的sample和template文件都应该有newattr。
或者你可以ipdb设置断点,用python -m testtools.run nova.tests.integrated.test_api_samples.ExtendedServerAttributesXmlTest.test_detail执行单个用例进行调试(如果执行单个用例报NoSuchOptError: no such option: consoleauth_manager,注释掉这行File “nova/tests/integrated/integrated_helpers.py”, line 89, in setUp
    self.consoleauth = self.start_service(‘consoleauth’)就可以了),就可以看到具体是哪个文件缺少了你新增的属性, File “nova/tests/integrated/api_samples_test_base.py”, line 243, in _verify_response,基本都是用这个方法来验证一致性的,里面有self._get_template(name),self._get_sample(name),这两个方法,可以手工调用这两个方法来确定具体是哪个template或者sample文件有问题。