Junit介绍
■Juint由Erich Gamma和Kent Beck编写的一个测试框架
■开源软件
■支持语音有Smalltalk,Java,C++,Perl等
■支持的IDE:JBuilder,VisualAge,Eclipse等
■Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能
常用的测试基本概念
■白盒测试:程序内部的逻辑结构和其他信息对测试人员是公开的
■回归测试:软件或环境的修复或更正后的“再测试”,自动测试工具对这类测试尤其有用
■单元测试:是最小颗粒度的测试,以测试某个功能或代码块。一般由程序员来做,因为它需要知道内部设计和编码的细节
■JUnit:是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于Java语言)。主要用于白盒测试,回归测试
单元测试工具
目前最流行的单元测试工具是xUnit系列框架,常用的根据语言不同分为
■Junit(java)
■Cppunit(C)
■DUnit(Delphi)
■Nunit(.net)
■PhpUnit(Php)
■Pyunit(Python)等
在Eclipse中配置好Junit
1.在该项目上点右键,点“属性”
2.选择“Java Build Path”,选择“Libraries”标签,点击“Add Library”按钮,弹出Add Libray窗体,选中“Junit”,单击“Next”
生成Junit的测试用例框架
■在Eclipse的Package Explorer中右击Calculate.java,选择new-->“Junit Test Case”
■setUpBeforeClass():调用这个测试类的时候,会先执行setUpBeforeClass的内容。只会被执行一次(因为测试类只会被调用一次,所以它只会执行一次),主要用于初始化
■tearDownAfterClass():测试类所有方法都被执行之后,它会执行该方法,只会被执行一次。初始化工作做一些执行后处理,例如关闭和数据库的连接
■setUp():每个测试用例执行的时候,都会执行setUp()
■tearDown():每次测试用例执行后,都会执行tearDown()
■Class under test:选择被测试类,可以直接输入类名/Browse
单元测试基本思想:通过断言来判断,期望值与实际值比对,一致的话,断言成功。如果不一致则失败。
■测试类是一个独立的类,没有任何父类。测试类的名字也可以任意命名,没有任何局限性。但是建议都用类名+Test来命名
■我们不能通过类的声明来判断它是不是一个测试类,它与普通类的去呗在于它内部的方法和声明
创建一个待测试类的对象
Private static Calculator calculator= new Calculator();
■需要测试哪个类,首先就要创建该类的对象
■为了测试Calculater类,我们必须创建一个calculator对象
测试方法的声明
■在测试类中,并不是每个方法都是用于测试的,必须使用“标注”来明确表明哪些是测试方法
◆@Before
◆@Test:表明这是一个测试方法
◆ @Ignore:跳过,不执行
■方法名可以随便取,没有任何限制,但是规范写法是test+方法名,方法名首字母大写
■方法的返回值必须为void
■方法不能有任何参数
■如果违反这些规范,运行时会抛出一个异常
测试方法的例子——@test
@Test
public void testAdd(){
calculator.add(2);
calculator.add(3);
assertEquals(5,calculator.getResult()); //判断期待结果和实际结果是否相等
}
■我们期待的结果应该是5
■第一个参数填写期待结果,第二个参数填写实际结果
■JUnit会自动进行测试并把测试结果反馈给用户
测试方法的例子——@Ignore
@Ignore("Mulctiply() Not yet implented")
public void testMultiply(){
}
■加上@Ignore标注的含义就是“某些方法尚未完成,暂不参与此次测试”
■这样的话测试结果就会提示你又几个测试被忽略,而不是失败
@Before和@After
@Before
public void setUp() throws Exception{
calculator.clear();
{
@After
public void tearDown() throws Exception{
}
■@Before,@After是每个方法测试时候必然被调用的代码
■保证每个测试都是独立的,相互之间没有任何耦合度
■这里不需要@Test标注,因为这不是一个test
测试开始-->setUp-->test*****-->tearDown-->测试结束
@BeforeClass或@AfterClass
■只在测试用例初始化执行@BeforeCalss方法,当所有测试执行完毕后,执行@AfterClass进行收尾工作
■用于测试读取文件等耗时的方法
■该方法必须是public和static的
■注意:@BeforeClass和@AfterClass只执行一次
■@Before,@After是每个测试用例执行的时候都会执行
限时测试
@Test(timeout=2000)//设置超时时间为2000ms
public void testDivide(){
for( ; ;);//死循环
}
■对于逻辑很复杂,循环嵌套比较深的程序采用限时测试
■函数设定一个执行时间,超过了这个时间,他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时
测试异常
@Test(expected = ArithmeticException.class)
public void divideByZero(){
calculator.divide(0);
}
■expected属性用来测试函数应该抛出的异常
Runner(运行器)
■JUnit中有一个默认的Runner,如果你没有指定,那么系统自动使用默认Runner来运行你的代码
■@RunWith是用来修饰类,可以指定需要的Runner
参数化测试
可以将所有参数集中起来一次测试。步骤如下:
1.为这种测试专门生成一个新的类
2.定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果
3.定义测试数据的集合,用@Papameters标注进行修饰
4.创建构造函数对先前定义的两个参数进行初始化
参数化测试
■数据驱动:用多组不同的数据执行相同的脚本——脚本是固定的,但是测试数据是变化的,一组数据或多组数据
■ 关键字驱动:操作元素,操作动作,输入的值,三个都可以自定义
可以将所有参数集中起来一次测试。步骤如下:
1.为这种测试专门生成一个新的类
2.定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果
3.定义测试数据的集合,用@Papameters标注进行修饰
4.创建构造函数对先前定义的两个参数进行初始化
测试集
步骤:
1.用@RunWith标注传递一个参数Suite.class
2.用@Suite.SuiteClasses表明这个类是一个打包测试类
3.把需要打包的类作为参数传递给该标注
对于一些比较大,较长期且相对于需求越稳定的项目,非常适合底层的单元测试的方式来进行,整体的质量会提高,效率也很高
推荐书籍:单元测试的艺术