单元测试实践

简介: 工欲善其事,必先利其器. 单元测试三剑客: - TestNg:单元测试框架 - AssertJ:断言工具 - Jmockit:mock工具

说在前面的话:

就像阿里规约里提到, 单元测试需要满足的AIR原则 :

  • A:Automatic(自动化)
  • I:Independent(独立性)
  • R:Repeatable(可重复)
    image

工欲善其事,必先利其器. 单元测试三剑客:

  • TestNg:单元测试框架
  • AssertJ:断言工具
  • Jmockit:mock工具

TestNg


testNg是个unit test/sut框架, 支持很多功能。但本篇文章重点不是介绍testNg,简单提一下我觉得比较有用的功能

  • Group:测试用例分组,根据业务/逻辑分组,以更小的粒度来执行case.
  • Parallel:并行执行,可以配置多个线程来执行case.需要注意并发问题.

    <suite name="My suite" thread-count="10" parallel="classes">
     <test name="mocking">
         <packages>
             <package name="com.hz.constantine.jmockit.slideshare.mocking"/>
         </packages>
       </test>
     <test name="faking">
         <packages>
             <package name="com.hz.constantine.jmockit.slideshare.faking"/>
         </packages>
     </test>
     <test name="testng">
         <packages>
             <package name="com.hz.constantine.jmockit.slideshare.testng"/>
         </packages>
     </test>
    </suite>
  • Listener:通过监听器集成自定义的功能
  • DataProvider:测试用例和测试数据分离

    static final String expectData = DataProviderTest.class.getSimpleName();
    static final class DataProvider{
       @org.testng.annotations.DataProvider(name = "str")
       public static Object[][] provide(){
           return new Object[][]{{expectData}};
       }
    }
    @Test(dataProvider = "str",dataProviderClass = DataProvider.class)
    public void dataProviderTest(String data){
       Assert.assertEquals(data,expectData);
    }
  • Timeout/ExpectExceptions:支持用例执行超时 和 异常

    @Test(timeOut = 5,expectedExceptions = {ThreadTimeoutException.class,NullPointerException.class})
    public void timeout(){
       try {
           Thread.sleep(10);
       } catch (InterruptedException e) {
       }
    }

    Tips:附上TestNg Tutorial, http://testng.org/doc/documentation-main.html

TestNg 集成Jmockit


image

  • Java instrumentation:开发者可以构建一个独立于应用程序的代理程序,监测和协助运行在JVM上的程序,虚拟机级别的AOP实现
  • TestNg Listener: TestNg Listener特性提供开发者扩展TestNg的能力.

Jmockit


在jmockit的世界里,它提供两套不同的语法和api. 分别是mocking和faking.下面分别针对这两套做详细的说明

-1- mocking

注解

image

特性
  • Expectations.代表一组调用关联到当期的case.
  • Record-Replay-Verify Mode.
  • Record: 预准备依赖和数据.
  • Replay:执行业务.
  • Verify:校验.
  • RecordingResult
  • FlexibleArgumentTest
  • Delegate表达式
  • Caputring: 用在Verification里.
  • CasCadeMock: 级联Mock

其中最重要的是Record-Replay-Verify Mode ,三段式的表述方式。即

  1. Record: 记录,即定义数据、并mock相关的依赖.
  2. Replay:回放,即执行被测试的业务逻辑.
  3. Verify:校验,即校验逻辑是否正确.
    废话不多说,直接上代码:

    @Test(expectedExceptions = MissingInvocation.class)
    public void recordReplyVerifyNotInOrder() {
       //Record
       ClassUnderTest classUnderTestInstance = newClassUnderTestInstance();
       final String data = this.getClass().getSimpleName();
       new Expectations(classUnderTestInstance.getEye(), classUnderTestInstance.getRepository()) {
           {
               classUnderTestInstance.getEye().find();
               result = data;
               classUnderTestInstance.getRepository().insert(data);
               times = 1;
           }
       };
       //Replay
       classUnderTestInstance.action();
       //Verify
       new VerificationsInOrder(){
           {
               classUnderTestInstance.getRepository().insert(data);
               classUnderTestInstance.getEye().find();
           }
       };
    }

