单元测试

  单元测试(unit testing) ,是指对软件中的最小可测试单元进行检查和验证。

  单元测试不是为了证明您是对的,而是为了证明您没有错误。

  单元测试主要是用来判断程序的执行结果与自己期望的结果是否一致。

  关键是在于所用的测试用例(Test Case) 。

JUnit

  JUnit是一个Java语言的单元测试框架。

  项目主页:http://junit.org/

  Java的很多IDE,比如Eclipse集成了JUnit,只需要在build path中添加Library并选择想用的版本即可。

  JUnit的两种主要版本是JUnit 3.8和JUnit 4,前者使用反射,后者使用反射和注解。

  博文回顾:本博客上次介绍JUnit的时候是在反射和注解之后:

  http://www.cnblogs.com/mengdd/archive/2013/02/02/2890204.html

  

结合实例来说明单元测试的用法:

1.编写目标类源代码

  新建一个项目,起名叫JUnitTest,首先编写一个目标类Calculator:

package com.mengdd.junit;

public class Calculator
{
public int add(int a, int b)
{
return a + b;
} public int subtract(int a, int b)
{
return a - b;
} public int multiply(int a, int b)
{
return a * b;
} public int divide(int a, int b)
{
return a / b;
}
}

2.添加JUnit库

  然后为了使用JUnit,需要加入库:

  右键选择项目Properties->左侧Java Build Path->标签Libraries->Add Library...

  弹出的对话框中选JUnit,然后Next,再选择JUnit 3或者JUnit 4.

  本文示例选择JUnit 3。

3.创建测试类

  这里需要注意以下几点:

  1.使用JUnit的最佳实践:源代码和测试代码需要分开。

  所以可以新建一个名叫test的source folder,用于存放测试类源代码。这样在发布程序的时候测试类的程序就可以丢掉了。

  但是这两个文件夹中的类编译出的class文件都会在同一个bin文件夹中。

  2.测试类和目标源代码的类应该位于同一个包下面,即它们的包名应该一样。

  这样测试类中就不必导入源代码所在的包,因为它们位于同一个包下面。

  3.测试类的命名规则

  在要测试的类名之前或之后加上Test。

  此步骤完成后项目目录如下:

  

4.测试类代码编写

  测试类必须继承于TestCase类。

  TestCase文档说明:

public abstract class TestCase
extends Assert
implements Test

A test case defines the fixture to run multiple tests.

To define a test case
1) implement a subclass of TestCase
2) define instance variables that store the state of the fixture
3) initialize the fixture state by overriding setUp
4) clean-up after a test by overriding tearDown.
Each test runs in its own fixture so there can be no side effects among test runs.

  (本文最后参考资料中会给出JUnit文档的网盘链接,有需要可下载)

  还有一个很重要的Assert类,参见文档,全是static void方法。

对于测试类中方法的要求:

  在JUnit 3.8中,测试方法需要满足如下原则:

  1.public的。

  2.void的。

  3.无方法参数。

  4.方法名称必须以test开头。 (它通过反射找出所有方法,然后找出以test开头的方法)。

Test Case之间一定要保持完全的独立性,不允许出现任何的依赖关系。

  删除一些方法后不会对其他的方法产生任何的影响。

  我们不能依赖于测试方法的执行顺序。

综上,编写代码如下:

package com.mengdd.junit;

