`
ronghao
  • 浏览: 450150 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
E9473dd5-1985-3883-ac98-962354ca10b3
张小庆,在路上
浏览量:8576
社区版块
存档分类
最新评论

数据驱动测试

阅读更多

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

最开始我们需要验证在用户名和密码都正确的情况下,能够正常登录系统,我们这样编写测试代码(以下都是伪代码,使用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.

分享到:
评论
15 楼 rexqiu 2010-07-07  
学习了,处处都是封装。学习测试中
14 楼 wwccss 2010-01-09  
大家可以参考我之前写的一篇文章,也许有些帮助:http://www.ibm.com/developerworks/cn/opensource/os-cn-testingdata/index.html
13 楼 jiangduxi 2009-12-15  
不过我使用Selenium+JUnit进行功能测试(单元性质的)。比如测试登陆页面的测试。我也有点疑问:
我先说说我怎么测试的吧!

我将一个登陆页面的所有情况使用XML文件进行编写。然后使用dom4j进行解析XML。将XML的中的每个数据通过Selenium进行测试。基本上可以将登陆的所有想到的情况都测试。但是我就是不知道怎么将这些一个单独的功能测试进行整合成一个业务流的方式进行有序的测试。!

给出我的一些代码
以下这个是一个登陆数据及其验证结果
<loginPage>
	<user sid="001">
		<login>admin</login>
		<password>123</password>
		<validateCode>1</validateCode>
		<result>true</result>
		<ResultSuccessMessage>Successfully</ResultSuccessMessage>
		<ResultFailMessage>Fail</ResultFailMessage>
	</user>
	
	<user sid="002">
		<login>abc</login>
		<password>123</password>
		<validateCode>1</validateCode>
	    <result>false</result>
	    <ResultSuccessMessage>Successfully</ResultSuccessMessage>
		<ResultFailMessage>Fail</ResultFailMessage>
	</user>

	<user sid="003">
		<login>dd</login>
		<password>123456</password>
		<validateCode>1</validateCode>
		<result>false</result>
		<ResultSuccessMessage>Successfully</ResultSuccessMessage>
		<ResultFailMessage>Fail</ResultFailMessage>
	</user>
	
	<user sid="004">
		<login>def</login>
		<password>123456</password>
		<validateCode>1</validateCode>
		<result>false</result>
		<ResultSuccessMessage>Successfully</ResultSuccessMessage>
		<ResultFailMessage>Fail</ResultFailMessage>
	</user>
	
	<user sid="005">
		<login>jian</login>
		<password>1236</password>
		<validateCode>1</validateCode>
		<result>false</result>
       <ResultSuccessMessage>Successfully</ResultSuccessMessage>
		<ResultFailMessage>Fail</ResultFailMessage>
	</user>

	<user sid="006">
		<login>dddddc</login>
		<password>1234536</password>
		<validateCode>1233a</validateCode>
		<result>false</result>
        <ResultSuccessMessage>Successfully</ResultSuccessMessage>
		<ResultFailMessage>Fail</ResultFailMessage>
	</user>
........
</loginPage>

类似的将这样列出想到的所有情况!
在使用dom4j进行解析出来。调用Selenium进行页面填充。
12 楼 gjhohj 2009-12-12  
这几天也在学习测试和重构
11 楼 whaosoft 2009-12-10  
ronghao 写道
daquan198163 写道
太好了,正在思考这方面的问题。
ps:我觉得适用范围可以是功能测试(如selenium测试)和集成测试(如JUnit写出的集成测试)
更进一步的我想象的可能场景是,前者由QA mm来维护测试数据文件,后者由开发人员来维护测试数据文件。


我的看法和你一致,使用范围应该是功能测试和集成测试,不包括单元测试。

恩 表示同意 。单元测试都是开发人员测
10 楼 huangfeng1982 2009-12-09  
data[0]=['hrong','1234',true] as Object[]   
data[1]=['hrong','4321',false] as Object[]   
data[1]=['rhao','1234',false] as Object[]


有点担心的是,如果输入和输出比较复杂时,QA mm能看懂吗?

之前一个项目有一个比较大JUnit集成测试,也是类似以上的写法,
维护时发觉比较痛苦(主要是data[][]不够直观,修改输入输出时比较麻烦)
客户提出改进意见(他们也会跑这个JUnit),希望能用excel来描述输入输出,这样他自己就能追加case了
修改后发现果然更好用了

代价是:读excel比读data[][]烦
9 楼 ronghao 2009-12-08  
daquan198163 写道
太好了,正在思考这方面的问题。
ps:我觉得适用范围可以是功能测试(如selenium测试)和集成测试(如JUnit写出的集成测试)
更进一步的我想象的可能场景是,前者由QA mm来维护测试数据文件,后者由开发人员来维护测试数据文件。


我的看法和你一致,使用范围应该是功能测试和集成测试,不包括单元测试。
8 楼 ronghao 2009-12-08  
photon 写道
ronghao 写道
photon 写道
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?


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


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



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

既然是环境准备数据,那么显然这些脚本和程序也是要放入版本管理中的,这样就避免冲突。
7 楼 daquan198163 2009-12-08  
太好了,正在思考这方面的问题。
ps:我觉得适用范围可以是功能测试(如selenium测试)和集成测试(如JUnit写出的集成测试)
更进一步的我想象的可能场景是,前者由QA mm来维护测试数据文件,后者由开发人员来维护测试数据文件。
6 楼 yimlin 2009-12-08  
单元测试下的数据驱动测试倒是有dbunit和dddunit来支持。
集成测试下倒没有研究过,主要涉及到测试环境是否存在多人共用情况,如果不存在此种情,倒是可以在集成测试脚本启动前加载进行测试数据环境加载。
5 楼 photon 2009-12-07  
ronghao 写道
photon 写道
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?


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


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

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


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

3 楼 photon 2009-12-07  
我想问楼主一个问题,在实际的"数据驱动测试"开发中,一些测试相关的db记录都是这么通过数据库数据初始化脚本直接插入到db中吗?
2 楼 zozoh 2009-12-07  
嗯,测试数据同测试行为的分离
1 楼 庄表伟 2009-12-07  
很有启发,可惜不能ding一下。。。

相关推荐

    介绍如何进行QTP数据驱动测试

    介绍如何进行数据驱动测试 测试脚本的开发和维护是自动化测试的重要环节,适当地调整和增强测试脚本,能提高测试脚本的灵活性,增加测试覆盖面,以及提高应对测试对象变更的能力。数据驱动方式的测试脚本开发是解决...

    自动化测试摸索-高级数据驱动测试

    高级数据驱动测试高级数据驱动测试高级数据驱动测试高级数据驱动测试高级数据驱动测试高级数据驱动测试

    高级数据驱动测试.pdf

    Test automation can be thought of as "writing software to test other software”. Using one of the commercially available automated testing tools, test scripts are written that drive the application ...

    黑盒测试功能测试或数据驱动测试

    让你知道黑盒测试,是你的首先,如果你想要知道黑盒测试法

    手把手教你搭建数据驱动测试框架构

    本文来自于testerhome,文章介绍了如何搭建基于SeleniumWebDriver的数据驱动测试框架的相关内容。在自动化测试框架中,数据驱动的意思指定的是测试用例或者说测试套件是由外部数据集合来驱动的框架。这里说的数据集...

    数据驱动测试在QTP中的实现.pdf

    此文档讲述了利用QTP进行数据驱动测试是怎么实现的。

    webdriver数据驱动测试注意事项.

    webdriver 数据驱动 webdriver 数据驱动webdriver 数据驱动webdriver 数据驱动webdriver 数据驱动webdriver 数据驱动

    基于QTP的数据驱动测试开发

    提出采用面向自动化测试的测试用例设计格式,通过QTP的编程功能,使用外部数据源来实现较复杂的数据驱动测试。具体方法是采用Excel作为测试数据源,制定Excel中测试数据的设计格式,建立专用的函数库来操作Excel数据...

    黑盒测试方法揭密,黑盒测试又被称为功能测试、数据驱动测试或基于规格说明的测试

    黑盒测试方法揭密,黑盒测试又被称为功能测试、数据驱动测试或基于规格说明的测试,实际上是站在最终用户的立场上,检验输入输出信息及系统性能指标是否符合规格说明书中有关功能需求及性能需求的规定。

    robotframework-datadriver:该库可为Robot Framework提供CSV表的数据驱动测试

    机械手数据驱动器DataDriver是用于Robot Framework的数据驱动测试库。 本文档说明了如何使用DataDriver库侦听器。 有关安装,支持等的信息,请访问有关机器人框架的更多信息,请参见 。 DataDriver用作/导入为库,但...

    test-nginx, 面向 Nginx C 模块和 OpenResty Lua库开发的数据驱动测试.zip

    test-nginx, 面向 Nginx C 模块和 OpenResty Lua库开发的数据驱动测试 电子邮件名称Test::Nginx - Nginx MODULE 和 Nginx/openresty库和应用程序的数据驱动测试脚手架 table-内容NAME描述用户指南使用 Test::Nginx ...

    sazerac一个JavaScript数据驱动单元测试

    sazerac一个JavaScript数据驱动单元测试

    在JMeter中实现数据驱动测试

    本文来自于简书,本文章主要详细介绍了如何通过存储输入数据和结果的是Excel文件,在JMeter中实现数据驱动测试,希望对您的学习有帮助。DataDrivenTesting(DDT)即数据驱动测试,是一种用于创建自动化测试的方法,...

    基于python的接口自动化测试 ddt数据驱动.docx

    在测试接口时,一个接口会先写好...采用数据驱动方式,把数据写在excel表格中,代码做封装,用数据驱动测试,两部分相互独立。python中用ddt模块来做数据驱动,代码简单好维护,调试也方便。 自己写的框架,结构如下:

    使用ddt执行数据驱动测试

    所谓数据驱动测试,简单的理解为数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变。通过使用数据驱动测试的方法,可以在需要验证多组数据测试场景中,使用外部数据源实现对输入输出与期望值的参数化,...

    灵活使用RFT数据池迭代器实现数据驱动测试

    火龙果软件工程技术中心 本文内容包括:1.RFT与数据驱动测试2.实例分析——数据驱动测试3.RFT默认支持的迭代器——顺序迭代访问和随机迭代访问4.选择合适的数据池访问方式5.结束语参考资料对数据驱动测试的支持是...

    数据驱动测试在Nunit框架中的应用

    为了解决单元测试工具Nunit本身不支持数据驱动测试的问题,提出了在Nunit框架下实现数据驱动测试的方法。该方法首先将测试类所使用的测试数据基本信息设定在ini文件中,将输入数据及预期结果存放于Excel文件中。随后...

    Python Selenium 之数据驱动测试的实现

    数据驱动模式的测试好处相比普通模式的测试就显而易见了吧!...ddt库包含一组类和方法用于实现数据驱动测试。可以将测试中的变量进行参数化。 可以通过python自带的pip命令进行下载并安装:pip install

Global site tag (gtag.js) - Google Analytics