单元测试的实施

发表于:2017-6-01 09:03

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:向润    来源:51Testing软件测试网原创

  一、单元测试的介绍
  1、单元测试和白盒测试
  要回答这个问题,需要从测试的分类谈起,见图1. 软件测试的分类。
  在单元测试阶段,那时候可能软件的界面还没有做出来,测试工程师自然就没有办法去做用户视角的测试,常会针对代码进行测试,久而久之,单元测试和白盒测试就分得不是那么清楚了。作为测试人,我们应该知道单元测试只是测试阶段中的一个过程,而白盒测试是针对代码进行测试。
  
图1. 软件测试的分类
  2、"单元"是什么?
  个人认为,单元测试阶段的测试对象,是比较灵活的,但不管怎么灵活,单元测试的颗粒度都应该是最小的。
  若是软件设计的耦合性比较低,那么在面向过程的语言,那单元应该就是某个过程或者函数,而面向对象的程序设计中,单元就是一个个的类。
  反之,若是软件设计的耦合性比较高,你把完成了某一个功能所涉及到的几个函数或者一个package中的类说成是一个单元,也没什么不可以。
  3、单元测试这个事情,我们总觉得让开发做比较合适,但是你若是很牛X的测试工程师,交给你做也是可能的。
  二、前期的单元测试工作内容
  1、计划
  有计划才能有条不紊的做事。
  单元测试也不例外,需要计划,但是什么时候做单元测试计划呢?
  计划中有些什么呢?
  单元测试的要是开展的话,测试入口是什么?又测试到什么时候结束呢?
  1)什么时候写计划
  单元测试的测试依据,应该是详细设计,很多人觉得现在做项目,哪里看得到详细设计,开发人员能够把代码按照时间点写出来就不错了,都顾不上设计。但是,我还是要说,单元测试的依据就是在编码之前对"程序的"设计",我们不要去关注这个"设计"是以什么样的形式存在,并不一定非要一个多么正式的文档,也许,它只是个Excel,或者是思维导图,甚至就只是一些图片,只有内容上写了每个包作用,每个包中包含的文件是完成了什么功能,相互之间如何传递接口数据,每个文件中的功能是怎么完成的,这就算是详设。这些内容也许在开发人员工作中,不是集中一段时间完成的,今天开发一组开会讨论了某个业务,明天开发二组又商量了另一个业务,那么作为项目的负责人,要去整理收集这些信息,当然,整理这些信息的人,极有可能是身为测试工程师的你。
  谈完了测试的依据-详设,那么单元测试何时被计划的答案就很容易得到了。就在详设完成了以后开始计划单元测试。
  有个问题是这样的"单元测试传递参数边界如何界定?单元测试测试函数时,怎么知道是不是需要测试:传递参数不允许为null 的情况 (1.函数注释里没写明,2.去问开发人员不知道,3.不知道哪些功能调用该函数)",我看了很久这个问题,猜想提问者可能是想表达当一个被测试的函数有好几个需要传递的参数,但是因为没有这几个参数的说明,传递参数不晓得怎么构造,不晓得我是否准确的理解了提问者的问题。若使我理解的那样的话,我真心觉得,最好的方法是去找知情者沟通,笨办法就是自己坐在工位上瞎猜,这是句玩笑话,我想表达的意思是,单元测试的依据就是详设,那么详设中一定会有对参数的说明,若是搞不清这些最基本的信息,工作是无法开展的。
  2)计划中包含什么
  i.测试的范围:
  · 一般最常见的的是从功能角度考虑,确定测试的是哪些功能模块对应的"单元",即对应的类或者方法
  · 也有可能是在项目中遇到算法比较复杂的部分,比如群红包分配的算法
  · 也有按照测试的类型,不仅是单元级别的功能测试,还比如有单元级别的性能测试、单元级别的安全检查
  ii.测试的环境资源:看需要哪些硬件和软件的设备,好提前准备
  iii.测试的人员:因为单元测试对测试工程师的要求是需要良好的代码能力,所以需要看看团队中who can,就who up。再一个,你可能会认为单元测试不是都是开发做吗?其实单元测试是细颗粒度的测试,有些要针对代码测试,有些也要针对界面测试,开发和测试一起,大家分工合理,才能做好单元测试
  iv.测试的入口:单元测试要进行之前,必须的入口需要定义,比如,是不是做好的详设,是不是准备好的资源、用例设计是否已经完成、是不是确定好开发人员和测试人员的工作界限。这里不给大家定死入口的标准,因为毕竟每家企业都有自己的特点,每个项目也不一样
  v.测试的出口:在计划中首先就确定单元测试的质量目标,比如"某等级的缺陷不超过3个"这样的句子。
  vi.测试进度的安排:确定某年某月某日某人要完成某些单元的测试,确定该项工作的实施人和检查者。
  vii.风险:是进行单元测试的过程中预料到的风险,并提出风险的解决措施。
  总之,计划就是定下做单元测试的人力资源、物力资源、时间安排、入口和出口。
  至于单元测试具体的工作要怎么开展,我们可以讨论一下单元测试的方案。
  2、方案
  很多人提出的问题是,怎么做好单元测试?怎么开展单元测试?这类问题比较开放性,真不好按照某种套路回答。这种问题,我想本身也没有标准答案,我只能说说我的看法。
  怎么做单元测试,这就是要确定方案
  那么方案中,要明确哪些内容呢?
  i.测哪些,不测哪些,说清楚了后,要说明原因
  ii.测试的那些,哪些重点测,哪些次重点测,要说明原因,当然,重要程度的划分可以不止重要和不重要两个等级,完全可以根据项目的规模、难度划分多个等级
  iii.重点测试和次重点测试,分别采用什么测试方式(手工、自动化)、采取哪种用例设计方法、分别要测试的人员和回归的次数,总之重点测试的部分,在人力物力和时间上肯定是倾斜的
  iv.若是手工测试,那么确定一下用例的设计模板,用例的提交地址、用例怎么评审、缺陷怎么记录,记录时的规范用、语
  v.若是自动化测试,除了要确定手工测试的那些内容之外,还要考虑用哪一款工具,测试的框架要在团队内部统一。而且自动化测试经常还要开发人员的源码融合进来,所以尽可能的要考虑测试框架和开发框架不要有违和感,莫让大家费劲的做单元测试,所以一个好的持续集成方案,也是要在单元测试方案中体现的。
  说明一点:有些测试工程师会说自己的公司里根本就没有提出过方案,看都没看到过这种文档,动手测就是了;其实,我们不应该拘泥于文档,我相信,就算公司里没有一份专门的文档说明以上的内容,但肯定也是在工作中提到过这些。
  3、用例设计
  网络上和教科书上有很多关于白盒用例设计的内容,包括逻辑覆盖法(语句、判定、条件、判定_条件、条件组合、路径)、根据控制流的基本路径法、还有数据流测试等,这里就不多说了。
  但是要补充一点的是,不管做什么测试,我还是认为功能测试要最先考虑。在保证了功能的基础上,再考虑白盒用例的设计。这并不矛盾,有的人可能会认为功能测试就是在程序的界面上操作,其实不然。
  每个方法一定都有自己的功能,先测试这个方法的功能,用黑盒用例设计方法设计测试用例,比如等价类、边界值、因果图等。等这些黑盒的用例验证过被测试的方法没有错误后,再考虑用白盒用例的设计方法进行用例设计。
  以测试界里一个很经典的三角形问题为例,我们来谈谈单元测试用例设计可以怎么设计。
  三角形问题:三个1-200之间的整数代表三角形的三条边a、b、c,判断这是一个等边三角形?还是等腰三角形?还是一般三角形?
  设计如下:c1、c2、c3三个方法是用来判断三条边的范围,isTriangle方法用来判断三边是不是能组成三角形,这四个方法都是private的访问权限,isType方法是用来判断三角形的类型,最后还有一个方法是setTriangle用来初始化三角形,这两个方法的访问权限是public。
  
