论坛首页 综合技术论坛

数据驱动测试

浏览 9797 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-12-05   最后修改:2009-12-05

我们从一个最简单的登录例子开始。

最开始我们需要验证在用户名和密码都正确的情况下,能够正常登录系统,我们这样编写测试代码(以下都是伪代码,使用TestNG和Selenium):

@Test
def should_login_success_with_exist_username_and_correct_password(){
    LoginPage page = user.open(LoginPage,"/login.html")
    user.perform("login",['user1','1234'],on(page))
    assert page.successLogin
}
 



恩,很不错,运行一下,出现红条。为什么呢?原来测试数据库里没有用户名为user1的用户,好吧,写个数据库数据初始化脚本。再运行,OK,绿条!

那么,接下来我们再增加一个测试,需要覆盖密码错误时不能登录系统的情况,很快测试就完成了:

@Test
def should_login_success_with_exist_username_and_incorrect_password(){
    LoginPage page = user.open(LoginPage,"/login.html")
    user.perform("login",['user1','4321'],on(page))
    assert page.successLogin,false
}
 



再运行一下测试,绿条。好啦,现在可以看下这段代码,恩,有些重复,重构一下:

@Test
def should_login_success_with_exist_username_and_correct_password(){
    assert login('user1','1234')
}

@Test
def should_login_success_with_exist_username_and_incorrect_password(){
    assert login('user1','4321'),false
}

def login(username,password){
    LoginPage page = user.open(LoginPage,"/login.html")
    user.perform("login",[username,password],on(page))
    return page.successLogin
}
 



重构完成,可以看到,我们的测试方法里现在没有了任何行为,仅仅是数据!这样让我感觉有点怪,不管了,先用TestNG提供的@dataProvider整理一下:

@Test(dataProvider="testdata")
def testLogin(username,password,expected){
    LoginPage page = user.open(LoginPage,"/login.html")
    user.perform("login",[username,password],on(page))
    assert page.successLogin,expected
}

@DataProvider(name="testdata")
def Object[][] dataForLogin(){
    def data=new Object[2][]
    data[0]=['user1','1234',true] as Object[]
    data[1]=['user1','4321',false] as Object[]
}
 



测试方法只剩下了一个!如果要测试不存在的用户不能登录系统呢?很简单,增加数据即可!

@DataProvider(name="testdata")
def Object[][] dataForLogin(){
    def data=new Object[2][]
    data[0]=['user1','1234',true] as Object[]
    data[1]=['user1','4321',false] as Object[]
    data[1]=['inexistuser','1234',false] as Object[]
}
 



在我们的测试方法里,测试数据和测试的行为进行了完全的分离。从系统的功能来说,功能一旦实现,那么就是一个黑盒,我们只要提供数据即可进行测试,这个数据包括两部分:输入和期待的输出。我开始暗自嘀咕:难道我以前那么多的洋洋得意测试方法很多都是不需要的吗?这些方式为什么会存在呢?恩,想起来了,这些方法是为了覆盖功能的各个路径的,是提高测试覆盖率的。那么为什么会产生这么多的测试方法呢?哦,在这些测试方法里,测试数据和测试行为是耦合在一起的

我伸了个懒腰,突然想,这下好了,我已经封装好了功能行为,QA想增加测试用例只需要自己增加数据就可以了,嘿嘿,爽啊。说曹操,QA到。QA mm说,你的某个功能实现有问题。我瞅了一眼,说,不可能啊(这是dev面对bug的第一反应),俺有测试的,持续集成一直是绿条的。QA mm说,在你的开发环境下测试是没有问题的,但是在QA环境,因为数据库变了,数据变了,应用服务器变了,所以会有些问题。我极不情愿的登录到QA环境,一测试,还真是,郁闷。

怎么办?修复完BUG,第一反应就是自动化测试能不能跑在QA环境呢?一般情况下,这些测试需要干净的测试环境,我们会制造很多的测试数据,可是在QA环境下,QA有她自己的测试数据,这些数据都不存在了哈。恩,看看刚才的测试代码,哈,就用QA的数据也可以啊,心情愉悦的改下:

