第一个要讲的是测试数据的管理,因为在我以往的公司中,我发现这方面是大家最容易忽略,但却是影响成败的最关键的几个因素之一。
说到测试数据,我想大家第一个反应就是数据库。现如今大多数产品,尤其是互联网产品都是使用数据库来保存数据的。以下的例子中,我均已数据库为例。那么在测试中,测试数据的准备和维护就成了一个很重要的方面。同样的,自动化测试中,测试数据的管理也成为了一个难点。管理不好,你根本没法自动化,因为你的脚本不能够重复执行,注意重复执行的重要性。不能重复执行的脚本,不配称为自动化。 也是不能加入持续集成流程中的。这也是我痛恨的那些为了KPI而被创造出来的,高大上的,“所谓的测试平台”的特性。
好了,既然提到了测试数据,那么我们先把测试数据分个类吧。
按使用方式分类
共享数据:所有的case或者是一些case共同使用的测试数据。
OK,貌似我们看到了使用共享数据的方式除了速度快以外貌似没什么出众的地方了,而且缺点貌似也很严重,大家会不会想,那么我们就不要用这种方式了好不好? 其实也是不对的,只要使用得当,这种方式在某些场景下也是比较好的方案。具体我后面再说
隔离数据:每个case都有独享测试数据,case之间互不影响,说白了就是为每个case都做setup和teardown的操作。case执行前创造数据,执行后销毁数据。
按创建数据的类型分类:
调用开发接口:
好吧我说了太多这种方式的缺点,因为我曾经是真的被坑的很惨。 所以我是不建议用这种方式的。
直接使用sql:就是直接写sql创造和销毁数据。
好了这种分类我也说完了。可以看出我是比较偏向使用sql创造数据的。第一种分类的时候虽然我说共享数据比较坑,但是在某些场景中还是很有用的。但是第二种分类中,我十分的强烈的不建议使用调用开发接口创造数据的方式。case一旦多了,一个bug就能让你崩溃。想象一下如果case库里有5千条脚本,一个bug搞出了100以上的脚本fail是什么感觉吧(我们曾经是7千,迭代一开始,就得专门找俩人维护脚本,什么也不干)。
OK,说完了两种分类,那么我们说说如何在我们的测试中使用这些数据管理方式吧。想了想,还是以我现在给我们公司写的这个框架举例子好了。
in-line 方式:
其实我是实在不知道该怎么给这种方式起名了,所以借用了xunit test partten一书中的定义。而且我也实在不知道in-line方式翻译成中文该怎么说,所以就这么叫它吧。它的使用方式很简单,也很原始。 你直接在脚本中,或者在各种框架中的setup方法,teardown方法中直接写代码创建这些数据。例如testng中就有beforeMethod,beforeClass以及beforeSuit等标签帮你初始化测试环境。你可以使用原始的JDBC语句,也可以使用例如mybatis这一类的ORM框架。强烈建议用ORM,配置个级联操作直接给脚本调用就行了。在脚本里写sql简直是噩梦。
注册式:
这个方式不太好理解,什么叫注册式呢?就是你把测试数据注册到框架中,并说明是共享数据,还是隔离数据。这些数据的作用域是什么。接下来的事情就交给框架做了,框架帮你在测试执行前创建测试数据,测试结束后销毁数据。完全不用测试人员关心。这是我比较推崇的方式,我在接口测试中使用的就是注册式加in-line方式管理数据的,说明一下,用的是直接写sql的方式入库的,只不过sql由框架生成,我们不用管。 好了,这么说实在有点难懂。 让我们来看一下例子吧。
看过我在Tester Home的第一篇帖子的人应该对注册式数据管理有印象。 没看过的可以看一下,下面是链接:
NO_CODE接口测试框架
在我的框架中,我创建了一个叫做DataBaseFile的注解(注解为java语言特性,非java工程师请google),注解里定义了两个属性,一个叫filePath。规定了数据文件的路径,这个数据文件做什么的呢?看下面截图。
这是一个excel文件,大家看这个是不是很像数据库的表结构。 答案是对了,其实这个文件就是从navicat for mysql导出来的。我们的思路是在UI上创建数据,然后用像navicat这种数据库客户端导出一个excel文件。框架会读取这个文件拼出三种sql并封装在一个对象里。这三种sql分别是select,insert,delete。这三种sql就可以用来维护我们的测试数据了。这样就解决了测试人员写sql的问题。
OK,让我们看看DataBaseFile注解的第二个属性----作用域。这个属性是一个枚举类型,这个枚举暂时有两种值,method和class。其实这个属性规定了测试数据的作用域。如果测试类指定了method作用域,那么这个数据就是“隔离数据”,框架会在每一个测试用例执行前创建数据,测试结束后删除数据。如果指定了class作用域,那么框架会在这个类的所有测试方法开始前创建数据,所有的测试结束后销毁数据。其实这就是“共享数据”了,测试类中所有的case共享这些数据。 有些时候这个策略是比较有用的。 比如被测功能不会对数据库造成影响的情况,例如查询某些订单的功能。测试这个功能的一批用例,就是可以使用同样的数据的,只不过可能我这个用例是按id查,下个用例按name查,其他的可能对查询结果做正序排序或者倒叙排序。所以我在一开始也说共享数据在某些情况下也是蛮有用的。其实还应该有个suit作用域,只不过我暂时没用上。
具体思路就是创建一个基类,在基类里维护一个List,list里装的就是读取excel文件后分析出的三种语句的集合。在before和after方法里使用java反射技术读取子类的注解。这样就可以控制子类的测试行为了。 是不是还不算复杂?
transaction roll back:
这种模式是用来销毁测试数据的不二神器,专门在单元测试和小型集成测试中用来销毁测试数据的。 不过此模式依赖软件设计支持这种模式。也是就是大家说的需要软件有可测试性。具体怎么搞呢,就是要求开发在设计的时候就把测试考虑进去,不能在持久化层就把事务写死在被测方法里。而是把事务专门提取出一层来,或者使用spring这种提供了事务管理的框架管理软件的事务。这样的话,我们就可以在测试脚本中显示的控制事务。 在测试结束的时候,直接一个roll back 就搞定了。 管你被测功能到底对数据库做了什么,我不care~,直接暴力的全部回滚。 注册式数据管理方式的缺点就是它无法删除被测功能本身创造出来的数据。需要使用in-line的方式显示的删除这部分数据。 但是transaction roll back就方便多了。我心中完美的管理方式其实就是注册式加上transaction roll back。 所以现在我们都要求开发再设计之初就考虑到这方面的事。 这也是方便他们做单元测试。 可惜这种方式不能用在接口测试和UI自动化中。
原文发表于:Testerhome;
作者:ycwdaaaa ;
原文链接:https://testerhome.com/topics/4773
目前腾讯WeTest服务器性能测试已经正式对外开放,点击链接:http://wetest.qq.com/gaps/立即体验!
提早接入游戏测试,通过工具自动化测试、高效率低成本发现问题,提升游戏品质“轻量测试”,点击链接:http://wetest.qq.com/cloud/index.php/index/tinyTest立即体验!