32、单元测试运行与测试替身对比及后续学习建议

单元测试运行与测试替身对比及后续学习建议

1. 使用不同工具运行单元测试

1.1 使用 IntelliJ IDEA 运行测试

IntelliJ IDEA 自带 TestNG - J 插件,可识别 TestNG 测试。运行测试的方式有两种:
- 鼠标操作
- 运行单个测试类:右键点击选定的测试类(如 MoneyTest ),选择“Run ‘MoneyTest’”。
- 运行多个测试:在项目树视图中,右键点击 src/test/java 目录(或包含测试的任何包),选择相应的“Run …”选项。
- 运行单个测试方法:右键点击该方法,选择“Run ‘MoneyTest’”。
- 键盘操作
- 运行所选类的所有测试:确保测试类在编辑器中处于焦点状态,将光标置于任何测试方法之外,按下 CTRL + SHIFT + F10
- 运行特定测试方法:将光标置于该方法上,使用相同组合键 CTRL + SHIFT + F10
- 重新运行相同测试:按下 SHIFT + F10

1.1.1 使用 IntelliJ IDEA 调试测试

调试测试也有多种方式:
- 右键点击测试类、测试包或测试方法,选择“Debug …”选项。
- 使用 ALT + SHIFT + F9 键。
- 重新运行相同调试会话:按下 SHIFT + F10

1.2 使用 Gradle 运行测试

Gradle 是强大且复杂的构建工具。要使用 Gradle 运行 TestNG 测试,需告知它查找 TestNG 测试,并为 testCompile 范围提供 TestNG 依赖。以下是一个基本的 build.gradle 文件示例:

apply plugin: 'java' 
repositories {
    mavenCentral() 
}
dependencies {
    testCompile 'org.testng:testng:6.4' 
}
test {
    useTestNG() 
}

上述代码解释如下:
- apply plugin: 'java' :告诉 Gradle 准备编译 Java 类。
- repositories { mavenCentral() } :定义用于下载依赖项的仓库(这里是 Maven 中央仓库,包含 TestNG JAR 文件)。
- dependencies { testCompile 'org.testng:testng:6.4' } :定义用于测试编译(和执行)的库(这里是 testng - 6.4.jar )。
- test { useTestNG() } :指示 Gradle 查找 TestNG 测试类以运行测试。

运行测试的步骤如下:
1. 将上述 build.gradle 文件放在应用程序的根目录。
2. 在命令行执行 gradle test 。示例输出如下:

>gradle test
:first_test:compileJava
:first_test:processResources
:first_test:classes
:first_test:compileTestJava
:first_test:processTestResources
:first_test:testClasses
:first_test:test
BUILD SUCCESSFUL

若要获取更多信息,可使用 -i 开关,或编写自己的监听器。若测试失败,Gradle 会打印错误消息。若要运行单个测试,使用 gradle -Dtest.single=MoneyTest test 语法。

1.2.1 使用 TestNG 监听器和报告器与 Gradle

可在构建脚本的测试配置部分传递监听器和报告器类的全限定名,让 TestNG 使用它们。示例如下:

test {
    useTestNG()
    options {
        listeners << 'com.practicalunittesting.DotTestListener', 
        listeners << 'fully.qualified.path.to.ExcelReporter'  
    }
}
1.2.2 向 Gradle 的测试类路径添加 JAR

若测试需要额外库,需将其添加到 testCompile 范围。示例如下:

dependencies {
    testCompile 'org.testng:testng:6.4'
    testCompile 'org.hamcrest:hamcrest-all:1.1'
    testCompile 'com.practicalunittesting.listeners:1.0'
}

1.3 使用 Maven 运行测试

使用 Maven 运行测试,需了解 Maven Surefire 插件、Maven Surefire 报告插件和 Maven 站点插件的文档。以下是一个基本的 Maven 构建脚本示例:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
        http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.practicalunittesting</groupId>
  <artifactId>first-test</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>6.4</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

运行测试的步骤如下:
1. 确保理解 Maven 的基本概念(如生命周期)。
2. 在命令行执行 mvn test 。示例输出如下:

 [INFO] -------------------------------------------------------------------
 [INFO] Building first-test 1.0-SNAPSHOT
 [INFO] -------------------------------------------------------------------
 [INFO]
 -------------------------------------------------------
 T E S T S
 -------------------------------------------------------
 Running TestSuite
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.295 sec
 Results :
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
 [INFO] -------------------------------------------------------------------
 [INFO] BUILD SUCCESS
 [INFO] -------------------------------------------------------------------

