Demo002IDEA 中Junit 单元测试的使⽤(初级篇)
推荐JUnit 视频教程:。
1.基本理论
1.1 单元测试
单元测试⼜称模块测试,属于⽩盒测试,是最⼩单位的测试。模块分为程序模块和功能模块。功能模块指实现了⼀个完整功能的模块(单元),⼀个完整的程序单元具备输⼊、加⼯和输出三个环节。⽽且每个程序单元都应该有正规的规格说明,使之对其输⼊、加⼯和输出的关系做出名明确的描述。
JUnit 是⼀个回归测试框架(regression testing framework )。Junit 测试是程序员测试,即所谓⽩盒测试,因为程序员知道被测试的如何(How )完成功能和完成什么样(What )的功能。Junit 是⼀套框架,继承TestCase 类,就可以⽤Junit 进⾏⾃动测试了。
1.2 什么是Junit
①JUnit 是⽤于编写可复⽤测试集的简单框架,是xUnit 的⼀个⼦集。xUnit 是⼀套基于测试驱动开发的测试框架,有PythonUnit 、CppUnit 、JUnit 等。
②Junit 测试是程序员测试,即所谓⽩盒测试,因为程序员知道被测试的软件如何(How )完成功能和完成什么样(What )的功能。
③多数Java 的开发环境都已经集成了JUnit 作为单元测试的⼯具,⽐如IDEA ,Eclipse 等等。
④JUnit 官⽹:
1.3 为什么要使⽤单元测试
①测试框架可以帮助我们对编写的程序进⾏有⽬的地测试,帮助我们最⼤限度地避免代码中的bug ,以保证系统的正确性和稳定性。
②很多⼈对⾃⼰写的代码,测试时就简单写main ,然后sysout 输出控制台观察结果。这样⾮常枯燥繁琐,不规范。缺点:测试⽅法不能⼀起运⾏,测试结果要程序猿⾃⼰观察才可以判断程序逻辑是否正确。
③JUnit 的断⾔机制,可以直接将我们的预期结果和程序运⾏的结果进⾏⼀个⽐对,确保对结果的可预知性。
1.4 测试覆盖评测测试过程中已经执⾏的代码的多少。
1.5 代码覆盖率
代码的覆盖程度,⼀种度量⽅式。针对代码的测试覆盖率有许多种度量⽅式。
语句覆盖( StatementCoverage ):也称为⾏覆盖( lin EC overage ) , 段覆盖(segmentcoverage )和基本块覆盖(bASicblockcoverage )。它度量每⼀个可执⾏语句是否被执⾏到了。
判定覆盖(DecisionCoverage ):也被称为分⽀覆盖(branchcoverage ),所有边界覆盖(alledgescoverage ), 基本路径覆盖( basispathcoverage ),判定路径覆盖(decisiondecisionpath 或DDPtesting )。它度量是否每个 BOOL 型的表达式取值true 和 false 在控制结构中都被测试到了。
条件覆盖(ConDItionCoverage ): 它独⽴的度量每⼀个⼦表达式,报告每⼀个⼦表达式的结果的 true 或 false 。这个度量和判定覆盖(decisioncoverage )相似,但是对控制流更敏感。不过,完全的条件覆盖并不能保证完全的判定覆盖。
路径覆盖(PathCoverage ):也称为断⾔覆盖(prEDIcatecoverage ),它度量了是否函数的每⼀个可能的分⽀都被执⾏了。路径覆盖的⼀个好处是:需要彻底的测试。但有两个缺点:⼀是,路径是以分⽀的指数级别增加的,例如:⼀个函数包含 10个 IF 语句,就有 1024 个路径要测试。如果加⼊⼀个 IF 语句,路径数就达到 2048;⼆是,许多路径不可能与执⾏的数据⽆关。
c语言编译器idea循环覆盖(LOOPCoverage ):这个度量报告你是否执⾏了每个循环体零次、只有⼀次还是多余⼀次(连续地)。对于 dowhile 循环,循环覆盖报告你是否执⾏了每个循环体只有⼀次还是多余⼀次(连续地)。这个度量的有价值的⽅⾯是确定是否对于 while 循环和 for 循环执⾏了多于⼀次,这个信息在其它的覆盖率报告中是没有的。
2. IDEA 中Junit 4的配置
2.1 环境配置
IDEA 中⾃带JUnit 的jar 包(,,):位于安装⽬录下的lib ⽂件内。即:IDEA ⾃带⼀个JUnit 插件, 该插件可以运⾏JUnit 测试⽂件,但⽆法⾃动⽣成JUnit 测试代码. 如果需要⾃动⽣成测试代码,需要安装 插件。安装⽅法:-->-->-->-->输⼊-->选择安装,安装好后重启 IDEA ,即可使⽤。
PS: IDEA ⾃带的JUnit 插件和JUnitGeneratorV2.0插件都要勾选上,若只勾选JUnit 可能导致⽆法⾃动⽣成测试⽂件,若只勾选JUnitGenerator V2.0可能导致⽣成的测试⽂件⽆法运⾏
2.2 修改配置
通过模版⽣成的测试代码与java 类在同⼀个⽬录下,与maven 项⽬标准测试⽬录不匹配。修改⽅法:
修改为有时候会出现⼀个提⽰框,提⽰选择(general/merge/exixt ),选择general 就⾏
原类的路径,就是你⾃⼰写的类
原类的包名,java 包命名规范就是按照包名⼀级⼀级创建的⽂件夹
测试类的类名
hamcrest-core-1.3.jar junit.jar junit-4.12.jar IntelliJ IDEA 2018.1\lib
JUnitGenerator V2.0File settings Plguins Browse repositories JUnit JUnit Generator V2.0${SOURCEPATH}/test/${PACKAGE}/${FILENAME}${SOURCEPATH}/../test/java/${PACKAGE}/${FILENAME}
${SOURCEPATH}${PACKAGE}${filename}
修改 Junit4 选项卡中包的申明,把默认的 test 前缀去掉。⽣成的测试⽂件@since 位置Date 可能存在乱码,可配置JUnit 模板更改⽇期格式,不影响程序可直接忽略。修改⽅法:
第40⾏: 修改为3. 简单⼊门单元测试
在中讲了单元测试,我们根据⽼师的⽅法来进⾏简单⼊门单元测试。
什么是单元测试?单元测试(unit testing ),是指对软件中的最⼩可测试单元进⾏检查和验证。对于单
元测试中单元的含义,⼀般来说,要根据实际情况去判定其具体含义,如Java ⾥单元指⼀个类。
编程是智⼒活动,不是打字,编程前要把⼲什么、如何⼲想清楚才能把程序写对、写好。与⽬前不少同学⼀说编程就打开编辑器写代码不同,我希望同学们养成⼀个习惯,当你们想⽤程序解决问题时,要会写三种码:
伪代码
产品代码
测试代码
伪代码与具体编程语⾔⽆关,不要写与具体编程语⾔语法相关的语句(如,这样只能⽤C 语⾔编程了),从意图层⾯来解决问题,最终,是最⾃然的、最好的注释。
需求:我们要在⼀个类中来实现简单计算器的功能。
3.1 伪代码
设计的伪代码:
3.2 产品代码有了,⽤特定语⾔翻译⼀下,就是可⽤的了。
翻译之后的产品代码 :
@since <pre>$Date</pre>@since <pre>$today</pre>
⽤malloc 分配内存伪代码伪代码产品代码Calculator 简单计算器:
加法:返回两个数相加后的结果
减法:返回两个数相减后的结果
乘法:返回两个数相乘后的结果
除法:除数不为0,返回两个数相除后的结果
除数为0,打印异常信息在程序中出错的位置及原因
其他 :未完成的模块例如平⽅、开⽅等等
伪代码产品代码Calculator.java public class Calculator {
public int add(int x, int y) { //加法 return x + y;
}
public int sub(int x, int y) { //减法
return x - y;
}
public int mul(int x, int y) { //乘法
return x * y;
}
public int div(int x, int y) { //除法
return x / y;
}
public int div2(int x, int y) { //除法 做了异常判断
try {
int z = x / y;
} catch (Exception e) {
e.printStackTrace();
}
return x / y;
}
public void loop(int x, int y) { //死循环
for (; ; )
x = y;
}
public void unCompleted(int x, int y) { //未完成的模块:例如平⽅、开⽅等等
//还在开发中
}
// public static void main(String[] args) { // 传统代码测试
// int a = 8;
// int b = 2;
在IDEA 中创建项⽬,在 右键新建java 类,将上述代码写⼊。
3.3 测试代码
写了产品代码,我们还要写测试代码,证明⾃⼰的代码没有问题。
Java 编程时,程序员对类实现的测试叫单元测试。类XXXX 的单元测试,我们⼀般写建⼀个XXXXTest
的类。所以,对于,我们写⼀个的测试模块,代码如下:这⾥我们设计了⼀个,测试⽤例是为某个特殊⽬标⽽编制的⼀组测试输⼊、执⾏条件以及预期结果,以便测试某个程序路径或核实是否满⾜某个特定需求。这⾥我们的测试输⼊,预期结果分别为。
我们在类上单击⿏标右键,在弹出的菜单中选择(我们可以看到对应键盘快捷键为)-> -> ,这时IDEA 会⾃动⽣成⼀个test ⽬录并⽣成CalculatorTest 类,我们先删除⾃动⽣成的代码,输⼊刚才写的代码。
在 IDEA 中我们把产品代码放在⽬录中,把测试代码放在⽬录中,在命令⾏中我们知道要设置SOURCEPATH 环境变量,在IDEA 中我们右键单击⽬录,在弹出的菜单中选择->就可以了:(这时test ⽂件夹图标会变绿)
在IDEA 中运⾏结果如下,测试结果符合预期:
3.4 测试代码2 (使⽤Junit )
在刚才⾃动⽣成的⽬录下,⾥代码如下:
// int b = 2;
// Calculator calculator = new Calculator();
// System.out.println(calculator.add(a, b));
// System.out.println(calculator.sub(a, b));// System.out.println(calculator.mul(a, b));// System.out.println(calculator.div(a, b));
// System.out.println(calculator.div2(a,0));
// }
}
anjie.junit01.Calculator Calculator 类CalculatorTest.java public class CalculatorTest {
public static void main(String[] args) {
Calculator calculator = new Calculator();
if (calculator.add(8, 2) == 10) {
System.out.println("Test passed!");
} else {
System.out.println("Test failed!");
}
if (calculator.sub(8, 2) == 6) {
System.out.println("Test passed!");
} else {
System.out.println("Test failed!");
}
if (calculator.mul(8, 2) == 16) {
System.out.println("Test passed!");
} else {
System.out.println("Test failed!");
}
if (calculator.div(8, 2) == 4) {
System.out.println("Test passed!");
} else {
System.out.println("Test failed!");
}
}
}
测试⽤例(Test Case)8和2的加减乘除四种运算10,6,16,4Calculator Generate Alt+Insert Junit Test Junit 4CalculatorTest.java src test test Mark Directory as Test Sources Root test CalculatorTest.java public class CalculatorTest {
@Before
public void before() throws Exception {
}
@After
public void after() throws Exception {
}
/**
*
* Method: add(int x, int y)
*
*/
@Test
public void testAdd() throws Exception {
}
/**
*
* Method: sub(int x, int y)
*
*/
@Test
public void testSub() throws Exception {
我们修改测试模块,代码如下: public void testSub() throws Exception {
}
/**
* * Method: mul(int x, int y)
*
*/ @Test
public void testMul() throws Exception {
}
/**
*
* Method: div(int x, int y)
*
*/ @Test
public void testDiv() throws Exception {
}
/**
*
* Method: div2(int x, int y)
*
*/
@Test public void testDiv2() throws Exception {
}
/**
* * Method: loop(int x, int y) *
*/
@Test
public void testLoop() throws Exception {
}
/**
*
* Method: unCompleted(int x, int y)
*
*/
@Test
public void testUnCompleted() throws Exception {
}
}
CalculatorTest.java public class CalculatorTest {
Calculator calculator;
@Before
public void setUp() throws Exception {
calculator = new Calculator();
}
@After
public void after() throws Exception {
}
/**
*
* Method: add(int x, int y)
*
*/
@Test
public void testAdd() throws Exception {
Assert.assertEquals(calculator.add(8,2),10);
}
/**
*
* Method: sub(int x, int y)
*
*/
@Test
public void testSub() throws Exception {
Assert.assertEquals(calculator.sub(8,2),6);
}
/**
*
* Method: mul(int x, int y)
*
*/
在IDEA 中运⾏结果如下,测试结果符合预期:
3.5 编辑测试设置我们可以通过 ->或⼯具栏上的标签来调整我们测试运⾏配置:在选项卡,⽤户可以选择需要运⾏的测试。例如,您可以从⼀个类、程序包、测试套件或甚⾄模式中运⾏所有的测试。这⾥的Fork 模式让⽤户在⼀个单独的进程运⾏每个测试。
代码覆盖测试:
默认情况下使⽤⾃⼰的测试引擎
覆盖率模式:Tracing 会增加消耗,但是测试会更准确
3.6 收集覆盖率
过 ->或⼯具栏上的选项运⾏特定模式的测试。
当覆盖模式运⾏⾄少⼀个测试之后,IDE 将会在Project ⼯具窗⼝显⽰每个程序包、类的覆盖率数据,同
时在Coverage ⼯具窗和编辑器中也会显⽰。
如果⽤户添加另⼀个⽅法到,并运⾏覆盖率测,就会发现,没有被测试覆盖到的代码都将⾼亮显⽰为红⾊。覆盖的代码颜⾊则是绿⾊。如果⼀些代码是只覆盖部分,那没将显⽰为黄⾊。
本⽂代码: */
@Test
public void testMul() throws Exception {
Assert.assertEquals(calculator.mul(8,2),16);
}
/**
*
* Method: div(int x, int y)
*
*/
@Test
public void testDiv() throws Exception {
Assert.assertEquals(calculator.div(8,2),4);
}
/**
*
* Method: div2(int x, int y)
*
*/
@Ignore
public void testDiv2() throws Exception {
}
/**
*
* Method: loop(int x, int y)
*
*/
@Ignore
public void testLoop() throws Exception {
}
/**
*
* Method: unCompleted(int x, int y)
*
*/
@Ignore
public void testUnCompleted() throws Exception {
}
}
Run Edit Configuration Configuration Run Run 'MyClassTest' with Coverage junit01junit01
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论