这个是我在自动化case编写框架的经验总结,由于作者经验有限,如有错误,欢迎指正
另外我有代码示例,但是不知道怎么上传,好像不支持附件啊,我传到资源里了,找不到的同学也可以留言,我私下发给你
框架背景
在测试项目中,项目的版本会有很多,需要测试人员对每个版本进行尽可能详尽的测试。自动化case能够大大提高测试的效率,减少人为出错的可能,有益于项目质量的保证。随着项目规模的扩大,项目case的增多,测试case的编写困扰着测试人员,这篇文章就是为了解决这个问题。
框架优点
- 简单
- 重用代码
- 层次化
- 便于扩展
- 让测试人员聚焦于业务逻辑的编写,提高自动化case编写的效率
- 方便代码的维护
框架使用
对于框架的使用,从一个小case说起,在作者测试的一个项目中,经常测试网络的连通性case,传统的case,可能需要十几甚至几十行代码,而使用自动化case编写框架,只需简单的3行语句,就能很好的完成这个任务
代码如下
#-*- coding: UTF-8 -*-
__author__ = ‘ligengyong‘
‘‘‘
a sample test for auto case framework
‘‘‘
import CaseBase
class Case(CaseBase.CaseBase):
def __init__(self):
CaseBase.CaseBase.__init__(self, "host ping itself")#case 名字
def caseWork(self):
cmd = "ping -c 3 127.0.0.1"
flag = self.verifySumLocal(cmd, "icmp_seq", 3)
self.organiseOutputDefault(flag)
def work(self):
self.caseWork()
if __name__ == "__main__":
case = Case()
case.start()
查看执行结果:
[[email protected]bb-nsi-uinp09.bb01.baidu.com ligengyong]# python demo.py
/usr/local/lib/python2.7/site-packages/Crypto/Util/number.py:57: PowmInsecureWarning: Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.
_warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
exe cmd at local host: ping -c 3 127.0.0.1 #执行命令
return:
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. #返回结果
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.014 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.031 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.018 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.014/0.021/0.031/0.007 ms
#case执行情况
Project: project
Version: 1.0.0
Case: host ping itself
Start_Time: 12:19:56 07/04/2015
End_Time: 12:19:58 07/04/2015
Expectation: success
Result: success
Reason: success
框架介绍
框架类关系图
关于图中几个类介绍一下
- case A, B, C表示具体的case类,本文中的demo例子中的case类型和CaseC类似
- CaseBase自动化代码基础框架类,继承了threading.thread类,实现了run方法,run调用了三个方法,
a. 调用work方法,这个方法执行具体的工作,由子类去实现
b. 调用时间戳函数,当case执行结束后计算更新时间
c. 调用case运行结果输出函数,统计case执行结果
- ProjectBase继承了CaseBase,用来对一些project层面的配置和公用函数的编写,以及规范化case的执行流程
举个例子,作者测的项目中,经常要在机器a上执行一些命令,CaseBase提供了函数exeRemote(self, cmd, ip, port, name, password, timeout=10)但是我不想每次都要输入host a的ip,密码等信息,这样我就写一个
exeCmdAtHostA()方法,在exeCmdAtHostA中按照ProjectBase对于host a的配置信息对exeRemote方法进行进一步的封装,这样所有的子类case都可以简单的调用这个方法就可以了,既简化了代码,又便于理解,同时当host a的配置信息发生了变化或者exeCmdAtHostA方法的功能需要修改的时候,只需要改一处就可以了,这样使得代码便于维护
另外一种情况,如果对于case要求执行前整理环境,执行任务,之后清理环境,这样就可以再重写work方法,新建子work方法,在work方法中调用整理环境,执行子work方法,清理环境,让子类去重写子work方法
- ModuleBase继承了ProjectBase, 它和ProjectBase有着类似的功能,只不过是module层面的信息
通过简单的介绍,不难看出框架具有以下特点
- 依赖倒置,使得程序依赖于抽象的类,而非具体的类
- 层次化复用代码
- 对修改关闭,对拓展开放
- 程序的启动由框架来做,用户只负责具体的业务逻辑
- 拓展性好,用户可以对框架的执行流程进行拓展或者修改
CaseBase介绍
在上一小节,已经看到CaseBase继承了threading.Thread类,下面对CaseBase的其他方法做一下介绍,由于作者的水平有限以及参与的测试的项目,可能不能对所有测试的基础方法都封装进来,后续如果有其他的需求,可以再加进来
首先介绍一下公共方法:
- closeProcessLike(processName) 根据process的名字,在本地找到,并kill掉
- closeProcessLikeRemote(processName, ip, port, name, password, timeout=10)根据process的名字,在目标主机找到,并kill掉,如果失败,会抛出异常
其次介绍一下CaseBase的类方法
- __init__(self, name)类初始化方法,name为case的名字
- initParameter(self)初始化变量
- setProjectAndVersion(self, name="project", version="1.0.0")设置项目的名字和版本,这个一般在ProjectBase进行覆盖
- def work(self)具体的执行方法,需要子类覆盖
- setOutputFile(self, name)设置输出文件,如果没有设置,会输出到标准输出
- puts(self, line)自定义的输出方法,如果子类需要打印一些东西,可以调用这个方法
- touch(self, TIME)用来更新时间戳
- done(self)用来在case执行结束后输出case的执行情况
- run(self)覆盖threading.Thread的run方法
- getResultString(self)生成执行结果string
- verifyHasLocal(self, cmd, target)在本机执行cmd,并查看返回结果是否含有Target,如果有返回True,如果没有返回False
- sleep(self, timeout)自定义sleep方法
- verifySumLocal(self, cmd, target, sum)在本机执行cmd,并查看返回结果含有target的个数是否为sum,如果是返回True,如果不是返回False
- exeLocal(self, cmd)在本地执行命令cmd
- exeRemote(self, cmd, ip, port, name, password, timeout=10)在远程执行命令cmd
- getRetFromExeRemote(self, cmd, ip, port, name, password, timeout=10)在远程执行命令cmd,并将执行结果返回,用来为用户自定义判断提供接口
- transportFile(self, file, remoteFile, ip, name, password, sshPort=22)往远端发送文件
- verifyHasRemote(self, cmd, target, ip, port, name, password, timeout=1)和verifyHasLocal类似,只不过是在远端执行的
- verifySumRemote(self, cmd, target, sum, ip, port, name, password, timeout=10)和verifySumLocal功能类似,只不过是在远端执行的
- organiseOutputDefault(self, flag)默认组织case执行结果的输出,flag为执行的标识,True为成功,False为失败
TestException自定义的异常类
其他事项:
- 如果一个case需要两个不同线程,需要将一个线程的done方法重写,并且不做任何处理,这样避免同时有两个线程同时输出case执行结
def done(self):
pass
2. 如果一个case需要两个相同的线程的话,需要调用一下,setOutputFlag(False)即可