若测试失败,Maven 会在控制台打印错误消息。测试结果以文本和 XML 格式保存在 target/surefire - reports 目录。若需要更易读的报告,可使用 Maven Surefire 报告插件或 Maven 站点插件生成 HTML 报告。

1.3.1 使用 TestNG 监听器和报告器与 Maven

可编写自己的监听器和报告器,并让 Maven 使用它们。以下是 Maven Surefire 插件配置示例:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.12</version>
    <configuration>
        <properties>
            <property>
                <name>listener</name>
                <value>com.practicalunittesting.DotTestListener</value>
            </property>
            <property>
              <name>reporter</name>
              <value>com.practicalunittesting.ExcelReporter</value>
            </property>
        </properties>
    </configuration>
</plugin>
1.3.2 向 Maven 的测试类路径添加 JAR

若要向测试类路径添加其他库,需像指定 TestNG 依赖一样指定它们。示例如下:

<dependencies>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.4</version>
        <scope>test</scope> 
    </dependency>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-all</artifactId>
        <version>1.1</version>
        <scope>test</scope> 
    </dependency>
    <dependency>
        <groupId>com.practicalunittesting</groupId>
        <artifactId>listeners</artifactId>
        <version>1.0</version>
        <scope>test</scope> 
    </dependency>
</dependencies>

确保使用 test 范围,以便 Maven 将它们添加到测试类路径。

运行测试工具对比表格

工具 配置方式 运行命令 报告处理 监听器和报告器配置
IntelliJ IDEA 自带 TestNG - J 插件 鼠标操作或键盘操作 IDE 内查看 暂未提及
Gradle 编写 build.gradle 文件 gradle test 命令行查看,可使用 -i 开关获取更多信息 build.gradle 文件的 test 部分配置
Maven 编写 pom.xml 文件 mvn test 结果保存在 target/surefire - reports 目录,可生成 HTML 报告 pom.xml maven - surefire - plugin 配置

运行测试流程图

graph LR
    A[选择运行工具] --> B{IntelliJ IDEA}
    A --> C{Gradle}
    A --> D{Maven}
    B --> B1[鼠标操作或键盘操作运行测试]
    B --> B2[调试测试]
    C --> C1[配置 build.gradle 文件]
    C1 --> C2[执行 gradle test 命令]
    C2 --> C3[查看测试结果]
    D --> D1[配置 pom.xml 文件]
    D1 --> D2[执行 mvn test 命令]
    D2 --> D3[查看测试结果]

2. 测试替身:测试间谍与模拟对象的对比

2.1 不同的流程和断言者

测试间谍和模拟对象都用于验证被测系统(SUT)与依赖对象(DOCs)之间调用的正确性,但它们在测试流程和断言方式上有所不同。

2.1.1 测试间谍示例
// arrange
SomeClass sut = ...; 
ClientDAO testSpyClientDAO = mock(ClientDAO.class);
sut.setClientDAO(testSpyClientDAO);
// act
sut.deleteClient(req, resp);
// assert
verify(testSpyClientDAO).deleteClient("1234"); 

测试间谍的测试流程清晰,分为三个阶段:
1. 安排(Arrange) :创建 SUT 和测试间谍对象,并将测试间谍对象注入到 SUT 中。
2. 行动(Act) :调用 SUT 的方法。
3. 断言(Assert) :显式地验证测试间谍对象的方法调用。

2.1.2 模拟对象示例
// arrange
SomeClass sut = ...; 
ClientDAO mockClientDAO = createMock(ClientDAO.class); 
sut.setClientDAO(mockClientDAO);
// assert - part I
expect(mockClientDAO.deleteClient("1234")); 
replay(mockClientDAO); 
// act
sut.deleteClient(req, resp);
// assert - part II
verify(mockClientDAO); 

模拟对象的断言阶段分为两个部分:
1. 设置期望(Assert - part I) :在行动之前设置模拟对象的期望行为。
2. 验证期望(Assert - part II) :在行动之后验证模拟对象的期望是否得到满足。

