单元测试编写

Junit 单元测试框架

对于Java语言而言,其单元测试框架,有Junit和TestNG这两种, 下面是一个典型的JUnit测试类的结构

  1. package com.example.demo;

  2.  

  3. import org.junit.jupiter.api.*;

  4.  

  5. import static org.junit.jupiter.api.Assertions.*;

  6.  

  7. @DisplayName("售票器类型测试")

  8. class DemoTest {

  9. // 定义测试的实例

  10. private Demo demo;

  11.  

  12. // 定义前缀 整个测试类开始执行的地方

  13. @BeforeAll

  14. public static void init(){

  15.  

  16. }

  17.  

  18. // 定义后缀,整个测试类完成后执行的操作

  19. @AfterAll

  20. public static void cleanup(){

  21.  

  22. }

  23.  

  24.  

  25. // 定义每个测试用例开始执行前的操作

  26. @BeforeEach

  27. public void create(){

  28. this.demo = new Demo();

  29. }

  30.  

  31.  

  32. // 定义在每个测试用例完成后执行的操作

  33. @AfterEach

  34. public void destory(){

  35.  

  36. }

  37.  

  38. // 执行测试用例

  39. @Test

  40. @DisplayName("售票后的余额减少")

  41. public void shouldReduceInventoryWhenticketSoldOut(){

  42.  

  43. }

  44.  

  45.  

  46.  

  47. @Test

  48. public void ming(){

  49.  

  50. }

  51. }

测试结果如图所示

Java 之单元测试_JAVA

层次性表达测试用例

测试用例较多的情况下,为了层次性表达测试用例,使用Junit的Nested注解有层次的表达测试用例

  1. package com.example.demo;

  2.  

  3. import org.junit.jupiter.api.*;

  4.  

  5. @DisplayName("交易服务测试")

  6. class DemoTest {

  7. @Nested

  8. @DisplayName("用户交易测试")

  9. class Test02{

  10.  

  11. @Test

  12. @DisplayName("交易检查测试")

  13. public void test01(){

  14.  

  15. }

  16.  

  17. }

  18. }

Java 之单元测试_JAVA_02

使用Tag标签区分测试用例

在执行Maven打包的时候,使用tage注解,可以有选择的执行一些测试命令

  1. package com.example.demo;

  2.  

  3. import org.junit.jupiter.api.*;

  4.  

  5. @DisplayName("交易服务测试")

  6. class DemoTest {

  7.  

  8. @Test

  9. @DisplayName("售票后额度减少")

  10. @Tag("fast")

  11. public void test01(){

  12.  

  13. }

  14.  

  15. @Test

  16. @DisplayName("一次性减少车票")

  17. @Tag("slow")

  18. public void test02(){

  19.  

  20. }

  21. }

添加相关的插件

  1. <plugin>

  2. <artifactId>maven-surefire-plugin</artifactId>

  3. <version>2.22.0</version>

  4. <configuration>

  5. <properties>

  6. <includeTags>fast</includeTags>

  7. <excludeTags>slow</excludeTags>

  8. </properties>

  9. </configuration>

  10. </plugin>

断言

使用Junit命令进行断言处理

  1. @Test

  2. @DisplayName("售票后额度减少")

  3. @Tag("fast")

  4. public void test01(){

  5. String s = "ming";

  6. Assertions.assertTrue(s.startsWith("ming"));

  7. Assertions.assertTrue(s.endsWith("g"));

  8. Assertions.assertEquals(5, s.length());

  9. }

Java 之单元测试_JAVA_03

此时断言错误。

单元测试的目的

提升软件质量

优质的单元测试可以保障,开发质量和程序的健壮性,在大多数互联网企业中,开发工程师,都会频繁的执行测试用例。

促进代码的优化

单元测试是由开发工程师编写和维护的,这会促进开发工程师不断的重新审视自己的代码质量。

提高研发效率

单元测试,虽然占用的大量的时间,但是对后续的联调,集成等,都可以进一步的提高研发的效率。

增加重构的自信

代码重构往往是牵一发而动全身的,当修改底层代码的时候,通过不断的单元测试,可以增加重构的软件的自信。

单元测试的基本原则

单元测试要符合AIR原则。单元测试,符合以下三个原则

  1. 自动化

  2. 独立性

  3. 可重复

单元测试覆盖率

语句覆盖

又称行覆盖(LineCoverage),段覆盖(SegmentCoverage),基本块覆盖(BasicBlockCoverage),这是最常用也是最常见的一种覆盖方式,就是度量被测代码中每个可执行语句是否被执行到了。

判定覆盖

又称分支覆盖(BranchCoverage),所有边界覆盖(All-EdgesCoverage),基本路径覆盖(BasicPathCoverage),判定路径覆盖(Decision-Decision-Path)。它度量程序中每一个判定的分支是否都被测试到了。

条件覆盖

它度量判定中的每个子表达式结果true和false是否被测试到了

路径覆盖

又称断言覆盖(PredicateCoverage)。它度量了是否函数的每一个分支都被执行了

Java 之单元测试_JAVA_04

小明菜市场