软件测试之JUnit单元测试

JUnit单元测试

JUnit简介
	由Erich Gamma和Kent Beck编写
	回归测试框架
	开源的Java测试框架
	属于白盒测试,由开发人员来编写
	主要用来判断程序的执行结果与自己期望的结果是否一致
	很重要的一个方面是测试用例(Test Case)
	不是证明您是对的,而是为了证明您没有错误
JUnit单元测试优点
	极限编程(最大化的开发效率)
	极限编程要求在编写代码之前先写测试,这样可以强制你在写代码之前好好的思考代码的功能和逻辑  
	否则编写的代码很不稳定,那么你需要同时维护测试代码和实际代码,这个工作量就会大大增加  
	因此在极限编程中,基本过程是这样的:构思-编写测试代码-编写代码-测试  
	而且编写测试和编写代码都是增量式的,写一点测一点  
	在编写以后的代码中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度
JUnit3.8基于反射,JUnit4.0基于注解
	所以JUnit3测试类必须继承TestCase,JUnit4测试类不需要继承TestCase
使用JUint的规定
	对测试包的规定
	    测试包必须和src是同级目录,并且是Source Folder,否则不会被编译  
	    测试类和被测试类虽然不在一个Source Folder中,  
	        但包名必须一致,这样才能保证编译之后的字节码文件在一个文件夹中  
	对测试类名的规定
		如果被测试类类名为Calculator,则测试类类名为CalculatorTest
		测试类必须保持完全独立性,不允许出现任何的依赖关系
	对测试方法的规定
		public
		void
		不能有返回值
		被测试方法名为addition,则测试方法名为testAddition
		测试方法必须是独立的,不允许有任何的依赖关系
每执行一个测试方法就会生成一个测试类实例
	比如一个测试类中有一个成员变量 int count=0
	在setUp()方法中打印++count
	如果有三个测试方法,执行后会打印三个1
JUnit测试类中每个测试方法都是一个测试用例(test case)
JUnit4注解说明
	@Before和@After
		@Before和@After修饰的方法相当于JUnit3中的setUp()和tearDown()
		被@Before修饰的方法为初始化方法,每测试一个方法先执行这个方法
		被@After修饰的方法为释放方法,每测试一个方法最后都要执行这个方法
	@Test
		被@Test修饰的方法为测试用例
		被@Test(timeout = 200)修饰的方法,还要测试是否在200毫秒之内执行完毕
		被@Test(expected = Exception.class)修饰的方法,还要测试是否抛出的异常是Exception 
	@BeforeClass和@AfterClass
		全局注解
		@BeforeClass和@AfterClass修饰的方法必须是静态的
		@BeforeClass全局初始化只执行一次,最先执行
 		@AfterClass全局销毁只执行一次,最后执行
 	@Ignore
 		可以用于测试类或者测试方法上表示忽略,不进行测试

为项目配置JUnit环境

第一步:增加JUnit类库,点击项目右键->Build Path->Add Library->选择JUnit 
第二步:为src增加一个测试包,点击项目右键->new->Source Folder 名称为test

MyEclipse IDE自动创建测试类

第一步:创建一个和src同级名称为test的Source Folder
第二步:选择src下需要测试的类右键->new->Junit Test Case

JUnit案例

/* 被测试类 */
package com.itlwc;

public class Calculator {
	public int addition(int a, int b) {
		return a + b;
	}
}

JUnit3测试类CalculatorTest

package com.itlwc;

import junit.framework.TestCase;

public class CalculatorTest extends TestCase {
	private Calculator c = null;

	// 初始化方法(每测试一个方法先执行setUp方法)
	@Override
	public void setUp() throws Exception {
		c = new Calculator();
	}

	public void testAddition() {
		// 真实的值
		int actual = c.addition(5, 3);
		// 期望的值
		int expected = 8;
		assertEquals(expected, actual);
	}

	// 释放方法(每测试一个方法最后都要执行tearDown方法)
	@Override
	public void tearDown() throws Exception {
		c = null;
	}
}

JUnit4测试类CalculatorTest

package com.itlwc;  

import static org.junit.Assert.*;  
import org.junit.After;  
import org.junit.Before;  
import org.junit.Test;  
  