其中 ClassUnderTest 是被测试类,依赖了Eye 和 Repository, 在Record阶段被定义了mocking.
其他特性的测试类,可以参看我的github: https://github.com/cscpswang/java-practice

-2- faking

  • Faking
  • unspecifiedFaking
  • Invocation Context
    第2个和第3个特性依然可以参看我的github,重点说明一下特性1:

1.定义一个被测试对象,一个echoServer(在io编程中,echoServer表示接受到任何消息不做处理,直接返回原消息)

       class EchoServer {
               private Dependency dependency=new Dependency();
               public String echo(String msg) {
                   return msg;
               }
               public String run(){
                  return dependency.run();
               }
       }

2.定义一个依赖类,这个类会在单测中被faking.

         class Dependency {
             public String run(){
                 return "dependency run";
             }
         }

3.case,测试EchoServer.

      public void applyFakesWithDependency(){
          final String msg = "i'm constantine";
          EchoServer echoServer = new EchoServer();
          final class DependencyMock extends MockUp<Dependency> {
              @Mock
              public String run(){
                  return msg;
              }
          }
          new DependencyMock();
          String actualMsg =  echoServer.run();
          Assert.assertEquals(actualMsg,msg);
      }

tips:

  1. spring 中使用faking api时泛型指定到具体的impl类.
  2. 被jdk 代理的类(如spring bean被aop),并不是实现类的实例. 所以要么基于接口mocking(需要mock接口的所有方法),要么使用faking.

小结:

Faking和Mocking是两套jmockit的api,在其官方文档,有下面一句话:

In particular, the use of both the Faking API and the Mocking API in the same test class should be viewed with suspicion, as it strongly indicates misuse.

image
我更偏爱使用Mocking api, 因为它的特性很酷。 但它不能mocking私有方法,这点有时会不太方便。

最后,如果你要下jmockit的源码,并希望研究,注意一个坑。由于jmockit基于java agent(instrumentation),你需要在你的classpath下放置一个jmockit-xxx.jar.

