设为首页 加入收藏

TOP

使用 Spock 框架进行单元测试(二)
2017-12-07 14:22:06 】 浏览:1385
Tags:使用 Spock 框架 进行 单元 测试
人来说几乎是不可能完成的任务。这也让很多新人有了“写单测很难”的感觉。

所以在这里需要强调一个观点,写单元测试的难易程度跟代码的质量关系最大,并且是决定性的。项目里无论用了哪个测试框架都不能解决代码本身难以测试的问题,所以如果你遇到的是“我的代码里依赖的东西太多了所以写不出来单测”这样的问题的话,需要去看的是如何设计和重构代码,而不是这篇文章。

2.3.推荐阅读

3.Spock是什么

3.1.简介

这里引用官方的介绍:

Spock is a testing and specification framework for Java and Groovy applications. What makes it stand out from the crowd is its beautiful and highly expressive specification language. Thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers. Spock is inspired from JUnit, jMock, RSpec, Groovy, Scala, Vulcans, and other fascinating life forms.

简单地说,spock是一个测试框架,它的核心特性有以下几个:

  • 可以应用于java或groovy应用的单元测试框架。
  • 测试代码使用基于groovy语言扩展而成的规范说明语言(specification language)。
  • 通过junit runner调用测试,兼容绝大部分junit的运行场景(ide,构建工具,持续集成等)。
  • 框架的设计思路参考了JUnit,jMock,RSpec,Groovy,Scala,Vulcans……

要理解spock的几个特性,还要理解几个关键名词:

3.1.1.groovy

引用维基百科上的介绍:

Groovy是Java平台上设计的面向对象编程语言。这门动态语言拥有类似Python、Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用。

Groovy的语法与Java非常相似,以至于多数的Java代码也是正确的Groovy代码。Groovy代码动态的被编译器转换成Java字节码。由于其运行在JVM上的特性,Groovy可以使用其他Java语言编写的库。

groovy是一门比较轻量,学习门槛也比较低的语言。对于只用过java语言的程序员来说,groovy是一个很不错的开拓视野的机会。如果你没有接触过groovy,那么可以参考这两条:

  1. 可以用纯java的语法写groovy。
  2. 参考这篇快速入门

我个人比较喜欢groovy语言,在一些小项目中经常使用它。引用一下R大在知乎的回复

Groovy比较讨好来自Java的程序员的一点是:用它写代码可以渐进的从接近Java的风格进化为接近Ruby的风格。使用接近Java风格写Groovy时,代码几乎跟Java一样,容易上手;而学习过程中可以逐渐用上各种类似Ruby的方便功能。

3.1.2.specification language

如果接触过不同语言类型的开源项目的话,就会发现有些项目中找不到测试目录(test),取而代之的是一个叫“spec”的目录,比如用ruby写的项目gitlab。这里的spec实际是specification的缩写,它的背后是一种近些年来开始流行起来的编程思想:BDD(Behavior-driven development)。

关于BDD,同样是引用维基百科上的介绍:

BDD:行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。BDD最初是由Dan North在2003年命名,它包括验收测试和客户测试驱动等的极限编程的实践,作为对测试驱动开发的回应。

BDD的做法包括:

  • 确立不同利益相关者要实现的远景目标
  • 使用特性注入方法绘制出达到这些目标所需要的特性
  • 通过由外及内的软件开发方法,把涉及到的利益相关者融入到实现的过程中
  • 使用例子来描述应用程序的行为或代码的每个单元
  • 通过自动运行这些例子,提供快速反馈,进行回归测试
  • 使用“应当(should)”来描述软件的行为,以帮助阐明代码的职责,以及回答对该软件的功能性的质疑
  • 使用“确保(ensure)”来描述软件的职责,以把代码本身的效用与其他单元(element)代码带来的边际效用中区分出来。
  • 使用mock作为还未编写的相关代码模块的替身

BDD背后的编程思想超出了这篇文章的范围,这里就不再展开。上文说的specification language实际上是BDD其中一部分思想的实现手段:通过某种规范说明语言去描述程序“应该”做什么,再通过一个测试框架读取这些描述、并验证应用程序是否符合预期。

3.1.3.单元测试的运行场景

测试只有被执行之后才会有价值,这里就涉及一个“什么时候执行单元测试”的问题。

  1. 被接触最多的就是在IDE中执行单元测试,java程序员比较幸运,主流的java IDE都可以很好的集成了单元测试功能,单元测试代码自动生成、测试覆盖率检查等功能也都成了IDE的标配。这些功能都能让程序员在编写代码的时候直接可以运行单元测试得到反馈。ut-ide
  2. 其次,主流的构建工具(如maven、gradle)中也都实现了运行单元测试的功能,在生成二进制包之前可以对代码进行回归测试,这些构建工具都可以通过命令行调用,这是自动化构建的前提。ut-maven
  3. 在此之上,依托于构建工具提供的自动化特性,在持续集成、持续部署的过程中可以执行自动化构建,在自动化构建的过程中通过构建工具执行单元测试,这是持续集成的流程中的重要步骤。
  4. ut-ci

3.2.Spock与现有框架的对比

3.2.1.已有的java单元测试框架

就像刚才说的,有很多已有的单元测试框架,稍微老一点的如JMockit、EasyMock,新一点的类似Mockito和PowerMock。我之前一直在用testng+Mockito作为主要的单元测试框架,用它写过大概上万行单元测试,它的写法相对来说比较易读,功能也能满足大多数场景。

但在使用mockito的过程中也总是有一些不是很方便的地方,比如代码的可读性总还是差那么一点,比如像这样:

@Test
public void testIsUserEnabled_userStatusIsClosed_returnFalse() throws Exception {
    UserInfo userInfo = new UserInfo();
    userInfo.status = UserInfo.CLOSED;
    doReturn(userInfo).when(userDao).getUserInfo(anyLong());
 
    boolean isUserEnabled = userService.isUserEnabled(1l);
 
    Assert.assertFalse(isUserEnabled);
}

虽然能读懂,但是对于它所做的事情全来说感觉说了很多废话,单元测试代

首页 上一页 1 2 3 4 5 6 下一页 尾页 2/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇源码 | 批量执行invokeAll() && .. 下一篇Spring、Spring Boot 和 TestNG ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目