public class CalculatorTest {  
    private Calculator c = null;  
  
    // 初始化方法(每测试一个方法先执行setUp方法) 
    @Before  
    public void setUp() throws Exception {  
        c = new Calculator();  
    }  
  
    @Test  
    public void testAddition() {  
        // 真实的值  
        int actual = c.addition(5, 3);  
        // 期望的值  
        int expected = 8;  
        assertEquals(expected, actual);  
    }
    
    // 释放方法(每测试一个方法最后都要执行tearDown方法)  
    @After  
    public void tearDown() {  
        c = null;  
    }  
}

测试私有方法使用反射

package com.itlwc;

import static org.junit.Assert.*;

import java.lang.reflect.Method;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CalculatorTest {
	private Calculator c = null;

	@Before
	public void setUp() throws Exception {
		c = new Calculator();
	}

	@Test
	public void testSubtraction() {
		Class clazz = c.getClass();
		try {
			Method method = clazz.getDeclaredMethod("addition", new Class[] {
					Integer.TYPE, Integer.TYPE });
			// 压制编译器的访问限制
			method.setAccessible(true);
			// 真实的值
			Object actual = method.invoke(c, new Object[] { 1, 2 });
			// 期望的值
			int expected = 4;
			assertEquals(expected, actual);
		} catch (Exception e) {
			fail();
		}
	}

	@After
	public void tearDown() {
		c = null;
	}
}

JUnit3组合测试使用测试套件TestSuite

package test;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import com.itlwc.CalculatorTest;

public class TestAll extends TestCase {
	// 此方法是固定写法
	public static Test suite() {
		TestSuite suite = new TestSuite();
		suite.addTestSuite(CalculatorTest.class);
		return suite;
	}
}

JUnit3测试CalculatorTest中的testAddition方法20次RepeatedTest

package test;

import junit.extensions.RepeatedTest;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import com.itlwc.CalculatorTest;

public class TestAll extends TestCase {
	// 此方法是固定写法
	public static Test suite() {
		TestSuite suite = new TestSuite();
		/*
		 	执行20次CalculatorTest类中的testAddition()
		 	需要给CalculatorTest增加一个构造器
		 	public CalculatorTest(String name) {
				super(name);
			}
		 */
		CalculatorTest c = new CalculatorTest("testAddition");
		Test t = new RepeatedTest(c, 20);
		suite.addTest(t);
		return suite;
	}
}

JUnit4组合测试使用注解

package test;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

import com.itlwc.CalculatorTest;

/*
 如果想要同时运行多个测试,需要使用
 @RunWith(Suite.class)和@Suite.SuiteClasses()
 */
@RunWith(Suite.class)
@Suite.SuiteClasses( { CalculatorTest.class, CalculatorTest.class })
public class TestAll {

}

JUnit4参数化测试Parameters

package com.itlwc;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/*
 当一个测试类使用参数化运行器时,需要在类的声明处加上@RunWith(Parameterized.class)
 表示该类不使用JUnit内建的运行器运行,而使用参数化运行器运行
 在参数化运行类中提供参数的方式需要使用@Parameters注解来修饰
 同时在测试类的构造方法中为参数赋值(构造器是由JUnit调用的)
 最后编写测试类,它会根据参数的组数来运行多少次
 */
@RunWith(Parameterized.class)
public class CalculatorTest {
	private int expected;
	private int input1;
	private int input2;
	private Calculator c = null;

	// 准备数据
	@Parameters
	public static Collection prepareData() {
		Object[][] object = { { 2, 1, 1 }, { 4, 2, 2 }, { 8, 4, 4 } };
		return Arrays.asList(object);
	}

	// 关联属性与准备数据的关系
	public CalculatorTest(int index1, int index2, int index3) {
		this.expected = index1;
		this.input1 = index2;
		this.input2 = index3;
	}

	@Before
	public void setUp() throws Exception {
		c = new Calculator();
	}

	@Test
	public void testAddition() {
		// 期望的值
		int actual = c.addition(input1, input2);
		assertEquals(expected, actual);
	}

	@After
	public void tearDown() {
		c = null;
	}
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值