使用JBehave,Gradle和Jenkins的行为驱动开发(BDD)

行为驱动开发 (BDD)是一个协作过程 ,产品负责人,开发人员和测试人员可以合作交付可为企业带来价值的软件。

BDD是 测试驱动开发 (TDD) 的合理下一步 。

行为驱动的发展

本质上,BDD是一种交付需求的方法。 但不仅有任何要求,还包括可执行要求! 使用BDD,您可以以可以针对该软件运行的格式来编写方案 ,以确定该软件是否按预期运行。

情境

场景以“ 给定,何时,然后”格式(也称为Gherkin)编写:

Given the ATM has $250
And my balance is $200
When I withdraw $150
Then the ATM has $100
And my balance is $50

Given表示初始上下文, When表示发生有趣的事件, 然后断言预期的结果。 并且可以用来代替重复的关键字,以使方案更具可读性。

Give / When / Then是一个非常强大的习惯用法 ,几乎可以描述任何要求。 这种格式的场景也很容易解析,因此我们可以自动运行它们。

BDD场景对开发人员非常有用,因为它们提供了有关故事是否完成的快速而明确的反馈。 不仅可以提供主要成功方案,还可以提供替代方案和异常方案 ,如滥用案例 。 后者要求产品负责人不仅要与测试人员和开发人员合作,还要与安全专家合作。 结果是, 管理安全要求变得更加容易。

尽管BDD实际上是关于协作过程的,而不是关于工具的,但在本文的其余部分中,我将专注于工具。 请记住, 工具永远无法挽救您,而沟通和协作则可以 。 消除了这一警告,让我们开始使用一些开源工具来实现BDD。

杰贝夫

JBehave是Java的BDD工具。 它从故事文件中解析场景,将它们映射到Java代码,通过JUnit测试运行它们,并生成报告。

JUnit的

这是我们使用JUnit运行故事的方式:

@RunWith(AnnotatedEmbedderRunner.class)
@UsingEmbedder(embedder = Embedder.class, generateViewAfterStories = true,ignoreFailureInStories = true, ignoreFailureInView = false, verboseFailures = true)
@UsingSteps(instances = { NgisRestSteps.class })
public class StoriesTest extends JUnitStories {@Overrideprotected List<String> storyPaths() {return new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(getClass()).getFile(),Arrays.asList(getStoryFilter(storyPaths)), null);}private String getStoryFilter(String storyPaths) {if (storyPaths == null) {return '*.story';}if (storyPaths.endsWith('.story')) {return storyPaths;}return storyPaths + '.story';}private List<String> specifiedStoryPaths(String storyPaths) {List<String> result = new ArrayList<String>();URI cwd = new File('src/test/resources').toURI();for (String storyPath : storyPaths.split(File.pathSeparator)) {File storyFile = new File(storyPath);if (!storyFile.exists()) {throw new IllegalArgumentException('Story file not found: ' + storyPath);}result.add(cwd.relativize(storyFile.toURI()).toString());}return result;}@Overridepublic Configuration configuration() {return super.configuration().useStoryReporterBuilder(new StoryReporterBuilder().withFormats(Format.XML, Format.STATS, Format.CONSOLE).withRelativeDirectory('../build/jbehave')).usePendingStepStrategy(new FailingUponPendingStep()).useFailureStrategy(new SilentlyAbsorbingFailure());}}

这使用JUnit 4的@RunWith注释指示将运行测试的类。 AnnotatedEmbedderRunner是JBehave提供的JUnit Runner 。 它寻找@UsingEmbedder批注以确定如何运行故事:

  • generateViewAfterStories指示JBehave在运行故事后创建测试报告
  • 当故事失败时, ignoreFailureInStories防止JBehave引发异常。 这对于与Jenkins集成至关重要,如下所示

@UsingSteps批注将方案中的步骤链接到Java代码。 下面的更多内容。 您可以列出多个类别。

我们的测试类重新使用了JBehave的JUnitStories类,这使得运行多个故事变得容易。 我们只需要实现两种方法: storyPaths()configuration()

storyPaths()方法告诉JBehave在哪里找到要运行的故事。 我们的版本有点复杂,因为我们希望能够从IDE和命令行运行测试,并且希望能够运行所有故事或特定子集。

我们使用系统属性bdd.stories指示要运行的故事。 这包括对通配符的支持。 我们的命名约定要求故事文件名以角色开头,因此我们可以使用-Dbdd.stories=wanda_*类的-Dbdd.stories=wanda_*轻松地为单个角色运行所有故事。