相关文章
|
8天前
|
敏捷开发 数据可视化 Devops
敏捷测试价值观、方法和实践读书笔记(4)
本章节探讨了敏捷测试执行的关键概念与实践。首先介绍了用户故事及其重要性,强调其在敏捷开发中的角色,并阐述了用户故事的 INVEST 原则。接着分析了用户故事生命周期中的测试关注点,包括定义、处理、完成及验收阶段的测试活动。此外,还对比了不同测试术语的差异,并提供了敏捷测试计划的策略与过程。通过看板等工具实现任务管理与跟踪,确保测试活动高效进行。最后,介绍了敏捷测试中的度量指标,帮助团队评估测试效果。
17 5
敏捷测试价值观、方法和实践读书笔记(4)
|
8天前
|
监控 架构师 Devops
敏捷测试价值观、方法和实践读书笔记(3)
本章节介绍敏捷测试转型框架,涵盖模型概览、实施难度与顺序、文化转变、角色技能需求及测试流程。敏捷测试转型模型包括文化、组织、流程与实践等关键要素,并针对各层面提出具体实施建议与障碍解决方案。此外,详细阐述了不同敏捷测试角色的技能需求与职责,以及从Sprint内至跨Sprint的测试流程与交付物。
16 5
敏捷测试价值观、方法和实践读书笔记(3)
|
8天前
|
开发框架 数据可视化 项目管理
敏捷测试价值观、方法和实践读书笔记(1)
敏捷软件开发宣言在身体力行的同时也帮助我们一直在实践中探寻更好的软件开发方法。由此,我们建立了如下价值观:个体和互动 高于 流程和工具工作的软件,高于 详尽的文档客户合作, 高于 合同谈判响应变化,高于 遵循计划。也就是说,尽管右项有其价值,但我们更重视左项的价值。
30 4
敏捷测试价值观、方法和实践读书笔记(1)
|
8天前
|
JavaScript 前端开发 Java
敏捷测试价值观、方法和实践读书笔记(5)
本章节介绍了敏捷功能测试的原则与实践,包括单元测试的概念及其编写步骤,测试驱动开发(TDD)的流程,以及如何通过模拟对象进行测试。详细讲解了单元测试的编写方法,如初始化对象、执行操作及验证结果,并探讨了 TDD 的五个步骤。通过具体案例展示了如何逐步完善储蓄账户的功能测试,包括存款、取款及异常处理。此外,还讨论了代码覆盖率的重要性及其局限性,强调了测试充分性比单纯追求代码覆盖率更为关键。
14 3
敏捷测试价值观、方法和实践读书笔记(5)
|
4天前
|
机器学习/深度学习 人工智能 测试技术
软件测试中的自动化测试实践与挑战
本文深入探讨了软件测试领域中的自动化测试,从基本概念到实际应用案例,揭示了自动化测试在提升软件开发效率和质量中的关键作用。同时,文章也分析了在实施自动化测试过程中面临的主要挑战,并提出了相应的解决策略。
25 5
|
3天前
|
设计模式 人工智能 算法
PHP中的设计模式:策略模式的深入解析与实践软件测试中的人工智能革命:提升效率与准确性的新篇章
在PHP开发中,理解并运用设计模式是提升代码质量和可维护性的重要途径。本文聚焦于策略模式(Strategy Pattern),一种行为型设计模式,它允许在运行时选择算法或业务规则。通过本文,我们将深入探讨策略模式的定义、结构、使用场景以及如何在PHP项目中有效地实现和利用策略模式。不同于性能优化等技术性摘要,本文着重于提供对策略模式全面而实用的理解,助力开发者编写出更加灵活和可扩展的应用程序。 本文深入探讨了人工智能在软件测试领域的应用,揭示了其如何显著提高测试过程的效率和准确性。通过实际案例分析,展示了AI技术在自动化测试、缺陷检测及结果分析中的关键作用,并讨论了实施AI测试策略时面临的挑
14 3
|
5天前
|
Ubuntu jenkins 测试技术
软件测试中的自动化与持续集成实践
【9月更文挑战第15天】在软件开发的快节奏世界中,自动化测试和持续集成(CI)已成为确保质量和效率的关键策略。本文旨在揭示如何通过实施自动化测试框架和CI流程来优化开发周期,减少人为错误,并加快产品上市时间。我们将探讨一些实用的工具和技术,以及它们如何帮助团队实现更流畅、更可靠的软件发布。
|
9天前
|
JavaScript 前端开发 数据库
数据库测试场景实践总结
本文介绍了数据库超时和应用锁表SSDB测试场景的验证方法,通过锁定数据表模拟写入失败情况,并利用SSDB进行重试。测试需开发人员配合验证功能。同时,提供了SSDB服务器登录、查询队列数量及重启服务等常用命令。适用于验证和解决数据库写入问题。
17 7
|
8天前
|
机器人 测试技术
敏捷测试价值观、方法和实践读书笔记(6)
验收测试驱动开发(ATDD)强调在开发前定义验收标准,并通过自动化测试确保用户价值得到满足。验收测试关注用户需求是否实现,而非代码细节。ATDD涉及用户、产品负责人、开发人员及测试人员,通过讨论、开发和交付三个阶段,确保产品符合预期。此方法有助于团队更好地理解和实现用户需求。
17 5
|
6天前
|
监控 jenkins 测试技术
软件测试中的自动化测试策略与实践
本文将深入探讨自动化测试在软件开发中的重要性及其实施策略。我们将从自动化测试的基本概念入手,分析其在提高软件质量、缩短开发周期和降低维护成本方面的优势。通过具体案例,展示如何有效地规划和执行自动化测试,以及如何评估其效果。
14 1