1.Tempest测试框架介绍
A.概念
B.具体内容
C.原理
D.优缺点
2.Tempest的安装配置
A.安装
B.初始化
C.修改配置
3.Tempest执行测试(命令)
A.执行测试(命令语句,格式)
B.执行部分用例
C.断点单步调试
4.Tempest代码结构、文件目录
A.目录结构
B.代码结构
C.tempest.conf结构
5.Tempest测试
A.API测试用例(流程图,结果)
1.Tempest测试框架介绍
a.Tempest 是 Openstack 的测试框架。和 Openstack 类似,Tempest 由社区人员维护。Tempest 测试框架包含 Openstack基本组件(nova, keystone, glance, quantum, cinder)的测试用例,同时支持 JSON、XML 两种 REST API 格式类型的测试, 以及 CLI 测试。
Tempest为OpenStack的功能测试、集成测试项目,它被设计为可在各种不同项目中使用。在OpenStack核心项目中的单元测试代码中经常可以看到它的身影,在一些孵化项目中也会使用Tempest去测试。它可以验证代码的正确性,已经成为OpenStack项目中不可或缺的组成部分。
b.Tempest具体内容
├── api # API的测试集
├── cli # OpenStack的命令行工具测试集
├── common # 一些公共的工具类和函数
├── scenario # 对OpenStack的常用场景进行测试,包括基本的启动VM,挂载volumn和网络配置等
├── services # tempest自己实现的OpenStack API Client,自己实现是为了不让一些bug隐藏在官方实现的Client里面。
├── stress # 压力测试集,利用multiprocessing来启动多个进程来同时对OpenStack发起请求。
├── thirdparty # EC2兼容的API测试集
├── whitebox # 白盒测试集,主要是对DB操作,然后发起请求,然后比对结果
c.tempest是通过nose驱动的,python语言编写,使用testtools和testresources等几个测试工具库
d.Tempest流程:1.调用各个Openstack组件的API
2.验证API返回的结果
e.Tempest的优点
1.Tempet可以自动寻找,执行测试:自动查找当前目录下所有以(T)test开头的Python源文件,并且按此规则递归查找子目录;所有以(T)test开头的Python源文件面的所有以(T)test开头的function和class,以及继承自unittest.TestCase的class(不需要test开头)都会被执行。
2.Tempest可以指定文件、模块、函数进行测试。
3.Tempest可以指定类型进行测试。
4.Tempest可扩展性强,可以方便的在tempest中添加其他测试用例,可以整合其他类型测试如压力测试、场景测试等。
f.tempest缺点
对于每一套不一样的openstack环境,都要手工修改相关的配置项tempest.conf文件。(至少要修改user ids, openstack endpoints, images id、password等).假如你要测试openstack的全部服务,那你得配置几十项内容,得花费不少时间。显然这非常不智能、且很愚笨。
2.Tempest的安装配置
A.安装 #得先pip设置代理,不然容易出错
a.首先得有装有openstack环境的物理机(本例使用secureCRT连接虚拟机192.168.0.25)
b.$source keystonerc_admin #使用admin登录
c.$git clone https://github.com/openstack/tempest/ #下载源码
( Tempest 下载地址 https://github.com/openstack/tempest
下载的源码在/root/tempest/tempest目录下)
在tempest目录下
d.$pip install tempest #安装tempest项目
(*如果pip install报错,比如某个Python包版本冲突或者之类的,可以先执行下
$ pip install -r tempest/requirements.txt #安装Python依赖包,然后再执
行d步命令)
B.初始化
e.$ tempest init hunter-tempest-01 #初始化测试环境目录
(此步骤相当于如下命令:
$mkdir hunter-tempest-01 && cd my-tempest-env-01 &&tempest init )
C.修改配置
f.初始化测试环境目录过程中,会在测试环境目录hunter-tempest-01下自动生成如下目 录
$ etc logs tempest_lock
其中etc目录下生成了tempest.conf.sample示例配置文件,我们修改好这个文件并重命名为tempest.conf。
下面是修改完毕的配置文件和初始化完毕的示例配置文件的diff结果
root@control-1:~#diff origin-sample-conf/etc/tempest.conf.samplemy-tempest-env-01/etc/tempest.conf -u
--- origin-sample-conf/etc/tempest.conf.sample 2015-12-23 20:07:37.703580165 +0800
+++ my-tempest-env-01/etc/tempest.conf 2015-12-23 19:45:27.390680269 +0800
@@ -178,19 +178,19 @@
# authenticating requests made by tenantisolation to create users and
# projects (string value)
# Deprecated group/name -[identity]/admin_username
-#admin_username = <None>
+admin_username = admin
# Tenant name to use for an administrative user. This is needed for
# authenticating requests made by tenantisolation to create users and
# projects (string value)
# Deprecated group/name -[identity]/admin_tenant_name
-#admin_tenant_name = <None>
+admin_tenant_name = admin
# Password to use for an administrative user. This is needed for
# authenticating requests made by tenantisolation to create users and
# projects (string value)
# Deprecated group/name -[identity]/admin_password
-#admin_password = <None>
+admin_password = admin #管理员模式下的用户名密码
# Admin domain name for authentication(Keystone V3).The same domain
# applies to user and project (string value)
@@ -290,18 +290,18 @@
# Valid primary image reference to be used intests. This is a
# required option (string value)
-#image_ref = <None>
+image_ref =643ea9b2-f2f8-408e-ab37-309494e82832 # ubuntu-12.04-root_qwerty-ubuntu_ubuntu
# Valid secondary image reference to be usedin tests. This is a
# required option, but if only one image isavailable duplicate the
# value of image_ref above (string value)
-#image_ref_alt = <None>
+image_ref_alt =42074fa5-231c-48f2-9db1-e283a5ea5b10 #Centos
#这两组数据是glance服务里面的两个image的ID,通过 #glance image-list命令可以取得所有的image id,如果需要可以专门上传两个image供tempest使用。
# Valid primary flavor to use in tests.(string value)
-#flavor_ref = 1
+flavor_ref = 1 #m1,tiny
# Valid secondary flavor to be used in tests.(string value)
-#flavor_ref_alt = 2
+flavor_ref_alt = 2 #m1.small
#这两组数据是tempest创建instance测试用例使用的flavor id参数。通过 $nova flavor-list命令可以看到当前openstack环境的所有flavor,默认情况下,openstack会创建5个flavor, 这里的1和2分别代表的是m1.tiny和m1.small。
# Time in seconds between build statuschecks. (integer value)
#build_interval = 1
@@ -320,7 +320,7 @@
# which will be used for creating servers iftempest does not create a
# network or a network is not specifiedelsewhere. It may be used for
# ssh validation only if floating IPs aredisabled. (string value)
-#fixed_network_name = <None>
+fixed_network_name = public #networkname,可通过neutron net-list找到
# Catalog type of the Compute service.(string value)
#catalog_type = compute
@@ -590,14 +590,14 @@
#ca_certificates_file = <None>
# Full URI of the OpenStack Identity API(Keystone), v2 (string value)
-#uri = <None>
+uri=http://192.168.0.100:5000/v2.0/ #测试的后端定为100;openstack服务的主机IP,也就是keystone服务所在节点的IP,默认是192.168.0.100,也就是本地地址;keystone认证API地址,包含端口和版本号
# Full URI of the OpenStack Identity API(Keystone), v3 (string value)
#uri_v3 = <None>
# Identity API version to be used forauthentication for API tests.
# (string value)
-#auth_version = v2
+auth_version = v2 #用于API测试的version为v2
# The identity region name to use. Also usedas the other services'
# region name unless they are set explicitly.If no such region is
@@ -624,12 +624,12 @@
# Username to use for Nova API requests.(string value)
# This option is deprecated for removal.
# Its value may be silently ignored in thefuture.
-#username = <None>
+username = demo
# Tenant name to use for Nova API requests.(string value)
# This option is deprecated for removal.
# Its value may be silently ignored in thefuture.
-#tenant_name = <None>
+tenant_name = demo
# Role required to administrate keystone.(string value)
#admin_role = admin
@@ -637,7 +637,7 @@
# API key to use when authenticating. (stringvalue)
# This option is deprecated for removal.
# Its value may be silently ignored in thefuture.
-#password = <None>
+password = demo
#非管理员用户操作的用户名密码
# Domain name for authentication (KeystoneV3).The same domain applies
# to user and project (string value)
@@ -683,10 +683,10 @@
#trust = true
# Is the v2 identity API enabled (booleanvalue)
-#api_v2 = true
+api_v2 = true
#v2 api可以激活
# Is the v3 identity API enabled (booleanvalue)
-#api_v3 = true
+api_v3 = false
#v3 api不可以激活
# A list of enabled identity extensions witha special entry all which
# indicates every extension is enabled. Emptylist indicates all
@@ -851,7 +851,7 @@
# Id of the public network that providesexternal connectivity (string
# value)
-#public_network_id =
+#public_network_id = <None> ?
# Default floating network name. Used toallocate floating IPs when
# neutron is enabled. (string value)
@@ -891,7 +891,7 @@
#
# Allow the execution of IPv6 tests (booleanvalue)
-#ipv6 = true
+ipv6 = false
#ipv6不可用
# A list of enabled network extensions with aspecial entry all which
# indicates every extension is enabled. Emptylist indicates all
@@ -1086,32 +1086,32 @@
#
# Whether or not cinder is expected to be available(boolean value)
-#cinder = true
+cinder = false
#cinder不可用
# Whether or not neutron is expected to beavailable (boolean value)
-#neutron = false
+neutron = true
#neutron可用
# Whether or not glance is expected to beavailable (boolean value)
-#glance = true
+glance = true
#glance可用
# Whether or not swift is expected to beavailable (boolean value)
-#swift = true
+swift = false
#swift不可用
# Whether or not nova is expected to beavailable (boolean value)
-#nova = true
+nova = true
#nova可用
# Whether or not Heat is expected to beavailable (boolean value)
#heat = false
# Whether or not Ceilometer is expected to beavailable (boolean
# value)
-#ceilometer = true
+ceilometer = true
#ceilometer可用
# Whether or not Aodh is expected to beavailable (boolean value)
#aodh = false
# Whether or not Horizon is expected to beavailable (boolean value)
-#horizon = true
+horizon = true
#horizon可用
# Whether or not Sahara is expected to beavailable (boolean value)
#sahara = false
我整理了一个tempest具体配置.word文档,里面标着红色的字体是需要修改的地方。配置完毕并将文件重命名为tempest.conf,就可以执行tempest测试了。
3.Tempest执行测试(命令)
*执行测试需要在修改好配置文件的测试环境配置目录下进行。
A.执行全部测试用例(有几种方式可以执行tempest测试)
a.$ testr run
b.$ testr run --parallel #并发测试,注意是双横杠
(并发测试:主要指当测试多个用户并同时访问同一个应用程序、同一个模块数据记录时是否存在死锁或其他性能问题,几乎所有的性能测试都会涉及并发测试。)
c.$ testr help run #查看testr的帮助文档查看更多参数
d.$ nosetests -v tempest #效果和tests run一样
执行完毕后会有类似如图的效果:
(对此结果的解读:测试了651个文件总共用时3447.950s,整个测试结果是失败的,其中skip(跳过)了18个,errors(脚本的错误)有272个,faliures(测试失败)81次)
*测试结果
--Tempest中的测试结果有4种:测试错误(Error)、测试失败(Failure)、跳过(Skip)、成功(success)
-- 测试错误:可以简单理解成测试代码执行时候报错了,比如:测试代码中print a,而a没有进行变量声明。跟setUp类似,如果代码在这个阶段出错,也都会认为是测试错误(Error)。
-- 测试失败:可以简单理解成测试代码执行正常,但没有得到预期的测试结果,比如:测试代码中调用功能代码add(1, 2),但返回结果不是3。
-- 跳过:也可以理解为测试忽略(Ignore),比如:某个测试只想在Windows下才运行,这样在Linux下就会被跳过,也就是忽略。
-- 成功:TestCase执行成功。
(error也可能是配置环境有问题,产生skip可能是被测试的服务有bug)
B.执行部分用例
e.可以按照目录+文件+类+方法的方式执行某个特定用例,比如$ testrrun tempest.api.compute.servers.test_servers_negative.ServerNegativeTestJSON.test_reboot_non_existent_server
f.也可以执行某个文件中的所有用例,比如:
$testr runtempest.api.compute.servers.test_servers_negative
g.或者一个类的所有用例:
$ testr runtempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON
h.还可以用python -m testtools.run来执行部分用例,比如:$ python -m testtools.runtempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server (同样可以用python -m testtools.run来执行某个文件或某个类的全部用例,用法与testr run相同)
i. nosetests 命令来执行部分用例也是一样的用法,不过要加上-s参数,
比如:
$nosetests -sv testtools.run\ tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server
C.断点单步调试
如果某个用例执行出错,需要加入断点单步调试,可以用pdb调试库来完成调试工作,建议用ipdb库来调试,这个库更智能易用,它的缺点是不是Python系统库,需要手工安装才能使用。
$pip install ipdb #ipdb库的安装
如果要加入断点单步调试,需要使用python-m testtools.run方法来执行被调试的用例,否则可能导致断点无法进入,也就没办法进行单步调试
以tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server用例为例进行说明,这里使用的是ipdb,pdb也是类似:
149 @test.attr(type=['negative'])
150 @test.idempotent_id('d4c023a0-9c55-4747-9dd5-413b820143c7')
151 deftest_reboot_non_existent_server(self):
152 importipdb;ipdb.set_trace() #此处加入了断点
153 # Reboot a non existent server
154 nonexistent_server =data_utils.rand_uuid()
155 self.assertRaises(lib_exc.NotFound, self.client.reboot_server,
156 nonexistent_server, type='SOFT')
4..Tempest目录、代码结构及测试
A.目录结构
1)api:API的测试集。
2)cli:OpenStack的命令行工具测试集。
3)common:一些公共的工具类和函数。
4)scenario:对OpenStack的常用场景进行测试,包括基本的启动虚拟机、挂载volume和网络配置等。
5)services:Tempest实现的OpenStack API Client,主要是避免官方Client中含有Bug。
6)stress:压力测试集,利用多进程(multiprocessing)同时对OpenStack发起请求进行测试。
7)thirdparty:EC2等第三方兼容API测试集。
8)whitebox:白盒测试集。
B.代码结构
C.Tempest.conf文件
Tempest里有一个很重要的文件,就是我们修改过配置的tempest.conf文件,在tempest.conf文件中分为以下session,这些session需要和测试的Openstack环境匹配
[identity] – 这个 session 主要包括user/tenant 相关的权限认证测试
[compute] – 这个 session 主要包括 OS ComputeAPI/CLI 相关测试
[whitebox] – 这个 session 主要包括查看 Nova 数据库状态,ssh 到虚机中查看其状态等
[image] – 这个 session 主要包括 OS 镜像 API/CLI 相关测试
[network] – 这个 session 主要包括 OS 网络 API/CLI 相关测试
[volume] – 这个 session 主要包括 OS Cinder 存储 API/CLI 相关测试
[object-storage] – 这个 session 主要包括 OS Swift 对象存储 API/CLI 相关测试
D.Tempest README.rst
tempest主要包括:API测试,命令行测试,复杂场景测试,压力测试,第三方API测试。
每一项都对应tempest中的一个目录,每个目录中包含不同类型的测试。
#/root/tempest/README.rst中记录着每个目录的作用,以及良好的测试实例及测试规则
5.Tempest测试
A.API测试用例
tempest.api是openstack api测试用例集。
现以tempest.api.compute.flavors.test_flavors.FlavorsV2TestJSON.test_list_flavors为例:
各类间的继承和调用:
FlavorV2TestJSO.test_list_flavors继承自BaseV2ComputeTest。Clients是负责管理包括FlavorsClient在内的所有的openstackclients的,同时调用TempestConfig来读取配置文件tempest.conf。FlavorsClient继承自RestClient,封装了访问openstackapi的接口。FlavorsV2TestJSON通过FlavorsClient来实现对openstackapi的访问。
源码:
classFlavorsV2TestJSON(base.BaseV2ComputeTest): #父类
_min_disk = 'minDisk'
_min_ram = 'minRam'
@classmethod
def setup_clients(cls):
super(FlavorsV2TestJSON,cls).setup_clients()
cls.client = cls.flavors_client
@test.attr(type='smoke')
@test.idempotent_id('e36c0eaa-dff5-4082-ad1f-3f9a80aa3f59')
deftest_list_flavors(self): #子类
# List of all flavors should containthe expected flavor
flavors =self.client.list_flavors()['flavors']
flavor =self.client.show_flavor(self.flavor_ref)['flavor']
flavor_min_detail = {'id':flavor['id'], 'links': flavor['links'],
'name':flavor['name']}
self.assertIn(flavor_min_detail,flavors)
@test.idempotent_id('6e85fde4-b3cd-4137-ab72-ed5f418e8c24')
def test_list_flavors_with_detail(self):
# Detailed list of all flavors shouldcontain the expected flavor
flavors = self.client.list_flavors(detail=True)['flavors']
flavor =self.client.show_flavor(self.flavor_ref)['flavor']
self.assertIn(flavor, flavors)
(测试结果)