configuration()方法告诉JBehave 如何运行故事并对其进行报告 。 我们需要XML输出,以便在Jenkins中进行进一步处理,如下所示。

感兴趣的一件事是报告的位置。 JBehave支持Maven,这很好,但是他们假定每个人都遵循Maven约定,但事实并非如此。 默认情况下,输出进入一个名为target的目录,但是我们可以通过指定相对于target目录的路径来覆盖该目录。 我们使用Gradle代替Maven,并且Gradle的临时文件进入build目录,而不是target 。 有关Gradle的更多信息,请参见下文。

脚步

现在我们可以运行我们的故事,但是它们会失败。 我们需要告诉JBehave如何将场景中的Given / When / Then步骤映射到Java代码。 步骤类确定可以在方案中使用的词汇表。 因此,他们定义了一种用于接受测试我们的应用程序的领域特定语言 (DSL)。

我们的应用程序具有RESTful接口,因此我们编写了通用的REST DSL。 但是,由于REST中的HATEOAS约束,客户端需要大量调用才能发现其应使用的URI。 这样写场景变得很无聊和重复,因此我们在REST DSL之上添加了特定于应用程序的DSL。 这使我们可以用产品负责人理解的术语来编写方案 。

在通用REST步骤之上分层特定于应用程序的步骤具有一些优点:

  • 实施新的特定于应用程序的DSL很容易,因为他们只需要调用REST特定的DSL
  • REST专用的DSL可以与其他项目共享

摇篮

有了步骤,我们可以从我们最喜欢的IDE中运行我们的故事。 这对开发人员来说效果很好,但不能用于持续集成 (CI)。

我们的CI服务器运行无头构建,因此我们需要能够从命令行运行BDD方案。 我们使用Gradle使构建自动化,并且Gradle已经可以运行JUnit测试。 但是,我们的构建是一个多项目构建。 在构建所有项目,创建发行版并启动应用程序之前,我们不希望运行BDD方案。

因此,首先,我们禁止在包含BDD故事的项目上运行测试:

test {onlyIf { false } // We need a running server
}

接下来,我们创建另一个可以在启动应用程序后运行的任务:

