前言
现在流行的测试驱动有数据驱动,行为驱动,关键字驱动。初听,甚是高大上,不明其理。车子讲究两驱四驱前驱后驱等,根据路况或场景来选择不同的车子,测试也搞驱动?那么这三个流行的驱动方式,到底哪一个才是人间真理?如何选择?别急,百晓生带你一探究竟。
什么是驱动?
什么是驱动?驱动什么?车子上的驱动,是指发动机的布置方式,显然是为了驱动车子跑动起来,所以车子上的驱动,只是一种布置架构,同理,测试中的驱动,是指测试框架的架构,是为了驱动测试脚本的执行。车子最重要的是能跑动,测试脚本最重要的是能够被执行,所以,驱动就是执行!
数据驱动
数据驱动(Data Driven),这里强调的是数据,驱动即执行,那么数据驱动就是根据数据来执行测试脚本。
场景:测试登录,分别用刘能和赵四的帐号去测试。
先写一个公共方法来描述登录的过程:(伪代码实现)
public boolean login(String username, String password){
//do login
}
再到测试方法里面去调用这个login方法/函数:
public void test1(){
login("liuneng","123456");
}
public void test2(){
login("zhaosi","654321");
}
这样测试用例就写完了,执行test1与test2两个方法即可。但细心的你可能会发现test1与test2这两个测试方法里的方法体除了数据,其它完全一样,这就存在重构的空间了:
public boolean login(String[][] accounts){
for(int i = 0; i<accounts.length; i++){
//do login
}
}
public void test(){
String[][] accounts = [["liuneng","123456"],["zhaosi","654321"]];
login(accounts);
}
经过重构后的代码,就有点数据驱动的意思了,根据accounts的length来决定login方法/函数体运行几次,这样维护起来就方便了,假如又有一个老王的帐号想用来测试,就不需要再加一个测试方法了,只需要:
String[][] accounts = [["liuneng","123456"],["zhaosi","654321"],["laowang","000000"]];
重构后的代码,是不是令你很激动?原来这就是数据驱动!别急,淡定,这还不是真的数据驱动,因为上面只有一个测试方法,最后执行完后,报告中记录的也是只有一个测试方法,而场景中:分别用刘能和赵四的帐号去测试,是希望在测试报告中有两个测试方法出现,显然上面的代码还不能满足我们的需求,于是进一步优化:
public boolean login(String username, String password){
//do login
}
public void test(String username, String password){
login(username,password);
}
public void executor(){
String[][] accounts = [["liuneng","123456"],["zhaosi","654321"]];
for(int i = 0; i<accounts.length; i++){
test(accounts[i][0],accounts[i][1]);
}
}
是的,离数据驱动原理真相越来越近了,上面多了个executor方法,这是啥?这就是车子的发动机引擎啊,就是测试脚本的执行引擎,让测试方法能够被执行起来,以及根据你所提供的测试数据的条数,决定测试方法的执行次数,并且报告中会显示是两个测试方法,这就是数据驱动。测试框架就是一个执行引擎,并且测试框架都会支持数据驱动这一基本诉求,比如testNg里的dataProvider,junit里的Parameters等。大家可以下去查一下自已所使用的测试框架的数据驱动写法,然后就可以重构优化自已的脚本啦!
行为驱动
数据驱动强调数据,行为驱动(Behavior Driven)当然得强调行为了。那么问题来了:什么是行为?需要注意的是,手工测试人员中或产品人员,很多都是不懂代码的,或者说他们压根不想去关注你这个脚本是如何实现的,他们更关注这个脚本覆盖了哪些场景,而通过代码或者注释告诉他们脚本的实现场景显然是不现实的,于是寻找一种大家都能够看的懂的"通用语言"来描述脚本就显得很重要了,伟大的计算机学者们把这种"通用语言"的描述定义为行为,这就是行为驱动的由来,即通过"通用语言"来执行脚本。
场景:测试购物流程。
先用一种"通用语言"来描述这个场景(这是一个单独的文件,命名为shop.feature):
步骤1:进入‘华为P9‘手机产品页并点击加入购物车按钮
步骤2:在购物车页面点击结算按钮
上面的行为描述不管是手工测试人员,还是产品人员都能看懂,除非他不懂汉语。行为定义好后,他们爽了,能看懂了,但脚本人员却傻了,如何把这些行为描述与脚本联系起来?别急嘛,有了理论基础,代码实现岂不是分分钟!
def /进入‘华为P9‘手机产品页并点击加入购物车按钮/
//coding, doing something
end
def /在购物车页面点击结算按钮/
//coding, doing something
end
def executor()
lines = read(‘shop.feature‘)
for line in lines
Method m = searchMethod(line) //通过正则并根据步骤内容来找到方法
m.run()//对line进行解析,比如‘‘里面的代表参数,执行找到的方法
end
end
只要是驱动,都会有执行引擎,所以上面的示例中也有一个executor方法来执行行为描述文件。行为驱动的原理就是循环读取并解析事先写好的行为描述特征文件,特征文件中的每一步都用一些特定符号或者特定字符串来标识参数,对象等,以便在解析时能够根据这些特定的符号或字符串来获取相应的值,当有了这些值以后,再根据正则来找到对应的方法并执行即可。行为驱动的好处就是把行为描述文件与实际的脚本进行了分离,特征文件给不懂代码的人看,脚本给开发人员看并且维护。行为驱动的作用及实现原理就是这样,现在也有很多很好的行为驱动测试框架,比如java里的JBehave,ruby里的cucumber,rspec等,至于行为驱动的好处与坏处,请期待百晓生后续文章,精彩持续不断!
关键字驱动
关键字驱动,就是把代码映射成关键字。可能有人会说,行为驱动的行为描述文件也可以理解成关键字,通过关键字来查找到对应的方法并且执行,那行为驱动与关键字驱动的不同点在哪?其实个人认为也就是一个描述文件的定义先后顺序问题,行为驱动是先定义描述文件,然后产品人员与手工测试人员审核通过后,脚本开发人员再去根据描述文件来代码实现,而关键字驱动,是脚本开发人员先去写好代码,然后把代码方法的关键字给定义后,然后再给产品人员与手工测试人员审核,你要说这两个驱动哪个好哪个坏,难分伯仲,只有符合自已公司业务特点的驱动才是好驱动。百晓生以前的文章里有一篇<<关键字驱动的原理和实现>>,大家可以自行查阅,也是干货哟!
总结
目前市面上的测试驱动的工具或者框架,都有一个共同点,就是都支持数据驱动,所以数据驱动才是根本之王。深入了解并熟悉数据驱动,结合测试框架,打造出符合公司业务特点的自动化测试框架,从此走上人生巅峰,当上CEO,迎娶白富美!最重要的一点:请持续关注百晓生!
百晓生微信公众号二维码: