JUnit测试框架,程序员的好助手,不要只把属性值输出而已
ccwgpt 2024-10-13 01:38 25 浏览 0 评论
6.1初识JUnit测试框架
单元级测试在面向对象的开发中变得越来越重要,而一个简明易学、适用广泛、高效稳定的单元级测试框架对成功的实施测试有着至关重要的作用。在java编程环境中,Junit Framework是一个已经被多数java程序员采用和实证的优秀的测试框架。开发人员只需要按照Junit的约定编写测试代码,就可以对自己要测试的代码进行测试。本小节我们采用Junit的一个小例子来学习在Myeclipse下Junit的运用。
我们创建一个Java工程,项目名称为JunitLesson1,添加一个example.Hello类,首先我们给Hello类添加一个abs()方法,作用是返回绝对值,源代码如下:
package example;
public class Hello {
public int reAbs(int a) {
return a > 0 ? a : -a;
}
}
因为MyEclipse现在默认的是Junit3.8,我们准备使用Junit4.4,所以必须在项目里面导入Junit4包。选择project->properties,在左侧树形条里面选择"java build path",单击右边的Libraries选项卡,如下图所示,点击"add External JARs..",找到Junit4.4.jar,将他导入到项目内。
图6-1 引入Junit包
下一步,我们在项目 JunitLesson1根目录下添加一个新目录 testsrc,并把它加入到项目源代码目录中:单击图3-1的Source选项卡,新建一个目录test,单元测试的代码放在此目录下。
我们准备对这个方法进行测试,确保功能正常。选中Hello.java,右键点击,选择New->other 在弹出的对话框中选择java->JUnit->JUnit Test Case 点击Next按钮,弹出如图6-2对话框:
图6-2 建立Test Case
默认选项,点击Next按钮,进入图6-3,选择要进行测试的方法,把Hello类的reAbs方法勾选上,点击Finish按钮,系统自动生成对Hello类的测试类HelloTest,源代码如下:
图6-3 建立Test 方法
package example;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HelloTest {
@Before //Java Anotation 注释性编程,
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testReAbs() {
fail("Not yet implemented");
}
}
修改如下:
package example;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HelloTest {
private Hello hello;
@Before
public void setUp() throws Exception {
hello = new Hello();
}
@After
public void tearDown() throws Exception {
}
@Test
public void testReAbs() {
int a1 = hello.reAbs(20);
assertEquals(20, a1);// ――――――#1
}
}
然后运行HelloTest类查看运行结果,如下图所示:
图6-4 Errors=0,Failures=0,绿色条代表测试通过。
将1处代码修改如下:
assertEquals(-20, a1);
再次运行HelloTest类查看运行结果,如下图所示:
图6-5 Errors=0,Failures=1,红条代表有测试方法没有通过。
在HelloTest类中,@Before注释的方法是建立测试环境,这里创建一个Hello类的实例;@After注释的方法用于清理资源,如释放打开的文件等等。以@Test注释的方法被认为是测试方法,JUnit会依次执行这些方法。在testReAbs()方法中,我们对reAbs()的测试分别2次测试,assertEquals方法比较运行结果和预期结果是否相同。如果有多个测试方法,JUnit会创建多个测试实例,每次运行一个测试方法,@Before和@After注释的方法会在测试实例前后被调用,因此,不要在一个testA()中依赖testB()。
现在我们在Hello类中增加一个方法,代码如下:
public double add(double number1, double number2) {
return number1 + number2;
}
然后在HelloTest类中增加一个测试方法Test Add,代码如下:
@Test
public void testAdd(){
double result=hello.add(10, 30);
assertEquals(40, result,0);
}
运行HelloTest类查看运行结果。AssertEquals方法中的第三个参数表示的是允许误差范围。
6.2 Junit框架分析
自动化测试框架就是可以自动对代码进行单元测试的框架。在传统的软件开发流程中,需求,设计,编码和测试都有各自独立的阶段,阶段之间不可以回溯,所以测试是不是自动化并不重要。新的软件开发流程中,引入了迭代开发的概念,并且项目迭代周期短,对代码要进行频繁的重构,这就要求单元级测试必须能够自动、简便、高速的运行,否则重构就是不现实的。
自动化测试框架应该支持简单操作,向测试包中添加新的测试用例,而且不影响测试包的正常运行。Junit的自动化测试框架图如下:
图3-6 Junit自动化测试框架
这是一个典型的Composite设计模式:TestSuite可以容纳任何派生自Test的对象;当调用TestsSuite对象的run()方法时,它会遍历自己容纳的对象,逐个调用它们的run()方法。使用者无须关心自己拿到的究竟是TestCase还是TestSute,只管调用对象的run()方法,然后分析run()方法返回的结果就行了
TestCase (测试用例)——扩展了JUnit的TestCase类的类。它以testXXX方法的形式包含一个或多个测试。一个test case把具有公共行为的测试归入一组。在本书的后续部分,当我们提到测试的时候,我们指的是一个testXXX方法;当我们提及test case的时候,我们指的是一个继承自TestCase的类,也就是一组测试。
TestSuite(测试集合)——一组测试。一个test suite是把多个相关测试归入一组的便捷方式。例如,如果你没有为TestCase定义一个test suite,那么JUnit就会自动提供一个test suite,包含TestCase中所有的测试(本书稍后会细说)。
TestRunner(测试运行器)——执行test suite的程序。JUnit提供了几个test runner,你可以用它们来执行你的测试。没有TestRunner接口,只有一个所有test runner都继承的BaseTestRunner。因此,当我们编写TestRunner的时候,我们实际上指的是任何继承 BaseTestRunner的test runner类。
图3-7 JUnit成员三重唱,共同产生测试结果
这3 个类是JUnit框架的骨干。一旦你理解了TestCase、TestSuite和BaseTestRunner的工作方式,你就可以随心所欲地编写测试 了。在正常情况下,你只需要编写test case,其他类会在幕后帮你完成测试。这3个类和另外4个类紧密配合,形成了JUnit框架的核心。图3-8归纳了这7个核心类各自的责任。
图3-8 Junit核心类及接口
6.3 用TestCase来工作
概括地说,JUnit的工作过程就是由TestRunner来运行包含一个或多个TestCase(或者其他TestSuite)的TestSuite。但在常规工作中,你通常只和TestCase打交道。有些测试会用到一些资源,要把这些资源配置好是件麻烦事。比如像数据库连接这样的资源就是典型的例子。可能TestCase中的几个测试需要连接到一个测试数据库并访问一些测试表。另一组测试则可能需要复杂的数据结构或者很长的随机输入序列。
把通用的资源配置代码放在测试中并不是好主意。你并不想测试自己建立资源的能力,你只需要一个稳健的外部环境,在这个环境中运行测试。运行测试所需要的这个外部资源环境通常称作test fixture。
定义 fixture——运行一个或多个测试所需的公用资源或数据集合。
TestCase 通过setUp和tearDown方法来自动创建和销毁fixture。TestCase会在运行每个测试之前调用setUp,并且在每个测试完成之后调 用tearDown。把不止一个测试方法放进同一个TestCase的一个重要理由就是可以共享fixture代码。图3-9描述了TestCase的生 命周期。
需 要fixture的一个典型例子就是数据库连接。如果一个TestCase包括好几项数据库测试,那么它们都需要一个新建立的数据库连接。通过 fixture就可以很容易地为每个测试开启一个新连接,而不必重复编写代码。你还可以用fixture来生成输入文 件,这意味着你不必在测试中携带测试文件,而且在测试开始执行之前状态总是已知的。
JUnit还通过Assert接口提供的工具方法来复用代码。我们将在下一节中加以介绍。
图3-9 TestCase生命周期,为每个测试方法重新创建fixture
在测试一个单元方法时,有时您会需要给它一些对象作为运行时的资料,例如您撰写下面这个测试案例:
MaxMinTest.java
package onlyfun.caterpillar.test; import onlyfun.caterpillar.MaxMinTool; import junit.framework.TestCase; public class MaxMinTest extends TestCase { public void testMax() { int[] arr = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; assertEquals(5, MaxMinTool.getMax(arr)); } public void testMin() { int[] arr = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; assertEquals(-5, MaxMinTool.getMin(arr)); } }
您将设计的MaxMinTool包括静态方法getMax()与getMin(),当您给它一个整数阵列,它们将个别传回阵列中的最大值与最小值,显然的,您所准备的阵列重复出现在两个单元测试之中,重复的程式码在设计中可以减少就尽量减少,在这两个单元测试中,整数阵列的准备是单元方法所需要的资源,我们称之为fixture,也就是一个测试时所需要的资源集合。
fixture必须与上下文(Context)无关,也就是与程式执行前后无关,这样才符合单元测试的意涵,为此,通常将所需的fixture撰写在单元方法之中,如此在单元测试开始时创建fixture,并于结束后销毁fixture。
然而对于重复出现在各个单元测试中的fixture,您可以集中加以管理,您可以在继承TestCase之后,重新定义setUp()与tearDown()方法,将数个单元测试所需要的fixture在setUp()中创建,并在tearDown()中销毁,例如:
MaxMinTest.java
package onlyfun.caterpillar.test; import onlyfun.caterpillar.MaxMinTool; import junit.framework.TestCase; public class MaxMinTest extends TestCase { private int[] arr; protected void setUp() throws Exception { super.setUp(); arr = new int[]{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; } protected void tearDown() throws Exception { super.tearDown(); arr = null; } public void testMax() { assertEquals(5, MaxMinTool.getMax(arr)); } public void testMin() { assertEquals(-5, MaxMinTool.getMin(arr)); } }
setUp()方法会在每一个单元测试testXXX()方法开始前被呼叫,因而整数阵列会被建立,而tearDown()会在每一个单元测试 testXXX()方法结束后被呼叫,因而整数阵列参考名称将会参考至null,如此一来,您可以将fixture的管理集中在 setUp()与tearDown()方法之后。最后按照测试案例的内容,您完成MaxMinTool类别:
MaxMinTool.java
package onlyfun.caterpillar; public class MaxMinTool { public static int getMax(int[] arr) { int max = Integer.MIN_VALUE; for(int i = 0; i < arr.length; i++) { if(arr[i] > max) max = arr[i]; } return max; } public static int getMin(int[] arr) { int min = Integer.MAX_VALUE; for(int i = 0; i < arr.length; i++) { if(arr[i] < min) min = arr[i]; } return min; } }
Swing介面的TestRunner在测试失败时会显示红色的棒子,而在测试成功后会显示绿色的棒子,而 "Keep the bar green to keep the code clean." 正是JUnit的名言,也是测试的最终目的。
相关推荐
- RACI矩阵:项目管理中的角色与责任分配利器
-
作者:赵小燕RACI矩阵RACI矩阵是项目管理中的一种重要工具,旨在明确团队在各个任务中的角色和职责。通过将每个角色划分为负责人、最终责任人、咨询人和知情人四种类型,RACI矩阵确保每个人都清楚自己...
- 在弱矩阵组织中,如何做好项目管理工作?「慕哲制图」
-
慕哲出品必属精品系列在弱矩阵组织中,如何做好项目管理工作?【慕哲制图】-------------------------------慕哲制图系列0:一图掌握项目、项目集、项目组合、P2、商业分析和NP...
- Scrum模式:每日站会(Daily Scrum)
-
定义每日站会(DailyScrum)是一个Scrum团队在进行Sprint期间的日常会议。这个会议的主要目的是为了应对Sprint计划中的不断变化,确保团队能够有效应对挑战并达成Sprint目标。为...
- 大家都在谈论的敏捷开发&Scrum,到底是什么?
-
敏捷开发作为一种开发模式,近年来深受研发团队欢迎,与瀑布式开发相比,敏捷开发更轻量,灵活性更高,在当下多变环境下,越来越多团队选择敏捷开发。什么是敏捷?敏捷是一种在不确定和变化的环境中,通过创造和响应...
- 敏捷与Scrum是什么?(scrum敏捷开发是什么)
-
敏捷是一种思维模式和哲学,它描述了敏捷宣言中的一系列原则。另一方面,Scrum是一个框架,规定了实现这种思维方式的角色,事件,工件和规则/指南。换句话说,敏捷是思维方式,Scrum是规定实施敏捷哲学的...
- 敏捷项目管理与敏捷:Scrum流程图一览
-
敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示,以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例:这个流程图涵盖了Scrum框架的主要阶段和活动,其中包...
- Mockito 的最佳实践(mock方法)
-
记得以前面试的时候,面试官问我,平常开发过程中自己会不会测试?我回答当然会呀,自己写的代码怎么不测呢。现在想想我好像误会他的意思了,他应该是想问我关于单元测试,集成测试以及背后相关的知识,然而当时说到...
- EffectiveJava-5-枚举和注解(java枚举的作用与好处)
-
用enum代替int常量1.int枚举:引入枚举前,一般是声明一组具名的int常量,每个常量代表一个类型成员,这种方法叫做int枚举模式。int枚举模式是类型不安全的,例如下面两组常量:性别和动物种...
- Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
-
Maven简介Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。Maven是一个跨平台的项目管理工具。主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。仔...
- Java单元测试框架PowerMock学习(java单元测试是什么意思)
-
前言高德的技术大佬在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。”这句话让我感触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现...
- Spring框架基础知识-第六节内容(Spring高级话题)
-
Spring高级话题SpringAware基本概念Spring的依赖注入的最大亮点是你所有的Bean对Spring容器的存在是没有意识的。但是在实际的项目中,你的Bean必须要意识到Spring容器...
- Java单元测试浅析(JUnit+Mockito)
-
作者:京东物流秦彪1.什么是单元测试(1)单元测试环节:测试过程按照阶段划分分为:单元测试、集成测试、系统测试、验收测试等。相关含义如下:1)单元测试:针对计算机程序模块进行输出正确性检验工作...
- 揭秘Java代码背后的质检双侠:JUnit与Mockito!
-
你有没有发现,现在我们用的手机App、逛的网站,甚至各种智能设备,功能越来越复杂,但用起来却越来越顺畅,很少遇到那种崩溃、卡顿的闹心事儿?这背后可不是程序员一拍脑袋写完代码就完事儿了!他们需要一套严谨...
- 单元测试框架哪家强?Junit来帮忙!
-
大家好,在前面的文章中,给大家介绍了以注解和XML的方式分别实现IOC和依赖注入。并且我们定义了一个测试类,通过测试类来获取到了容器中的Bean,具体的测试类定义如下:@Testpublicvoid...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- ui自动化框架 (47)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)