编写JUnit测试的另一种方法(Jasmine方法)

最近,我为一个小型个人项目编写了很多Jasmine测试。 我花了一些时间才终于感到正确地完成了测试。 此后,当我切换回JUnit测试时,我总是很难过。 出于某种原因,JUnit测试不再那么好,我想知道是否有可能以类似于Jasmine的方式编写JUnit测试。

Jasmine是受RSpec (Ruby BDD测试框架)启发的流行JavaScript行为驱动开发测试框架。

一个简单的茉莉花测试如下所示:

describe('AudioPlayer tests', function() {var player;beforeEach(function() {player = new AudioPlayer();});it('should not play any track after initialization', function() {expect(player.isPlaying()).toBeFalsy();});...
});

第一行中的describe()函数调用使用Description AudioPlayer tests创建一个新的测试套件。 在测试套件中,我们可以使用it()创建测试(在Jasmine中称为specs)。 在这里,我们检查创建新的AudioPlayer的isPlaying()方法是否返回false。
AudioPlayer实例。

用JUnit编写的相同测试如下所示:

public class AudioPlayerTest {private AudioPlayer audioPlayer;@Before public void before() {audioPlayer = new AudioPlayer();}@Testvoid notPlayingAfterInitialization() {assertFalse(audioPlayer.isPlaying());}...
}

我个人认为Jasmine测试与JUnit版本相比更具可读性。 在Jasmine中,对测试没有任何影响的唯一噪音是括号和function关键字。 其他所有内容都包含一些有用的信息。

在阅读JUnit测试时,我们可以忽略诸如void,访问修饰符(私有,公共,..),注释和不相关的方法名称(如以@Before注释的方法名称)之类的关键字。 除此之外,以驼峰案例方法名称编码的测试描述不太好阅读。

除了提高可读性外,我真的很喜欢Jasmine嵌套测试套件的功能。

让我们来看一个更长的示例:

describe('AudioPlayers tests', function() {var player;beforeEach(function() {player = new AudioPlayer();});describe('when a track is played', function() {var track;beforeEach(function() {track = new Track('foo/bar.mp3')player.play(track);});it('is playing a track', function() {expect(player.isPlaying()).toBeTruthy();});it('returns the track that is currently played', function() {expect(player.getCurrentTrack()).toEqual(track);});});...
});

在这里,我们创建了一个子测试套件,负责测试AudioPlayer播放曲目时的行为。 内部的beforeEach()调用用于为子测试套件内的所有测试设置通用的前提条件。

相反,在JUnit中为多个(但不是全部)测试共享通用的前提条件有时会变得很麻烦。 当然,在测试中复制设置代码是不好的,因此我们为此创建了额外的方法。 为了在设置方法和测试方法之间共享数据(如上面示例中的track变量),我们必须使用成员变量(范围要大得多)。

另外,我们应确保将具有类似前提条件的测试分组在一起,以避免需要阅读整个测试类来查找特定情况下的所有相关测试。 或者我们可以将事情分成多个较小的类。 但是,然后我们可能必须在这些类之间共享设置代码……

如果我们查看Jasmine测试,就会发现该结构是通过调用全局函数(例如describe(),it(),…)并传递描述性字符串和匿名函数来定义的。

有了Java 8,我们有了Lambdas,所以我们可以做同样的事情吗?

是的,我们可以在Java 8中编写如下代码:

public class AudioPlayerTest {private AudioPlayer player;public AudioPlayerTest() {describe("AudioPlayer tests", () -> {beforeEach(() -> {player = new AudioPlayer();});it("should not play any track after initialization", () -> {expect(player.isPlaying()).toBeFalsy();});});}
}

如果我们暂时假设describe(),beforeEach(),it()和Expect()是采用适当参数的静态导入方法,则至少可以编译。 但是,我们应该如何进行这种测试?

出于兴趣,我尝试将其与JUnit集成,结果发现这实际上非常简单(我将在以后进行介绍)。 到目前为止,结果是一个名为Oleaster的小型图书馆。

用Oleaster编写的测试如下所示:

import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*;
...@RunWith(OleasterRunner.class)
public class AudioPlayerTest {private AudioPlayer player;{describe("AudioPlayer tests", () -> {beforeEach(() -> {player = new AudioPlayer();});it("should not play any track after initialization", () -> {assertFalse(player.isPlaying());});});}
}

与前面的示例相比,只有几处发生了变化。 在这里,测试类使用JUnit @RunWith注释进行注释。 这告诉JUnit在运行此测试类时使用Oleaster。 通过静态导入StaticRunnerSupport。*,可以直接访问静态Oleaster方法,例如describe()或it()。 还要注意,构造函数已由实例初始化程序替换,而Jasmine like matcher被标准JUnit断言替换。

与原始的茉莉花测试相比,实际上有一件事情并不那么出色。 实际上,在Java中,变量必须有效地最终确定才能在lambda表达式中使用。 这意味着以下代码段无法编译:

describe("AudioPlayer tests", () -> {AudioPlayer player;beforeEach(() -> {player = new AudioPlayer();});...
});

在beforeEach()lambda表达式内对玩家的赋值将不会编译(因为玩家实际上不是最终的)。 在Java中,我们必须在这种情况下使用实例字段(如上例所示)。

万一您担心要报告:Oleaster仅负责收集和运行测试用例。 整个报告仍由JUnit完成。 因此,Oleaster应该不会对使用JUnit报告的工具和库造成任何问题。

例如,以下屏幕截图显示了IntelliJ IDEA中Oleaster测试失败的结果:

oleaster-idea

如果您想知道Oleaster测试在实践中的外观,可以看看Oleaster的测试(这些测试是用Oleaster本身编写的)。 您可以在此处找到GitHub测试目录。

通过评论此帖子或创建GitHub问题,随时添加任何类型的反馈。

翻译自: https://www.javacodegeeks.com/2014/07/an-alternative-approach-of-writing-junit-tests-the-jasmine-way.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

H5 input输入限制最大位数,和调用小键盘需求发生冲突的解决办法

首先&#xff0c;限制输入最大位数时&#xff0c;input有自带的属性maxlength。 <input type"text" name"email" maxlength"55" /> 使用方法&#xff1a;maxlength"位数" 但是&#xff0c;对于这个属性他是有自己的限制条件的 …

解决vue项目在ie浏览器中不显示的问题

安装 “babel-polyfill” npm install babel-polyfill --save-dev 或者 cnpm install babel-polyfill --save-dev在入口 main.js 文件引入&#xff1a;import babel-polyfill在 build 文件下的 webpack.base.conf.js 文件中修改代码&#xff1a; entry: {app: ["babel-p…

Spark-Luanch Driver

1.SparkSubmit.scala主要调用M-prepareSubmitEnvironment&#xff0c;该方法更根据用户定义的参数&#xff0c;匹配不同client&#xff0c;去调用不同clientApp。(ps&#xff1a;本次讲ClientApp 也就是standalone)在M-runMain通过 调用M-Utils.classForName 反射的方式调用 …

大风大浪大鱼

一群年轻人常在一泓深潭边钓鱼&#xff0c;而有一个渔夫总是在潭上边水流湍急的河里捕鱼。 年轻人觉得这渔夫可笑&#xff0c;在大风大浪的河里怎么会捕到鱼呢?有一天&#xff0c;年轻人忍不住去问渔夫&#xff1a;“鱼能在这么湍急的地方停留吗?”渔夫说&#xff0c;当然不能…

清空表单时出现问题

打开页面时报警告&#xff1a; 解决办法&#xff1a; &#xff08;1&#xff09;npm i default-passive-events -S &#xff08;2&#xff09;main.js中加入&#xff1a;import ‘default-passive-events’ 参考&#xff1a;https://www.jianshu.com/p/23850d4cade8 出现原…

JQuery Ajax 使用FormData上传文件对象

FormData部分: 先new FormData对象 :let somedata new FormData(),然后将数据添加进去&#xff0c;这里我们使用append()进行添加。 这里举一个上传头像的例子&#xff1a; let token localStorage.token; let img $(".file")..get(0).files[0]; let somedat…

[探索][管理]《现在,发现你的优势》

此书是我迄今为止看过最棒的一本书&#xff01;&#xff01;&#xff01; 为什么这么说&#xff0c;因为就像前言彼得德鲁克所说的一样 -- 大部分的人都不知道他们的优势何在。此书的宗旨就是测试你的优势是什么&#xff0c;并且发展你的优势。为何要去改变你不擅长的东西呢&am…

box2d——1.tiles瓦片积木

【调试渲染】 将TestCpp里Box2DTestBed的GLES-Render.h/cpp加入到项目中。声明绘制变量&#xff1a;GLESDebugDrawmDebugDraw。 【创建世界】 // 依据重力创建世界b2Vec2 gravity;gravity.Set(0.0f, -10.0f);mWorld new b2World(gravity);// 设置调试渲染和碰撞侦听mWorld-&…