@DataProvider(name="testdata")
def Object[][] dataForLogin(){
    def data=new Object[2][]
    data[0]=['hrong','1234',true] as Object[]
    data[1]=['hrong','4321',false] as Object[]
    data[1]=['rhao','1234',false] as Object[]
}
 



OK,完成!为了该测试既能在开发测试环境运行又能在QA环境下运行,我们可以引入一个环境变量,将测试数据扔到文件里,通过环境变量来加载不同的测试数据(测试文件)。

好吧,喝点东西(甲流很厉害,喝板蓝根好了),总结一下:

数据驱动测试:测试数据与测试行为分离,通过数据来驱动测试。

好处:在对测试行为封装好的情况下,QA mm能够自己通过数据修改自动化测试;
         自动化测试能够运行在多个环境下(开发环境、QA环境、产品环境);
         测试的可读性;
         测试方法大量压缩

适用范围:功能测试(selenium测试)
                通过环境准备测试数据(非测试用例自己准备数据)

可能存在的问题:比一般的测试编写困难,特别是在静态语言里

最后:该文章的思考来自于徐昊在团队内部的相应Session.

   发表时间:2009-12-07  
很有启发,可惜不能ding一下。。。
0 请登录后投票
   发表时间:2009-12-07  
嗯,测试数据同测试行为的分离
0 请登录后投票
   发表时间:2009-12-07   最后修改:2009-12-07
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?
0 请登录后投票
   发表时间:2009-12-07  
photon 写道
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?


首先声明一下,本人的数据驱动测试经验并不多,但是个人认为所有的测试数据都需要由环境准备。

0 请登录后投票
   发表时间:2009-12-07  
ronghao 写道
photon 写道
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?


首先声明一下,本人的数据驱动测试经验并不多,但是个人认为所有的测试数据都需要由环境准备。


我的数据驱动测试经验也很少。虽然还不清楚你说的测试数据由环境准备什么意思,但我想知道是否遇到过这样的问题:
如果每个dev准备自己的测试环境,创建db纪录,会不会在集成的时候造成db的冲突,比如这个简单和极端的情况,你用于fail的用户名/密码,却被另一个dev当作能成功登陆的用户对待。如果发现类似的问题,应该怎么解决?

0 请登录后投票
   发表时间:2009-12-08  
单元测试下的数据驱动测试倒是有dbunit和dddunit来支持。
集成测试下倒没有研究过,主要涉及到测试环境是否存在多人共用情况,如果不存在此种情,倒是可以在集成测试脚本启动前加载进行测试数据环境加载。
0 请登录后投票
   发表时间:2009-12-08   最后修改:2009-12-08
太好了,正在思考这方面的问题。
ps:我觉得适用范围可以是功能测试(如selenium测试)和集成测试(如JUnit写出的集成测试)
更进一步的我想象的可能场景是,前者由QA mm来维护测试数据文件,后者由开发人员来维护测试数据文件。
0 请登录后投票
   发表时间:2009-12-08  
photon 写道
ronghao 写道
photon 写道
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?


首先声明一下,本人的数据驱动测试经验并不多,但是个人认为所有的测试数据都需要由环境准备。


我的数据驱动测试经验也很少。虽然还不清楚你说的测试数据由环境准备什么意思,但我想知道是否遇到过这样的问题:
如果每个dev准备自己的测试环境,创建db纪录,会不会在集成的时候造成db的冲突,比如这个简单和极端的情况,你用于fail的用户名/密码,却被另一个dev当作能成功登陆的用户对待。如果发现类似的问题,应该怎么解决?



是这样,环境准备的意思是在测试开始之前所有测试数据已经准备完毕,测试代码里不准备数据。环境准备可以是一段在测试开始前的脚本也可以是一个程序,它的目的是清理测试环境并准备数据。

既然是环境准备数据,那么显然这些脚本和程序也是要放入版本管理中的,这样就避免冲突。
0 请登录后投票
   发表时间:2009-12-08  
daquan198163 写道
太好了,正在思考这方面的问题。
ps:我觉得适用范围可以是功能测试(如selenium测试)和集成测试(如JUnit写出的集成测试)
更进一步的我想象的可能场景是,前者由QA mm来维护测试数据文件,后者由开发人员来维护测试数据文件。


我的看法和你一致,使用范围应该是功能测试和集成测试,不包括单元测试。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics