【转】接口测试模仿篇

上一篇 / 下一篇  2014-06-12 16:48:07 / 个人分类:测试框架

我的需求:新增商盟写接口类,包括N个接口方法定义,编写接口测试用例,并且测试通过。

  过程:

  一、配置测试类及相关spring Bean

  1、在BaseCase。java中,声明接口类,添加spring注入标签。

  比如本次新增的接口类名为XXXService,那么在BaseCase中新增此对外接口类的声明:

@ITestSpringBean
protected XXXService XXXServiceClient;

  其中XXXServiceClient是需要配置的bean。

  2、在client.xml中,配置BaseCase中新增的接口类bean, bean的class最好是Client类而不是ServiceImpl,因为测试时一般是希望通过client调用,而不是直接serviceimpl 调用。

  配置类似于:

<bean id=“XXXServiceClient”
class=“xxxx.xxxxServiceClient” />

  其中xxxxServiceClient是xxxService的实现类。

  3、在biz-dao。xml中,配置新增的DAO;比如本次需求中有2个DAO需要新增。

  4、在biz-manager。xml中,配置实现类中互相需要调用的bean,比如xxxServiceImpl中需要用到xxxService,那么需要配置好xxxService的bean。

  关于spring的配置,我是参照原来已有的spring配置模仿配置的;真正的原理还没有掌握起来。

  以上配置OK后,可在BaseCase文件中写一个test方法,看spring注入是否成功。我的test文件这样写:

   @Test
   public void test(){
       XXXService a = new xxxServiceClient();
       assertNotNull(a);
   }

  如果PASS,说明你最基础的配置已经成功。若fail,则根据提示修改。本次需求因为已有先前的一些基础配置,所以跑起来相对顺利。

  我自己理解的代码结构调用关系是(针对SC的):

  Service类-> ServiceImpl->Manager

  Service类->Client-> ServiceImpl->Manager,一般接口测试是使用这个路径。

二、编写测试用例

  1、分析测试需求

  我理解测试需求的获取来源,有2种:根据需求方给的接口说明,设计测试用例;若需求方没有给接口说明,则自己看接口代码来分析。

  本次选择了CreateBusinessUnit接口作为测试对象,分析这个接口的实现。主要是:1个正常流,N个异常流。

  2、在QC中创建测试用例

  说明:按照规范命名测试用例名及步骤名,这个规范每人的习惯不同,目前店铺线的基本规范已经由元化整理出来。

  接口测试用例设计功能测试用例设计的基本思想是一致的,会写功能测试用例也一定会写接口测试用例。一般有:

  ●  正常流用例:正常的主流程业务校验;

  ●  分支流用例:校验分支业务,比如为校验字段大小符合某种条件下的业务校验。

  ●  异常流用例:传入不合法的参数或者不满足业务规则的参数,校验。

  CreateBusinessUnit接口对BusinessUnitDO的校验比较简单,用例设计如下。不需要数据准备。

  目前接口测试用例的规范,跟功能测试不同;功能测试是每个校验点一个用例,而接口测试因为校验点是比较正规简单的,一般都只需要一个步骤。所以现在接口测试用例的管理,一般一个接口就一个用例,每个用例以步骤为校验点。如果按照功能测试用例的编写方法,那么这些步骤都是需要拆分成独立用例的。个人意见,接口测试用例还是目前这种方式管理比较好!

3、编写接口测试用例代码

  有了第三步的接口测试用例,则根据用例编写用例代码。

  规则:QC中的一个用例就是一个test。java文件,一个步骤即一个测试方法。

  上面的用例转成代码就类似于:

  一个有对数据库操作的测试方法中,一般包括这些内容:

  参数初始化:测试方法中传入的参数,需要准备,比如上图中的userId,userNumId等输入参数,需要初始化。

  数据清除:接口用例执行后,会往数据库中插入记录,这些记录需要及时回收,避免太多数据库垃圾数据;

  执行测试接口:调用测试对象方法。没这个内容你测啥?

  校验数据:数据执行成功后校验预期结果和实际结果。

4、Run/debug测试用例代码

  这应该是整个过程中最关键部分。debug过程中,会遇到不同情况的问题,导致用例跑不通。

  我把过程中遇到的几个点都说明下:

  配置中,其实还遗漏了sqlmap的配置,如果你的测试用例中需要访问数据库的话。找到代码中需要引用的sqlmap_mapping.xml文件,配到测试工程下的sql-map.xml中,如:

  <sqlMap resource="sql/businessunit/businessunit_sqlmap_mapping.xml"/>

  此sqlmap中配置了所有ibatisDAO调用的sql id。

  至于到底用到了那份sqlmap文件,就需要我们查看代码追踪了。

  我是在进行配置的时候,就直接配置了接口要用的sqlmap。

  * 刚开始时,我初始化变量,就用了一个值,这个值给所有DO的字段属性set值;但发现最好还是能够区分下,这样传入的参数能够明确点。

  * 进行数据库校验的时候,本想是直接调用service下的查询方法来校验结果;但经过元化的提醒,测试的预期结果最好是由自己来确认,而不是调用其他开发写的方法,若方法有问题那么校验就不准确了。所以查询数据的时候,增加了UnitUtil。java文件,里面就是自己写的一个方法用例获取自己需要的内容。比如queryUnit方法,我就是通过unit_name查询数据库中存在的记录,然后进行对比。

  * Run一直失败,日志中是说expect和auctual不一致,通过debug发现,是因为我获取的auctual中有很多空值,但实际数据库中是有的。主要原因就需要看queryUnit是怎么实现的。

  这个是现在的实现:

List <BusinessUnionDO> businessUnionDOList = (List<BusinessUnionDO>) jdbcTemplate.query(sql.toString(),
new BusinessUnitRowMapper(),unit_name);

  下面的是原来写的,直接用了ParameterizedBeanPropertyRowMapper。

List <BusinessUnionDO> businessUnionDOList = (List<BusinessUnionDO>) jdbcTemplate.query(sql.toString(),
ParameterizedBeanPropertyRowMapper.newInstance(BusinessUnionDO.class),unit_name);

  ParameterizedBeanPropertyRowMapper类做的事情没有深究,大概是将DO的属性和数据库做个映射,如果数据库的字段和DO的属性命名是符合一些规范的,那么就可以不手工写映射就可以匹配。

  但本次BusinessUnitDO中的属性字段跟数据库字段没有满足默认映射的条件,所以刚开始用这个类方法时一直assert对比不成功。

  既然不能用默认的,就需要手工写映射关系,如:

  这样,映射问题解决了。

解决映射问题之后,通过assertLenientEquals就会把expect和auctual中不一致的内容单独拿出来,分析不同之处。

  * debug,发现expect和auctual的数据不同,主要是userNumId这个在auctual中是不存在的,即这个字段是不需要进行对比的。那么就可以在expect中把这个字段设置成null,即businessUnion.setAdminUserIdNum(null);, 去掉此字段的对比。

  * 另外说明一点,我的expect取的是DO对象,而在create时传入的也是DO对象,据元化介绍,java的方法可能会篡改传入的DO内容, 这样的话你预期想要的结果就不是你认为应该怎样的结果了。为避免这种情况产生,以DO为参数传入的时候,要使用cloneDo,这样保证你的DO是不变的。如:

  从这次实践中,自己的感受是:

  * 当你无从下手的时候,看别人的实现;

  * 自己不会主动写,那么先模仿写,模仿无罪;

  * 尽量自己debug,调式过程可以帮助你了解更多;

  * 不要怕太多不懂的东西,不懂的先不要追究,能够用起来之后再把它搞懂。



TAG:

 

评分:0

我来说两句

我的栏目

日历

« 2024-04-28  
 123456
78910111213
14151617181920
21222324252627
282930    

我的存档

数据统计

  • 访问量: 9341
  • 日志数: 10
  • 建立时间: 2014-06-11
  • 更新时间: 2014-06-12

RSS订阅

Open Toolbar