单元测试的测试工具
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单元测试的测试工具相关的知识,希望对你有一定的参考价值。
现在开始介绍单元测试工具,分别按编程语言进行分组介绍。 CppUnit
首先是CppUnit,这是C++单元测试工具的鼻祖,免费的开源的单元测试框架。由于已有一众高人写了不少关于CppUnit的很好的文章,老纳就不现丑了,想了解CppUnit的朋友,建议读一下Cpluser 所作的《CppUnit测试框架入门》,。该文也提供了CppUnit的下载地址。
C++Test
然后介绍C++Test,这是Parasoft公司的产品。[C++Test是一个功能强大的自动化C/C++单元级测试工具,可以自动测试任何C/C++函数、类,自动生成测试用例、测试驱动函数或桩函数,在自动化的环境下极其容易快速的将单元级的测试覆盖率达到100%]。[]内的文字引自,这是华唐公司的网页。老纳想写些介绍C++Test的文字,但发现无法超越华唐公司的网页上的介绍,所以也就省点事了,想了解C++Test的朋友,建议访问该公司的网站。华唐公司代理C++Test,想要购买或索取报价、试用版都可以找他们。
Visual Unit
最后介绍Visual Unit,简称VU,这是国产的单元测试工具,据说申请了多项专利,拥有一批创新的技术,不过老纳只关心是不是有用和好用。[自动生成测试代码 快速建立功能测试用例程序行为一目了然 极高的测试完整性 高效完成白盒覆盖 快速排错 高效调试 详尽的测试报告]。[]内的文字是VU开发商的网页上摘录的,。前面所述测试要求:完成功能测试,完成语句覆盖、条件覆盖、分支覆盖、路径覆盖,用VU可以轻松实现,还有一点值得一提:使用VU还能提高编码的效率,总体来说,在完成单元测试的同时,编码调试的时间还能大幅度缩短。算了,不想再讲了,老纳显摆理论、介绍经验还是有兴趣的,因为可以满足老纳好为人师的虚荣心,但介绍工具就觉得索然无味了,毕竟工具好不好用,合不合用,要试过才知道,还是自己去开发商的网站看吧,可以下载演示版,还有演示课件。
gtest
gtest测试框架是在不同平台上(Linux,Mac OS X,Windows,Cygwin,Windows CE和Symbian)为编写C++测试而生成的。它是基于xUnit架构的测试框架,支持自动发现测试,丰富的断言集,用户定义的断言,death测试,致命与非致命的失败,类型参数化测试,各类运行测试的选项和XML的测试报告。需要详细了解的朋友可以参阅《玩转Google单元测试框架gtest系列》该篇文章。 JUnit
JUnit 是 Java 社区中知名度最高的单元测试工具。它诞生于 1997 年,由 Erich Gamma 和 Kent Beck 共同开发完成。其中 Erich Gamma 是经典著作《设计模式:可复用面向对象软件的基础》一书的作者之一,并在 Eclipse 中有很大的贡献;Kent Beck 则是一位极限编程(XP)方面的专家和先驱。JUnit 设计的非常小巧,但是功能却非常强大。JUnit ——是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言)。主要用于白盒测试,回归测试。
JUnit的好处和JUnit单元测试编写原则:
好处:可以使测试代码与产品代码分开;针对某一个类的测试代码通过较少的改动便可以应用于另一个类的测试;易于集成到测试人员的构建过程中,JUnit和Ant的结合可以实施增量开发;JUnit是公开源代码的,可以进行二次开发;可以方便地对JUnit进行扩展;
编写原则:是简化测试的编写,这种简化包括测试框架的学习和实际测试单元的编写;是使测试单元保持持久性;是可以利用既有的测试来编写相关的测试;
JUnit使用帮助
1、junit3.x版本,我们通常使用junit 3.8
(1)、使用junit3.x版本进行单元测试时,测试类必须要继承于TestCase父类;
(2)、测试方法需要遵循的原则:
A、public的
B、void的
C、无方法参数
D、方法名称必须以test开头
(3)、不同的Test Case之间一定要保持完全的独立性,不能有任何的关联。
(4)、我们要掌握好测试方法的顺序,不能依赖于测试方法自己的执行顺序。
dome:
public class TestMyNumber extends TestCase
private MyNumber myNumber;
public TestMyNumber(String name)
super(name);
// 在每个测试方法执行 [之前] 都会被调用
@Override
public void setUp() throws Exception
// System.out.println(欢迎使用Junit进行单元测试…);
myNumber = new MyNumber();
// 在每个测试方法执行 [之后] 都会被调用
@Override
public void tearDown() throws Exception
// System.out.println(Junit单元测试结束…);
public void testDivideByZero()
Throwable te = null;
try
myNumber.divide(6, 0);
Assert.fail(测试失败);
catch (Exception e)
e.printStackTrace();
te = e;
Assert.assertEquals(Exception.class, te.getClass());
Assert.assertEquals(除数不能为 0 , te.getMessage());
2、junit4.x版本
(1)、使用junit4.x版本进行单元测试时,不用测试类继承TestCase父类,因为,junit4.x全面引入了Annotation来执行我们编写的测试。
(2)、junit4.x版本,引用了注解的方式,进行单元测试;
(3)、junit4.x版本我们常用的注解:
A、@Before 注解:与junit3.x中的setUp()方法功能一样,在每个测试方法之前执行;
B、@After 注解:与junit3.x中的tearDown()方法功能一样,在每个测试方法之后执行;
C、@BeforeClass 注解:在所有方法执行之前执行;
D、@AfterClass 注解:在所有方法执行之后执行;
E、@Test(timeout = xxx) 注解:设置当前测试方法在一定时间内运行完,否则返回错误;
F、@Test(expected = Exception.class) 注解:设置被测试的方法是否有异常抛出。抛出异常类型为:Exception.class;
G、@Ignore 注解:注释掉一个测试方法或一个类,被注释的方法或类,不会被执行。
dome:
package com.an.junit;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestMyNumber
private MyNumber myNumber;
@BeforeClass
// 在所有方法执行之前执行
public static void globalInit()
System.out.println(init all method...);
@AfterClass
// 在所有方法执行之后执行
public static void globalDestory()
System.out.println(destory all method...);
@Before
// 在每个测试方法之前执行
public void setUp()
System.out.println(start setUp method);
myNumber = new MyNumber();
@After
// 在每个测试方法之后执行
public void tearDown()
System.out.println(end tearDown method);
@Test(timeout=600)// 设置限定测试方法的运行时间 如果超出则返回错误
public void testAdd()
System.out.println(testAdd method);
int result = myNumber.add(2, 3);
assertEquals(5, result);
@Test
public void testSubtract()
System.out.println(testSubtract method);
int result = myNumber.subtract(1, 2);
assertEquals(-1, result);
@Test
public void testMultiply()
System.out.println(testMultiply method);
int result = myNumber.multiply(2, 3);
assertEquals(6, result);
@Test
public void testDivide()
System.out.println(testDivide method);
int result = 0;
try
result = myNumber.divide(6, 2);
catch (Exception e)
fail();
assertEquals(3, result);
@Test(expected = Exception.class)
public void testDivide2() throws Exception
System.out.println(testDivide2 method);
myNumber.divide(6, 0);
fail(test Error);
public static void main(String[] args)
有兴趣的朋友可以下下来仔细研究下,也可以到安安DIY创作室博客一起讨论一下。
JUnit-addons
对JUnit的一些补充,比如设置、获取被测试对象的私有属性的值,调用被测试对象的私有方法等。
常用类:junitx.util.PrivateAccessor
Spring 测试框架
可以测试基于Spring的应用,通过配置文件和注解自动组装需要的单元测试对象。
提供了一些常用的J2EE Mock对象,比如HttpSession的Mock类等。
可以支持数据库自动回滚,以防止对数据库的单元测试(插入,删除等)不可重复执行,防止修改数据库状态等。
DJUnit
通过代码自动产生Mock对象,省去了自己手动编写N多的Mock类。
此外,它的Eclipse插件还可以做到测试覆盖率、分支统计。
EasyMock
功能同DJUnit,也是通过编程自动Mock掉与测试对象无关的类,方法。
使用这款工具,测试工作=填表格。
是广州凯乐软件技术有限公司开发的一款C/C++单元测试工具及集成测试工具,独有的白盒用例设计器。
测试工作就是填表格而已,很容易,不需要写代码。
什么嵌入式测试,死循环测试等难度很高的,都只是填表格就自动测出来了。
在百度搜一下:广州凯乐软件技术有限公司,进官网就可以下载使用了。
测试篇——初探单元测试
初探单元测试
目录:
-
单元测试的核心意义
-
单元测试的特点
-
一个简单的单元测试demo
-
构建可测试的代码以及初探Mock框架NSubstitute
单元测试的核心意义
- 验证代码健壮性,无 Bug
- 项目升级,重构后涉及到旧的逻辑,保证以旧逻辑的稳定运行
单元测试的特点
- 单元测试可重复运行
- 单元测试持续长期有效,并且返回结果一致
- 单元测试在内存中运行,不会依赖外部组建(例如真实的数据库,真实的文件等)
- 单元测试可以快速返回结果
- 一个测试方法只测试一个问题(最小的粒度)
一个简单的单元测试demo
-
这里创建一个类 Product 代表商品; ProductCollection 代表配送的商品集合, DistributeProduct 方法根据传入的商品 Id 集合代表需要配送的商品(具体看项
目代码) -
创建一个基于 Framework 的单元测试项目 MyUnitTestApplication ,添加一个单元测试类 ProductCollectionTests , ,添加一个单元测试方
法 ProductCollction_DistributeProduct_Test- 注意点 1 :单元测试方法命名规范一般是 测试主体 _ 期待返回结果 _ 传入参数。
- 注意点 2 :单元测试类需要添加 [TestClass] 特性,单元测试方法需要 [TestMethod] 特性修饰
-
在单元测试的方法体内右键运行单元测试,如下图所示,可以在右侧测试资源管理器中看到看到运行结果;例如把第三个断言修改成一个错误的结果,右
键运行单元测试,就会出现测试未通过显示。 -
这样一个最简单的单元测试就写完了,假如将来有人修改了 DistributeProduct 方法,再将这个单元测试运行一遍就可以验证修改是否存在 Bug.
构建可测试性的代码
- 关于 demo 的依赖性问题:单元测试的用例能够成功运行取决于内部所有逻辑正常运行,例如上面 demo 中的测试核心是 DistributeNotice 对象,因为测试
的是它的 ToNotice 方法向外部发送通知消息。所以这里的 ProductCollection 对象依赖于 DistributeNotice 对象。但是,一般向外部发送信息需要 一些配置以
及 第三方的代理类(外部依赖)。例如如下图所示: DirstributeNotice 对象依赖着 ConfigurationManager 和 EmailSend 。此时单元测试已经不能进行了,因为需
要考虑其他的外在因素。
-
-
我们的解决方案是:此时我们可以添加一个 间接层。让原本依赖于 类或者 外部资源的对象抽象成依赖于它们的 接口,然后通过接口动态生成一个模拟的实现
类。(这也是设计原则中所谓的 面向接口编程)于是我们的依赖关系变为下图:
- 修改我们的代码,将实现类抽象成为接口;
基于接口重写编写单元测试,这里我们用到了 Mock 接口单元测试,使用了开源的 Mock 框架 NSubstitute 。(测试过程中替代真实对象的内存级别虚
拟对象)
- 所以,单元测试的关键是面向接口,面向抽象。使各个组件,各个类依赖于接口,当代码耦合度过高将无法进行单元测试。
- 当我们需要测试一些类中受保护的方法测试时候,将会遇到下面的问题:
- 在我们实现业务过程中,在类的内部经常会出现一些受保护的方法,然后测试类只会有一个公共的入口,此时我们要怎样测试这些受保护的方
法的业务逻辑呢?例如下图所示:我们在我们的 ProductCollection 集合类中添加一个方法 ValidatorProduct , ,根据产品的编号,判断产品的数量和价格是否合适,从而
判断这个产品是否合适。在编写方法过程中,我们遵循单一职责原则,将验证逻辑碎片化以备将来扩展和重用,但是这些逻辑都是重要逻辑,我们想
要测试它们,然而我们只有一个公共的方法入口 ValidatorProduct ,我们不能单独的测试其中一个的逻辑。
- 在我们实现业务过程中,在类的内部经常会出现一些受保护的方法,然后测试类只会有一个公共的入口,此时我们要怎样测试这些受保护的方
此时我们的解决方案是:我们可以在测试环境下,提供一个继承于测试类的子类,在子类中提供这些方法的可测试版本。如下图所示:我们建立了一个子
类 ProductCollectionAccessibility , ,通过继承的方式,在 ValidatorPriceAccessibility 方法中和 ValidatorNumberAccessibility 分别测试父类的验证产品价格和数
量的方法。
我们经常需要完善我们的测试用例,
- 我们的代码完成后会持续的进行修改,重构。在这个过程中,代码会进行修改,从而会对以前的代码造成影响。此时我们就需要一个保障。这个保证就是
单元测试,基于一个测试用例很完善的单元测试项目,我们修改后,只需要将单元测试重新运行一遍,就可以保证重构修改代码是否有 Bug ,是否有副作
用。
- 单元测试不仅仅验证代码正确性,无 Bug, 也保证了代码在生命周期中一直被完善和重构,让其越来越有价值,不会成为公司的技术债务。
以上是关于单元测试的测试工具的主要内容,如果未能解决你的问题,请参考以下文章