如何在JSF中实现自定义密码强度指示器

使用JavaScript验证密码强度是一项常见任务。 在本文中&#xff0c;我将展示如何向基于JSF的Web应用程序添加密码强度指示器。 的 PrimeFaces中的密码组件已经具有密码强度的反馈指示符&#xff0c;但是它有两个主要缺点&#xff1a; 反馈指示器没有响应&#xff08;固定宽度…

CSS 学习路线(二)选择器

选择器 规则结构: 分两个基本部分 选择器(selector)和声明块(declaration block) 组成 声明块:由一个或多个声明组成,每一个声明都是属性-值对 选择器分为:元素选择器,类选择器,后代选择器,通配选择器,ID选择器,属性选择器,伪类选择器.子元素选择器,相邻兄弟选择器. 元素选…

关于vue打包的问题

一、vue-cli2 二、vue-cli3 一、vue-cli2 错误提示&#xff1a; npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! hewelry1.0.0 build: node build/build.js npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the hewelry1.0.0 build script. npm ERR! This is prob…

关于==和equals的区别和联系,面试这么回答就可以

长篇大论的话&#xff0c;我这里就不多写了&#xff0c;相信大家入门java 的时候就知道个大概了&#xff0c;这里想表述的是&#xff0c;如果面试官问你《关于和equals的区别》&#xff0c;该怎么回答完美呢&#xff1f;可以这样说 总结的来说&#xff1a; 1&#xff09;对于&a…

如何使用新的Apache Http Client发出HEAD请求

如果您已更新Apache HTTP Client代码以使用最新的库&#xff08;在撰写本文时&#xff0c;它是4.2.x版本的httpclient 4.3.5版本和httpcore 4.3.2版本&#xff09;&#xff0c;您会注意到某些类&#xff08;例如org.apache.http.impl.client.DefaultHttpClient或org.apache.htt…

Delphi中禁止WebBrowser右键的方法

usesMSHtml;//在控件标签additional中找到TApplicationEvents控件&#xff0c;拖到窗体上&#xff0e;在TApplicationEvents的OnMessage事件中加入以下代码&#xff1a;//替换右键菜单procedureTForm1.ApplicationEvents1Message(varMsg: tagMSG; varHandled: Boolean);varmPoi…

【前端框架-Vue-基础】$attr及$listeners实现跨多级组件的通信

父子 A 组件与 B 组件之间的通信&#xff1a; &#xff08;父子组件&#xff09; 如上图所示&#xff0c;A、B、C三个组件依次嵌套&#xff0c;按照 Vue 的开发习惯&#xff0c;父子组件通信可以通过以下方式实现&#xff1a; A to B 通过props的方式向子组件传递&#xff0c…

html笔记(一)html4+css2.0、css基础和属性、盒模型

w3c 官网 这里是 html4 的内容 大标题小节一、关于HTML1. 基本语法2. HTML常用标签3. 相对路径和绝对路径二、css基础1. 表单元素2. 创建样式表3. css语法4. css选择器三、css的相关属性1. 列表 li 独有的属性list-style2. 边框属性border3. overflow4. 浮动 float 遇到的坑5.…

JUnit:使用Java 8和Lambda表达式测试异常

在JUnit中&#xff0c;有许多方法可以在测试代码中测试异常&#xff0c;包括try-catch idiom JUnit Rule和catch-exception库。 从Java 8开始&#xff0c;我们还有另一种处理异常的方法&#xff1a;使用lambda表达式。 在这篇简短的博客文章中&#xff0c;我将演示一个简单的示…

动态语言和静态语言的比较

一 、静态语言的优势到底在哪&#xff1f; 来自robbin 摘自 http://www.javaeye.com/article/33971?page7 引用是像Java或者C&#xff03;这样强类型的准静态语言在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中也有着非常强的优势这是一个存在于大家心…

sqlserver2012——使用子查询

1 select A.成绩&#xff0c;A.分数,B.姓名 FROM 成绩信息 A, 学生信息 BWHERE A.学生编号B.学号 AND A.课程编号‘2’ AND A.考试编号‘0801’ AND A.分数 <( SELECT AVG(分数) FROM 成绩信息 A&#xff0c;学生信息 B where A.学生编号B.学号 AND A.课程编号‘2’ and A.…

返回顶部小火箭

代码如下&#xff1a; <!DOCTYPE html> <html> <head lang"en"><meta charset"UTF-8"><title></title><style>body {width: 2000px;}.top{position: fixed;right:50px;bottom:100px;display: none;}</style&…