2.2 错误处理方式

  • 模拟对象 :在方法执行过程中,如果任何方法调用不符合期望,测试会立即失败。
  • 测试间谍 :在所有方法执行完毕后的验证阶段,如果发现方法调用不符合期望,测试才会失败。

测试间谍在断言消息中可能提供更详细的信息,因为它在所有方法执行完毕后进行验证。而模拟对象在运行时失败,可能会丢失一些信息。

2.3 存根功能

大多数人认为测试间谍也具有存根功能,例如 Mockito 框架为其测试间谍提供了存根功能。

2.4 宽容性

测试间谍通常比模拟对象更“宽容”,它允许指定要验证的交互,而忽略其他交互。例如,Mockito 测试间谍框架支持这种方式,避免过度指定测试。

然而,模拟框架通常更严格,但有些框架(如 EasyMock)支持两种测试风格。默认情况下,EasyMock 的模拟对象是“严格”的,但也允许使用“友好”的模拟对象,只验证选定的交互,类似于 Mockito 的测试间谍。

测试间谍与模拟对象对比表格

对比项 测试间谍 模拟对象
测试流程 遵循“安排 - 行动 - 断言”模式 断言阶段分为设置期望和验证期望两个部分
错误处理 所有方法执行完毕后验证,可能提供更详细信息 方法执行过程中不符合期望立即失败,可能丢失信息
存根功能 大多数支持 支持
宽容性 更宽容,可指定验证交互 通常更严格,但部分框架支持两种风格

测试间谍与模拟对象对比流程图

graph LR
    A[测试类型] --> B{测试间谍}
    A --> C{模拟对象}
    B --> B1[安排 SUT 和测试间谍]
    B1 --> B2[行动:调用 SUT 方法]
    B2 --> B3[断言:验证测试间谍方法调用]
    C --> C1[安排 SUT 和模拟对象]
    C1 --> C2[设置模拟对象期望]
    C2 --> C3[行动:调用 SUT 方法]
    C3 --> C4[验证模拟对象期望]

3. 后续学习建议

3.1 深入学习测试工具

  • 详细阅读 TestNG 和 Mockito 的文档,查找本书未涵盖的内容。
  • 关注新版本的发布公告,了解新功能。

3.2 掌握开发工具

  • 熟练掌握 IDE、构建工具和命令行,用于编写和执行测试。

3.3 学习其他测试工具

  • 学习新语言时,了解为该语言设计的测试工具。

3.4 开始实践 TDD

  • 若尚未开始,尝试进行测试驱动开发(TDD)。
  • 与更有经验的同行进行结对编程。
  • 尝试使用 IDE 插件,使编写测试更有趣。

3.5 迈向 BDD

  • 掌握 TDD 后,学习行为驱动开发(BDD)。

3.6 学习应用测试

  • 阅读相关书籍,深入了解可测试软件的开发。
  • 开始编写集成测试和端到端测试。

3.7 处理遗留代码

  • 若经常处理遗留代码,学习相关知识和技巧。

3.8 自动化测试和持续集成

  • 建立自动化测试流程,使用构建工具和持续集成服务器。
  • 若团队已使用,追求持续交付。

3.9 分享知识和经验

  • 参加社区活动,如代码撤退会议和代码练习。
  • 在 GitHub 等平台分享代码。
  • 在 RefactorMyCode.com 或 StackOverflow 等网站寻求指导和反馈。
  • 参与开源项目,与他人合作开发。

后续学习建议列表

  1. 深入学习测试工具
  2. 掌握开发工具
  3. 学习其他测试工具
  4. 开始实践 TDD
  5. 迈向 BDD
  6. 学习应用测试
  7. 处理遗留代码
  8. 自动化测试和持续集成
  9. 分享知识和经验

后续学习建议流程图

graph LR
    A[学习起点] --> B[深入学习测试工具]
    A --> C[掌握开发工具]
    A --> D[学习其他测试工具]
    B --> E[实践 TDD]
    E --> F[迈向 BDD]
    C --> G[学习应用测试]
    D --> H[处理遗留代码]
    G --> I[自动化测试和持续集成]
    I --> J[分享知识和经验]

通过以上内容,我们了解了使用不同工具运行单元测试的方法,对比了测试间谍和模拟对象的差异,并给出了后续学习的建议。希望这些信息能帮助你在单元测试的道路上不断前进。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值