jasmine单元测试_使用Jasmine,Spock和Nashorn测试JVM服务器端JavaScript

jasmine单元测试

JavaScript使用不仅限于浏览器中的客户端代码或NodeJS支持的服务器端代码。 许多基于JVM的项目都将其用作内部脚本语言。 测试这种功能既不简单也不标准。 在本文中,我打算演示一种使用成熟的工具(例如JasmineSpockNashorn在服务器端JVM环境中测试JavaScript的方法。

与客户端编码相比,在JVM应用程序内部将JavaScript用作脚本引擎有很大的不同。 不幸的是,如今没有用于测试它的工业标准工具。



关于Internet中现有的方法,我想强调以下缺点:

  • 缺乏与构建和持续集成工具(Maven,Gradle,Jenkins等)的集成
  • 与IDE的合作不足
    • 无法运行单个套件或通过IDE进行测试
  • 与浏览器环境紧密耦合
  • 无法使用自定义的JavaScript执行程序

据我所知,大多数项目通过调用JS引擎运行器,将被测脚本传递给它并通过在脚本执行后检查引擎或模拟的副作用来进行断言来测试其嵌入式业务脚本。

这些方法通常具有类似的缺点:

  • 很难在JS代码中存根或模拟某些东西,通常会导致对JS prototype黑客攻击
  • 脚本的模拟环境需要过多的编排
  • 难以将测试组织到套件中并报告测试执行错误
  • 以前的原因为特定项目创建了自定义测试套件框架
  • 不利用现有JavaScript测试工具和框架

因此,出于对JVM项目中舒适的嵌入式JavaScript测试的需求的驱动,我创建了此样本设置。 为了实现我们的目标,将使用下一个工具。

  • Jasmine是最著名JavaScript TDD / BDD工具之一
  • Spock是由Junit和Groovy支持的JVM的出色测试框架
  • Nashorn是JDK8中引入的现代脚本引擎

定制JavaScript运行器(基于Nashorn)

在非浏览器JS环境中不需要遵循标准,因此开发人员通常使用自定义函数,内置变量等来扩展脚本引擎。对于生产和测试目的,使用完全相同的运行程序极为重要。

让我们考虑一下,我们有这样的自定义运行器,接受脚本名称和预定义变量的映射作为参数并返回执行脚本的结果值。

JavaScriptRunner.java

public class JavaScriptRunner {public static Object run(String script, Map<String, Object> params) throws Exception {ScriptEngineManager factory = new ScriptEngineManager();ScriptEngine engine = factory.getEngineByName("nashorn");engine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(params);return engine.eval(new InputStreamReader(JavaScriptRunner.class.getResourceAsStream(script))); (1)}
}
1个 脚本源在类路径中搜索。

茉莉花的设置

要开始使用Jasmine框架,我们需要:

  • 下载Jasmine并将其解压缩到项目资源目录中的/jasmine/jasmine-2.1.2文件夹中
  • 自定义引导脚本,因为Jasmine不支持基于JVM的平台

jasmine2-bootstrap.js

var loadFromClassPath = function(path) { (1)load(Java.type("ua.eshepelyuk.blog.nashorn.Jasmine2Specification").class.getResource(path).toExternalForm());
};var window = this;loadFromClassPath("/jasmine/jasmine-2.1.2/jasmine.js");
loadFromClassPath("/jasmine/jasmine2-html-stub.js"); (2)
loadFromClassPath("/jasmine/jasmine-2.1.2/boot.js");
load({script: __jasmineSpec__, name: __jasmineSpecName__}); (3)onload(); (4)jsApiReporter.specs(); (5)
1个 helper函数从类路径位置解析脚本路径。
2 Nashorn专用代码可在非浏览器环境中调整Jasmine 。 不属于Jasmine发行。
3 加载测试套件源代码,有关详细信息,请参见下一部分。
4 伪造浏览器load事件,应触发测试套件执行。
5 该值将作为脚本结果返回。

将茉莉花报告转换为Spock测试

有了Jasmine JS执行程序和引导脚本,我们可以创建JUnit测试来遍历套件结果并检查是否全部成功。 但是了解哪个测试失败以及失败的原因将成为一场噩梦。 我们真正想要拥有的功能是能够将每个Jasmine规范表示为JUnit测试,因此任何Java工具都可以拾取并检查结果。 这就是为什么Spock可以解决问题的原因,它的数据驱动测试允许开发人员声明输入数据列表,并针对该数据集的每个项目创建并执行新测试。 这与Junit 参数化测试非常相似,但是功能更强大。

因此,想法是将运行引导脚本后获得的Jasmine测试套件结果视为输入数据数组,其每一项都将传递给Spock测试。 然后测试本身将提供断言以正确报告成功和失败的测试,即断言应检查Jasmine规范的状态。

  • 如果状态为pendingpassed ,则表示规范被忽略或成功
  • 否则, Spock测试应该抛出断言错误,并用Jasmine报告的失败消息填充断言异常

Jasmine2Specification.groovy

abstract class Jasmine2Specification extends Specification {@Shared def jasmineResultsdef setupSpec() {def scriptParams = ["__jasmineSpec__"    : getMetaClass().getMetaProperty("SPEC").getProperty(null), (1)"__jasmineSpecName__": "${this.class.simpleName}.groovy"]jasmineResults = JavaScriptRunner.run("/jasmine/jasmine2-bootstrap.js", scriptParams) (2)}def isPassed(def specRes) {specRes.status == "passed" || specRes.status == "pending"}def specErrorMsg(def specResult) {specResult.failedExpectations.collect {it.value}.collect {it.stack}.join("\n\n\n")}@Unroll def '#specName'() {expect:assert isPassed(item), specErrorMsg(item) (3)where:item << jasmineResults.collect { it.value }specName = (item.status != "pending" ? item.fullName : "IGNORED: $item.fullName") (4)}
}
1个 Jasmine套件的源代码公开为jasmineSpec变量,可让JS执行器访问。
2 Jasmine套件的实际执行。
3 对于每个套件结果,我们assert要么成功,要么在失败时使用Jasmine发起的消息引发断言错误。
4 其他数据提供程序变量,以突出显示被忽略的测试。

完整的例子

让我们为简单JavaScript函数创建测试套件。

mathUtils.js

var add = function add(a, b) {return a + b;
};

使用上一步中的基类,我们可以创建包含JavaScript测试的Spock套件。 为了演示我们解决方案的所有可能性,我们将创建成功,失败和被忽略的测试。

MathUtilsTest.groovy

class MathUtilsTest extends Jasmine2Specification {static def SPEC = """ (1)
loadFromClassPath("/js/mathUtils.js"); (2)
describe("suite 1", function() {it("should pass", function() {expect(add(1, 2)).toBe(3);});it("should fail", function() {expect(add(1, 2)).toBe(3);expect(add(1, 2)).toBe(0);});xit("should be ignored", function() {expect(add(1, 2)).toBe(3);});
})
"""
}
1个 Jasmine套件的实际代码表示为String变量。
2 使用从jasmine-bootstrap.js继承的功能加载测试中的模块。


图1. IntelliJ IDEA的测试结果


图1. IntelliJ IDEA的测试结果

IntelliJ Idea语言注入

尽管此微框架可以在所有IDE中使用,但由于其语言注入 ,它的最方便用法将在IntelliJ IDEA中 。 该功能允许将任意语言嵌入到以不同编程语言创建的文件中。 因此,我们可以将JavaScript代码块嵌入到用Groovy编写的Spock规范中。

图2.语言注入

图2.语言注入

解决方案的优缺点

优点

  • 使用两种语言的行业标准测试工具
  • 与构建工具和持续集成工具无缝集成
  • 从IDE运行单个套件的能力
  • 借助Jasmine的突出功能,可以从特定套件运行单个测试

缺点

  • 在测试异常的情况下,没有干净的方法来检测特定的源代码行
  • 一点面向IntelliJ IDEA的设置

聚苯乙烯

在此示例项目中,我使用了JDK8的现代Nashorn引擎。 但实际上对此没有限制。 同样的方法已成功应用于使用较旧Rhino引擎的项目。 再说一次, Jasmine只是我的个人喜好。 随着其他工作代码的调整,可以利用MochaQUnit等。

  • 完整的项目代码可在My GitHub上获得 。

翻译自: https://www.javacodegeeks.com/2014/12/testing-jvm-server-side-javascript-with-jasmine-spock-and-nashorn.html

jasmine单元测试

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

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

相关文章

常用于单片机的接口适配器模式C语言实现

一般实现在我们做项目的时候&#xff0c;一般的实现&#xff0c;可能我们会这样写代码// FileName: test.c// 来源&#xff1a;公众号【技术让梦想更伟大】#include#include “ExternModule.h” int main(void){/*初始化*/ vAllInit(); while(1) { /*项目逻辑*/ vLo…

ar面部识别_国内手机厂商AR布局报告

欢迎关注AIRX的B站官方账号&#xff1a;AIRX社区&#xff0c;我们会定期和一些ARVR、AI企业和高校合作直播&#xff0c;分享前沿ARVR、AI、Unity、Unreal技术和教程。招运营、UI设计志愿者进行时&#xff0c;我们期待您的加入&#xff5e;文章来源 &#xff1a;增强现实核心技术…

rest服务swagger_在Java EE 7上骑骆驼–带有Swagger文档的REST服务

rest服务swagger骆驼开箱即用。 Swagger集成就是其中之一。 不幸的是&#xff0c;大多数已经存在的功能都严重依赖于Spring。 但这并不能阻止我们在普通的Java EE 7应用程序中使用它们&#xff0c;因为有时它只是更轻量级的处理方式。 但是我不想再对此进行讨论。 相反&#xf…

知识贴!单片机C语言编程之.H文件与.C文件的关系

一、.H文件与.C文件的关系&#xff1a;迄今为止&#xff0c;写过的程序都是一些很简单的程序&#xff0c;从来没有想到要自己写.H文件&#xff0c;也不知道.H文件到底什么用&#xff0c;与.C文件什么关系。只是最近写键盘程序&#xff0c;参考别人的程序时&#xff0c;发现别人…

vector怎么按字段查询顺序输出_7大查询匹配类函数,一次给你总结好

Excel数据处理中&#xff0c;经常用到各种函数&#xff0c;可以说函数是Excel必不可少的一部分&#xff0c;今天向大家介绍数据处理中的七个查询匹配函数。下面一一介绍各函数的具体用法。vlookup功能&#xff1a;搜索表区域首列满足条件的元素&#xff0c;确定待检索单元格在区…

信工干货||C语言中的运算符和表达式

C语言中的运算符和表达式1算术运算符及表达式&#xff08;1&#xff09;算术运算符包括&#xff1a; &#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;%。&#xff08;2&#xff09;*&#xff0c;/&#xff0c;%同级&#xff0c;比 &#xff0c;-高。&#xff08;3&#x…

3皮卡丘眨眼代码_活见久,皮卡丘居然是一门编程语言

我很荣幸地向你介绍皮卡神教的编程语言&#xff0c;这门语言专为皮神设计(认真脸)。为什么一定要学习这门语言呢——谁不想要只皮卡丘我问你&#xff1f;在当今的宝可梦就业环境中&#xff0c;大多数皮卡丘们都在残忍的宝可梦训练师手下过着顺从和被奴役的生活。他们经常被迫与…

C语言关系运算符详解

关系运算符在使用时&#xff0c;它的的两边都会有一个表达式&#xff0c;比如变量、数值、加减乘除运算等&#xff0c;关系运算符的作用就是判明这两个表达式的大小关系。注意&#xff0c;是判明大小关系&#xff0c;不是其他关系。C语言提供了以下关系运算符&#xff1a;关系运…

jboss fuse 教程_IDC关于使用JBoss Fuse的商业价值的报告(与Apache Camel一起使用)

jboss fuse 教程这只是一篇博客文章&#xff0c;具有更多的商业性质&#xff0c;但是您不能一无所有。 实际上&#xff0c;这也是使Apache Camel保持活力并保持良好状态的原因&#xff0c;这还归功于其商业上的成功。 希望从JBoss Fuse之类的产品中寻找有关在商业上使用Apache…

嵌入式软件架构设计分层思路

在正规的项目开发中&#xff0c;项目往往是并行开发的&#xff0c;也就是说硬件设计、底层软件设计、应用软件设计等是同步进行的。比如说在开发板上调试模块驱动&#xff0c;在其他平台上调试应用程序再移植到目前这个平台等。嵌入式专栏1为什么很少看见嵌入式软件架构师职位在…

C语言函数返回1和返回0究竟哪个好?

基本上&#xff0c;没有人会将大段的C语言代码全部塞入 main() 函数。更好的做法是按照复用率高、耦合性低的原则&#xff0c;尽可能的将代码拆分不同的功能模块&#xff0c;并封装成函数。C语言代码的组合千变万化&#xff0c;因此函数的功能可能会比较复杂&#xff0c;不同的…

乐高ev3搭建图_乐高EV3第一讲,Hello Ev3,搭建机甲战神模型

课程主题认识编程及结构。课程目标1.简单认识 Ev3 的硬件及使用2.学习 Ev3主控自带的功能(最好拿控制器给孩子演示讲解)联系同学们好&#xff01;从今天开始我们就要进入乐高 EV3的世界&#xff0c;制作更多更酷、更好玩的机器人了&#xff01;首先老师先来问大家几个基本的问题…

对单片机C语言的一些误用和总结

我觉得语言之所以能称之为语言&#xff0c;它肯定是一种工具一种相互交流相互通信相互传达之间的意图的工具&#xff0c;作为语言那肯定得有自己的语法&#xff0c;要想相互交流肯定得先学好它的语法吧(比如像表达式&#xff0c;函数&#xff0c;循环&#xff0c;指针)我称之为…

java8 camel_WildFly 8的Camel子系统集成了Java EE –入门

java8 camel就在三天前&#xff0c;围绕Thomas Diesler&#xff08; tdiesler &#xff09;的团队发布了WildFly-Camel子系统的2.0.0.CR1版本&#xff0c;它允许您将Camel Routes添加为WildFly配置的一部分。 路由可以部署为JavaEE应用程序的一部分。 JavaEE组件可以访问Camel …

php简单网站源码包含数组_PHP无限分级阶梯递归数组排列 以及多层嵌套数组在网页中的解析源码...

数组递归PHP无限分级 将数组递归转化成阶梯型数组 数组中包含数组 使用更方便 查看也很方便&#xff0c;网上找的都不是很好&#xff0c;自己写的才是王道简单的递归 没有什么特别之处 只是自己写的容易理解一点而已&#xff01;代码在下面$array[0]array(fid>1,top>0,n…

工程师总结:单片机C语言编程心得

一、.H文件与.C文件的关系&#xff1a;迄今为止&#xff0c;写过的程序都是一些很简单的程序&#xff0c;从来没有想到要自己写.H文件&#xff0c;也不知道.H文件到底什么用&#xff0c;与.C文件什么关系。只是最近写键盘程序&#xff0c;参考别人的程序时&#xff0c;发现别人…

在建工地扬尘在线监控系统推荐_vocs在线监控系统安装的法规依据

voc是挥发性有机化合物的简称&#xff0c;在环保监测领域指活泼累得挥发性有机物&#xff0c;具有特殊的刺激性气味&#xff0c;vocs在线监控系统是专门用于监测voc的排放浓度及排放量的。当一个空间内的voc浓度达到一定数值&#xff0c;人们会出现头晕、恶心、呕吐等多种症状&…

jboss默认进程名称_快速指南:剖析JBoss BPM跨进程通信

jboss默认进程名称&#xff08;文章来宾与北美红帽公司高级解决方案架构师杰伊保拉杰合着&#xff09; 几周的提示与技巧文章将深入探讨JBoss BPM Suite&#xff0c;特别是有关如何在两个流程之间进行通信的问题。 在深入了解解决方案细节之前&#xff0c;让我们首先约束将要讨…

嵌入式C语言编程——.h文件与.c文件

.h文件与.c文件的关系参考高手的程序时&#xff0c;发现别人写的严格的程序都带有一个“KEY.H”&#xff0c;里面定义了.C文件里用到的自己写的函数&#xff0c;如Keyhit()、Keyscan()等。.H文件就是头文件&#xff0c;估计就是Head的意思吧&#xff0c;这是规范程序结构化设计…

sql between包括两端吗_SQL简单查询

1.SQL简单查询知识点概要&#xff1a;1. 1基本的查询语句&#xff1a;1.1 .1 Select<列明1>,<列明2>1.1.2 From<表名>1.2. SQL运行数据&#xff1a;1.2.1 SQL语句以英文分号(;)结尾。1.2.2列明用英文的单引号&#xff0c;不区分英文的大小写。1.2.3 列明命名…