单元测试实践

简介: 工欲善其事,必先利其器. 单元测试三剑客: - 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.

相关文章
|
1月前
|
测试技术
软件测试的艺术:探索式测试的实践与思考
在软件开发的广阔海洋中,测试是确保航船稳健行驶的关键。本文将带你领略探索式测试的魅力,一种结合创造性思维和严格方法论的测试方式。我们将一起揭开探索式测试的神秘面纱,了解其核心概念、实施步骤和带来的效益。通过实际代码示例,你将学会如何将探索式测试融入日常的软件质量保证流程中,提升测试效率与质量。
|
21天前
|
数据采集 监控 机器人
浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)
最开始转转的客服系统体系如IM、工单以及机器人等都是使用第三方的产品。但第三方产品对于转转的业务,以及客服的效率等都产生了诸多限制,所以我们决定自研替换第三方系统。下面主要分享一下网页端IM技术及相关测试方法,我们先从了解IM系统和WebSocket开始。
37 4
|
23天前
|
人工智能 JavaScript 前端开发
自动化测试框架的演进与实践###
本文深入探讨了自动化测试框架从诞生至今的发展历程,重点分析了当前主流框架的优势与局限性,并结合实际案例,阐述了如何根据项目需求选择合适的自动化测试策略。文章还展望了未来自动化测试领域的技术趋势,为读者提供了宝贵的实践经验和前瞻性思考。 ###
|
21天前
|
测试技术 Python
探索软件测试的深度与广度:从理论到实践
在数字化时代,软件已成为我们生活中不可或缺的一部分。随着技术的不断进步和用户需求的多样化,确保软件质量变得尤为重要。本文将深入浅出地介绍软件测试的核心概念、类型及其在软件开发生命周期中的重要性。我们将通过实际案例,展示如何实施有效的测试策略,并探讨自动化测试的未来趋势,旨在为读者提供一套完整的软件测试知识体系,帮助提升软件质量和开发效率。
|
22天前
|
测试技术 Python
探索软件测试的奥秘:从理论到实践
在软件开发的宇宙中,软件测试犹如一颗璀璨的星辰,指引着质量的方向。本文将带你穿梭于软件测试的理论与实践之间,揭示其内在的逻辑和魅力。从测试的重要性出发,我们将探讨不同类型的测试方法,并通过实际案例分析,深入理解测试用例的设计和应用。最后,我们将通过一个代码示例,展示如何将理论知识转化为实际操作,确保软件质量的同时,也提升你的测试技能。让我们一起踏上这段探索之旅,发现软件测试的无限可能。
|
25天前
|
jenkins 测试技术 持续交付
自动化测试框架的搭建与实践
在软件开发领域,自动化测试是提升开发效率、确保软件质量的关键手段。本文将引导读者理解自动化测试的重要性,并介绍如何搭建一个基本的自动化测试框架。通过具体示例和步骤,我们将探索如何有效实施自动化测试策略,以实现软件开发流程的优化。
52 7
|
24天前
|
测试技术
探索软件测试的奥秘:从理论到实践
本文深入探讨了软件测试的基本概念、重要性、主要类型以及实施策略。通过分析不同测试阶段和相应的测试方法,文章旨在为读者提供一套完整的软件测试知识体系,帮助他们更好地理解和应用测试技术,确保软件产品的质量和可靠性。
44 4
|
28天前
|
机器学习/深度学习 人工智能 自然语言处理
智能化软件测试:AI驱动的自动化测试策略与实践####
本文深入探讨了人工智能(AI)在软件测试领域的创新应用,通过分析AI技术如何优化测试流程、提升测试效率及质量,阐述了智能化软件测试的核心价值。文章首先概述了传统软件测试面临的挑战,随后详细介绍了AI驱动的自动化测试工具与框架,包括自然语言处理(NLP)、机器学习(ML)算法在缺陷预测、测试用例生成及自动化回归测试中的应用实例。最后,文章展望了智能化软件测试的未来发展趋势,强调了持续学习与适应能力对于保持测试策略有效性的重要性。 ####
|
28天前
|
敏捷开发 Devops 测试技术
探索自动化测试之美:从理论到实践
在软件开发的海洋中,自动化测试犹如一座灯塔,指引着项目向着质量和效率的彼岸。本文将扬帆起航,从自动化测试的意义出发,穿越工具选择的海域,停靠在实战演练的岛屿,最终抵达持续集成的港湾。我们将通过一个具体的代码示例,体验自动化测试的魅力,并分享如何将这些实践应用到日常的软件质量保证过程中。
|
27天前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
45 2