图2 三角形类的设计
  根据设计,开发人员编写出以下的产品代码:
  【代码清单】
  public class Triangle
  {
  private int a;
  private int b;
  private int c;
  private  boolean c1(){   //判断a边的范围
  boolean flaga=true;
  if(a>=1&&a<=200){
  flaga=true;
  }
  else{
  flaga=false;
  }
  return flaga;
  }
  private boolean c2(){   //判断b边的范围
  boolean flagb=true;
  if(b>=1&&b<=200){
  flagb=true;
  }
  else{
  flagb=false;
  }
  return flagb;
  }
  private boolean c3(){   //判断c边的范围
  boolean flagc=true;
  if(c>=1&&c<=200){
  flagc=true;
  }
  else{
  flagc=false;
  }
  return flagc;
  }
  private boolean IsTriangle(){  //根据三角形三边的性质,判断a、b、c是否能组成一个三角形
  boolean flagTriangle=true;
  if(c1()&c2()&c3()){
  if(a<b+c&b<a+c &c<a+b){
  flagTriangle=true;
  }
  else{
  flagTriangle=false;
  }
  }
  else{
  flagTriangle=false;
  }
  return flagTriangle;
  }
  public String IsType(){
  String str=" ";
  if(IsTriangle()){
  if(a==b&&a==c&&b==c){
  str="等边三角形";
  }
  else if(a==b||a==c||b==c){
  str="等腰三角形";
  }
  else{
  str="一般三角形";
  }
  }
  else{
  str="不能组成三角形";
  }
  return str;
  }
  }
本文出自51Testing软件测试网十三周年庆活动—51Testing大咖秀,51Testing软件测试网及相关内容提供者拥有51testing.com内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像,否则将追究法律责任。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号