task acceptStories(type: Test) {ignoreFailures = truedoFirst {// Need 'target' directory on *nix systems to get any outputfile('target').mkdirs()def filter = System.getProperty('bdd.stories') if (filter == null) {filter = '*'}def stories = sourceSets.test.resources.matching { it.include filter}.asPathsystemProperty('bdd.stories', stories)}
}

在这里,我们看到了Gradle的力量。 我们定义了一个Test类型的新任务,以便它已经可以运行JUnit测试。 接下来,我们使用一些Groovy脚本配置该任务。

首先,我们必须确保target目录存在。 我们不需要甚至不需要它,但是如果没有它,JBehave将无法在* nix系统上正常工作。 我想这有点Maven主义

接下来,再次使用bdd.stories系统属性添加对运行故事子集的支持。 我们的故事文件位于src/test/resources ,因此我们可以使用标准Gradle test 源集轻松访问它们。 然后,我们为运行测试的JVM设置系统属性bdd.stories

詹金斯

现在,我们可以从IDE和命令行运行BDD方案。 下一步是将它们集成到我们的CI版本中。

我们可以将JBehave报告存档为工件,但是,老实说,JBehave生成的报告并不是很好。 幸运的是,JBehave团队还维护了Jenkins CI服务器的插件 。 该插件需要事先安装xUnit插件 。

将xUnit和JBehave插件安装到jenkins中之后,我们可以配置Jenkins作业以使用JBehave插件。 首先,添加xUnit构建后操作。 然后,选择JBehave测试报告。

使用此配置,在我们的BDD故事上运行JBehave的输出看起来像常规单元测试的输出:

请注意,图中的黄色部分表示待处理的步骤。 那些用于BDD场景,但是在Java Steps类中没有。 等待结果显示在测试结果的“ Skip列中:

请注意,JBehave Jenkins插件如何将故事转换为测试,将场景转换为测试方法。 这样可以很容易地发现哪些方案需要更多工作。

尽管JBehave插件运行良好,但是有两点可以改进:

  • 测试的输出未显示。 这使得很难弄清楚场景失败的原因。 因此,我们还存档了JUnit测试报告
  • 如果将ignoreFailureInStories配置为false ,则JBehave会在失败时引发异常,该异常会截断XML输出。 然后,JBehave Jenkins插件将无法再解析XML(因为它的格式不正确),并且会完全失败,从而使您没有测试结果

所有这些都是不便之处,我们对自动化的BDD方案感到非常满意。

祝您编程愉快,别忘了分享!

参考: 安全软件开发博客上来自JCG合作伙伴 Remon Sinnema的JBehave,Gradle和Jenkins的行为驱动开发(BDD) 。


翻译自: https://www.javacodegeeks.com/2012/09/behavior-driven-development-bdd-with.html

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

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

相关文章

Maven Fluido Skin和Javadoc类图

我使用Maven网站已有一段时间了&#xff0c;对此我感到非常满意。 我不想在Maven 3之后更新我的项目&#xff0c;但是没关系&#xff0c;Maven 3带来了许多新奇的东西。 但是&#xff0c;有两件事使我感到烦恼&#xff1a;缺乏美观和现代的外观&#xff0c;以及浏览复杂代码的J…

咸宁省2021年模拟高考成绩查询怎么查,2021咸宁市地区高考成绩排名查询,咸宁市高考各高中成绩喜报榜单...

距离2018年高考还有不到一个月的时间了&#xff0c;很多人在准备最后冲刺的同时&#xff0c;也在关心高考成绩。2018各地区高考成绩排名查询,高考各高中成绩喜报榜单尚未公布&#xff0c;下面是往年各地区高考成绩排名查询,高考各高中成绩喜报榜单&#xff0c;想要了解同学可以…

国际旅游管理专业跨专业考计算机,旅游管理考研我想跨专业考旅游管理专业的研究 – 手机爱问...

2005-12-11我是学旅游管理的大一学生,听人说这专业就这位兄弟提出的苦恼在大学生中很典型呀!其实你说的不尽然!旅游管理专业,是个很有前景的专业呀!怎么会没有前途呀?你对自己的人生也太悲观了吧?就是你说,学校不太好,这可能对自身在大学四年的发展有所限制,但这主要还是看自…

java基础03变量和基本数据类型

package cn.bdqn.test;/*** * author 小豆腐* * 变量&#xff1a;会变化的量&#xff1f;&#xff1f;* 一个数据在内存中存储空间的表示&#xff01;在运行期间可以动态改变&#xff01;* * 关键字:在java中已经被使用或者定义的单词&#xff01;不能作为变量名&#xff01…

JavaFX中基于表达式的PathTransitions

在JavaFX中&#xff0c;您可以使用PathTransition对象为路径上的节点设置动画。 PathTransitions使用Shape对象描述它们需要沿其动画的路径。 JavaFX提供了各种类型的形状&#xff08;例如&#xff0c;多边形&#xff0c;圆形&#xff0c;多边形&#xff0c;路径&#xff09;。…

html 显示视频列表,dvd光碟制作节目轨菜单布局,不要视频缩略图,只显示文件列表...

“如何在刻录视频光盘时自定义制作菜单&#xff1f;实现的效果就是当光盘插入DVD影碟机播放时&#xff0c;首先会出现一个所有视频文件列表的菜单(节目轨菜单)&#xff0c;就相似于音乐CD曲目表一样&#xff0c;不需要有视频缩略图&#xff0c;可通过遥控器选择性播放列表中某一…

v3学院教你学习-task和function的异同

v3学院教你学习-task和function的异同 task&#xff08;任务&#xff09;与function&#xff08;函数&#xff09;的不同 任务与函数主要有以下四点不同&#xff1a; l 函数只能与主模块共用一个仿真时间单位&#xff0c;而任务定义自己的仿真时间单位。 l 函数不能启动任务&am…

Java 7:HashMap与ConcurrentHashMap

从我过去有关性能的文章和HashMap案例研究中可能已经看到&#xff0c;Java线程安全性问题可以很轻松地使Java EE应用程序和Java EE容器崩溃。 在对Java EE性能问题进行故障排除时&#xff0c;我观察到的最常见问题之一是由非线程安全的HashMap get&#xff08;&#xff09;和pu…

【2017-03-02】集合、结构体、枚举

集合和数组的差别&#xff1a; 数组&#xff1a;同一类型&#xff0c;固定长度集合&#xff1a;不同类型&#xff0c;不固定长度 一、普通集合&#xff08;弱类型&#xff09; 1、ArryList 使用集合首先要引用命名空间。 或者在ArryList上右键找“解析”。 2、集合的定义&#…

Mathematica图片局部变色

这篇博客来源于Stack-Exchange上的一个帖子&#xff0c;问题描述如下&#xff1a;如何将图中的红球变为蓝球&#xff1f; 这个问题下面有很多答案&#xff0c;我选了最好的一个答案&#xff0c;代码如下 img Import["C:/Users/1/Desktop/red.jpg"]; getReds[x_Image…

在WebLogic 12c上运行RichFaces

我最初以为我可以在几个月前写这篇文章。 但是我最终被不一样的事情所淹没。 其中之一是&#xff0c;它无法像我在4.0版本中那样简单地启动RichFaces展示柜。 有了所有的JMS magic和不同的提供者检查&#xff0c;这已经成为简单构建和部署它的挑战。 无论如何&#xff0c;我愿意…

Spring Boot系列教程一:Eclipse安装spring-tool-suite插件

一.前言 一直使用eclipse&#xff0c;个人习惯选用Eclipsespring-tool-suite进行开发&#xff0c;特别注意Eclipse要选用对应的spring-tool-suite进行安装&#xff0c;这点笔者浪费了好长时间&#xff0c;以下为对应的版本。eclipse-kepler.4.3.1–>springsource-tool-suite…

湖南工程学院计算机网络考试,湖南工程学院 计算机网络期末试卷试题

湖南工程学院 计算机网络期末试卷试题湖南工程学院 计算机网络 期末试题(计算机10级&#xff0c;90%的题目)1 从逻辑功能上看,计算机网络可分为哪两个子网?答&#xff1a;通信子网和资源子网 2 数据链路层的最基本功能答&#xff1a;数据链路层的最基本的功能是向该层用户提供…

C#设计模式(11)——外观模式(Facade Pattern)

一、引言 在软件开发过程中&#xff0c;客户端程序经常会与复杂系统的内部子系统进行耦合&#xff0c;从而导致客户端程序随着子系统的变化而变化&#xff0c;然而为了将复杂系统的内部子系统与客户端之间的依赖解耦&#xff0c;从而就有了外观模式&#xff0c;也称作 ”门面“…

OS X Mountain Lion上的多个Java版本

在Mountain Lion之前&#xff0c;Java被捆绑在OS X中。似乎在升级期间&#xff0c;我在计算机上安装的Java 6版本被删除了。 显然&#xff0c;在升级过程中卸载Java的原因是Java运行时存在的安全问题。通过这种方式&#xff0c;您不得不安装可解决此安全问题的最新版本。 所以我…

2020暨阳学院园林计算机考研考场,【图片】2020考研,老学长教你如何规划!【计算机考研吧】_百度贴吧...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼二、关键一步——院校选择我把各位同学的院校选择阶段分为以上几个阶段&#xff0c;因为考研这一年中&#xff0c;很多人的目标院校并不是固定不变的&#xff0c;而是随着不同阶段而改变的。学长我在大三下学期这一时间段内也多次更…

JavaOne 2012:向上,向上和向外:使用Akka扩展软件

在最后的社区主题演讲后&#xff0c;我前往希尔顿金门大桥3/4/5观看了维克多巴生 &#xff08; Viktor Klang &#xff09;的&#xff08; Typesafe &#xff09;“上&#xff0c;下&#xff0c;外&#xff1a;Akka”演讲。 巴生&#xff08;Klang&#xff09;是Akka的技术主管…

Spring测试支持和上下文缓存

Spring为单元测试和集成测试提供了全面的支持-通过注释来加载Spring应用程序上下文&#xff0c;并与JUnit和TestNG等单元测试框架集成。 由于为每个测试加载大型应用程序上下文需要时间&#xff0c;因此Spring智能地为测试套件缓存应用程序上下文–通常&#xff0c;当我们通过a…

perl6正则 4: before / after 代码断言: ?{} / !{}

<?before> <? befor XXX> 某字符在 xxx 之前 <?after > <?after XXX> 某字符之后有XXX 对应的取反分别为: <!before > <!before XXX> XXX之前没有 <!after> <!after xxx> 某字符后面不是 xxx say "foobar" ~~…

如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)

转载&#xff1a;http://www.cnblogs.com/codeon/p/6123863.html 上篇文章说到接口安全的设计思路&#xff0c;如果没有看到上篇博客&#xff0c;建议看完再来看这个。 通过园友们的讨论&#xff0c;以及我自己查了些资料&#xff0c;然后对接口安全做一个相对完善的总结&#…