import junit.framework.Assert;
import junit.framework.TestCase; public class CalculatorTest extends TestCase
{
public void testAdd()
{
Calculator calculator = new Calculator();
int result = calculator.add(1, 2);
// 判断方法的返回结果
Assert.assertEquals(3, result);// 第一个参数是期望值,第二个参数是要验证的值
} public void testSubtract()
{
Calculator calculator = new Calculator();
int result = calculator.subtract(1, 2);
// 判断方法的返回结果
Assert.assertEquals(-1, result);// 第一个参数是期望值,第二个参数是要验证的值 } public void testMultiply()
{
Calculator calculator = new Calculator();
int result = calculator.multiply(2, 3);
// 判断方法的返回结果
Assert.assertEquals(6, result);// 第一个参数是期望值,第二个参数是要验证的值 } public void testDivide()
{
Calculator calculator = new Calculator();
int result = calculator.divide(12, 3);
// 判断方法的返回结果
Assert.assertEquals(4, result);// 第一个参数是期望值,第二个参数是要验证的值 } }

  运行一下:右键选择该类,Run As->JUnit Test

  (可以在此处右键选择Run重复运行)

  JUnit的口号:Keep the bar green to keep the code clean.

5.代码重构:setUp()方法的使用

  有一个原则:DRY(Don’t Repeat Yourself)

  所以对代码进行重构,将重复的生成对象的部分放在setUp()方法中。

  (重写的时候将protected变为public,继承的时候扩大访问范围是没有问题的。)

  先进行一个方法的测试测试:

  在CalculatorTest类中加入代码如下:

    @Override
public void setUp() throws Exception
{
System.out.println("set up");
} @Override
public void tearDown() throws Exception
{
System.out.println("tear down");
}

  再次运行后发现Console中输出如下:

  说明这两个方法执行了多次。

  在每个测试用例之前执行setUp(),每个测试用例执行之后,tearDown()会执行。

  即对于每个测试用例,执行顺序为:

  1.setUp()

  2.testXXX()

  3.tearDown()

  重构:使用成员变量生成对象(为了能在每个方法中都用到),将生成对象的语句放在setUp()中,注意这里为每一个测试用例都会生成新的对象。

  重构后代码如下:

package com.mengdd.junit;

import junit.framework.Assert;
import junit.framework.TestCase; public class CalculatorTest extends TestCase
{ private Calculator calculator = null; @Override
public void setUp() throws Exception
{
System.out.println("set up");
// 生成成员变量的实例
calculator = new Calculator();
System.out.println(calculator);
} @Override
public void tearDown() throws Exception
{
System.out.println("tear down");
} public void testAdd()
{
int result = calculator.add(1, 2);
// 判断方法的返回结果
Assert.assertEquals(3, result);// 第一个参数是期望值,第二个参数是要验证的值
} public void testSubtract()
{
int result = calculator.subtract(1, 2);
// 判断方法的返回结果
Assert.assertEquals(-1, result);// 第一个参数是期望值,第二个参数是要验证的值 } public void testMultiply()
{
int result = calculator.multiply(2, 3);
// 判断方法的返回结果
Assert.assertEquals(6, result);// 第一个参数是期望值,第二个参数是要验证的值 } public void testDivide()
{
int result = calculator.divide(12, 3);
// 判断方法的返回结果
Assert.assertEquals(4, result);// 第一个参数是期望值,第二个参数是要验证的值 } }

  运行后控制台输出:

  说明每一个测试的方法前后都会有setUp()和tearDown()方法的调用,所以每次生成的都是一个新的对象,各个方法之间没有干扰

参考资料

  圣思园张龙老师Unit Test系列视频教程。

  CHM格式文档网盘链接:

  JUnit 3.8.1:http://pan.baidu.com/share/link?shareid=539342&uk=2701745266

  JUnit 4.0:http://pan.baidu.com/share/link?shareid=539345&uk=2701745266

JUnit基础及第一个单元测试实例(JUnit3.8)的更多相关文章

  1. Web框架本质及第一个Django实例 Web框架

    Web框架本质及第一个Django实例   Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web ...

  2. Web框架本质及第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...

  3. Django之Web框架本质及第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...

  4. Web的本质以及第一个Django实例.

       Web框架的本质:    所有的Web应用本质上就是一个socket服务器, 而用户的浏览器就是一个socket客户端. import socket sk = socket.socket() s ...

  5. DAY15-web框架本质及第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...

  6. (一)Maven基础及第一个Maven工程

    一.Maven介绍 ANT/Maven/gradle是一个项目管理工具,它包含了一项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecy ...

  7. React学习笔记-1-什么是react,react环境搭建以及第一个react实例

    什么是react?react的官方网站:https://facebook.github.io/react/下图这个就是就是react的标志,非常巧合的是他和我们的github的编辑器Atom非常相似. ...

  8. ArcGIS API for JavaScript开发环境搭建及第一个实例demo

    原文:ArcGIS API for JavaScript开发环境搭建及第一个实例demo ESRI公司截止到目前已经发布了最新的ArcGIS Server for JavaScript API v3. ...

  9. Java基础教程1:环境配置及第一个HelloWorld.java

    本文主要介绍JDK环境配置.Sublime Text3配置及第一个HelloWorld.Java程序.运行环境为Win10系统,使用JDK1.8版本. 1. JDK下载及环境配置 1.1 JDK下载 ...

随机推荐

  1. 响应式布局:Flexbox应用总结

    距离上篇文章<布局神器:Flexbox>的发表已有一周时间,转眼这周又到了周五(O(∩_∩)O~~): 习惯性在周五对自己的一周工作进行下总结,记录下这周值得被纪念的工作事件,无论是好的, ...

  2. java 版本SQLHelper

    package com.jack.SQLHelper; import java.sql.*;import java.util.logging.*;import javax.swing.table.*; ...

  3. 免费邮件服务器:MailEnable

    官方网站地址:www.mailenable.com 下载最新版的 Standard Edition (FREE) 安装之前请留意安装指引就可以了,安装上去之后,直接就可以使用了 安装指引上写的清清楚楚 ...

  4. [Cycle.js] Read effects from the DOM: click events

    So far we only had effects that write something to the external world, we are not yet reading anythi ...

  5. 细说php(六) 数组

    一.数组概述 1.1 数组是复合类型 1.2 数组中能够存储随意长度的数据, 也能够存储随意类型的数据 二.数组的类型 2.1 索引数组: 下标是顺序整数作为索引 <?php $user[0] ...

  6. android内存优化之图片压缩和缓存

    由于手机内存的限制和网络流量的费用现在,我们在加载图片的时候,必须要做好图片的压缩和缓存. 图片缓存机制一般有2种,软引用和内存缓存技术. 1.压缩图片:压缩图片要既不能模糊,也不能拉伸图片. 图片操 ...

  7. 最小生成树prim算法———模板

    codevs.cn 最优布线问题 #include<cstdio>#include<cstring> bool u[101]; int g[101][101],minn[101 ...

  8. 管理员权限dropfiles和copydata小时失败问题

    //处理低权限向高权限进程发消息的失败的问题 if(windows::version::instance()->IsVistaOrLater()) { typedef BOOL (WINAPI ...

  9. 运行一个Hadoop Job所需要指定的属性

    1.设置job的基础属性 Job job = new Job(); job.setJarByClass(***.class); job.setJobName("job name") ...

  10. IE查看控件时常

    一.按一下F12 二.找到探查器 三.点击开始配置文件 四.当前视图:改成调用树的形式 然后工具事件去查询 如图: