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

jbehave

行为驱动开发 (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

Give表示初始上下文, 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可以与其他项目共享

Gradle

有了步骤,我们可以从我们最喜欢的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

jbehave

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

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

相关文章

嵌入式 开发——DMA内存到外设

学习目标 加强理解DMA数据传输过程加强掌握DMA的初始化流程掌握DMA数据表查询理解源和目标的配置理解数据传输特点能够动态配置源数据学习内容 需求 串口发送数据 uint8_t data = 0x01; 串口发送(data); 实现串口的发送数据, 要求采用dma的方式 数据交互流程 CPU配置好DM…

XSS

1.什么是xss XSS攻击全称跨站脚本攻击&#xff0c;是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆&#xff0c;故将跨站脚本攻击缩写为XSS&#xff0c;XSS是一种在web应用中的计算机安全漏洞&#xff0c;它允许恶意web用户将代码植入到提供给其它用户使用的页面中…

Python之匿名函数

一、匿名函数&#xff1a;也叫lambda表达式 1.匿名函数的核心&#xff1a;一些简单的需要用函数去解决的问题&#xff0c;匿名函数的函数体只有一行 2.参数可以有多个&#xff0c;用逗号隔开 3.返回值和正常的函数一样可以是任意的数据类型 二、匿名函数练习 请把下面的函数转换…

vaadin_5分钟内Google App Engine上的Vaadin App

vaadin在本教程中&#xff0c;您将学习如何创建第一个Vaadin Web应用程序&#xff0c;如何在本地AppEngine开发服务器上运行它以及如何将其部署到Google App Engine基础结构。 所有这些大约需要5到10分钟。 是的&#xff0c;如果您已经安装了必要的先决条件&#xff0c;则可以立…

【分形】【洛谷P1498】

https://www.luogu.org/problemnew/show/P1498 题目描述 自从到了南蛮之地&#xff0c;孔明不仅把孟获收拾的服服帖帖&#xff0c;而且还发现了不少少数民族的智慧&#xff0c;他发现少数民族的图腾往往有着一种分形的效果&#xff0c;在得到了酋长的传授后&#xff0c;孔明掌握…

linux下杀死进程全权讲解

linux下杀死进程全权讲解 2009-10-27 08:57 佚名 linux 我要评论(0) 字号&#xff1a;T | T本文将详细讲解linux杀死进程的多种命令&#xff0c;包含他们的作用&#xff0c;kill作用&#xff1a;根据进程号杀死进程&#xff1b; killall作用&#xff1a;通过程序的名字&#xf…

Java Process中waitFor()的问题

Java Process中waitFor()的问题 http://yearsaaaa123789.iteye.com/blog/1404865在编写Java程序时&#xff0c;有时候我们需要调用其他的诸如exe,shell这样的程序或脚本。在Java中提供了两种方法来启动其他程序&#xff1a;(1) 使用Runtime的exec()方法(2) 使用ProcessBuilder…

应用程序模块和实体缓存

任何具有ADF业务组件基础知识的ADF开发人员都应该熟悉下图&#xff1a; 它代表运行时ADF业务组件的核心构建块。 有一个包含视图对象实例的根应用程序模块实例。 视图对象实例可能由存储在实体集合或换句话说就是实体缓存中的实体对象备份。 根应用程序模块可能还包含嵌套的应…

kubernetes-dashboard(1.8.3)部署与踩坑

Kubernetes Dashboard 是一个管理Kubernetes集群的全功能Web界面&#xff0c;旨在以UI的方式完全替代命令行工具&#xff08;kubectl 等&#xff09;。 目录 部署创建用户集成Heapster访问 kubectl proxyNodePortAPI ServerIngress部署 Dashboard需要用到k8s.gcr.io/kubernetes…

oracle线程阻塞_Oracle Service Bus –线程阻塞案例研究

oracle线程阻塞本案例研究描述了在AIX 6.1和IBM Java VM 1.6上运行的Oracle Service Bus 11g遇到的线程阻塞问题的完整根本原因分析过程。 本文也是您提高线程转储分析技能的绝佳机会&#xff0c;我强烈建议您学习并正确理解以下分析方法。 它还将展示正确数据收集的重要性&…

Activiti中的安全脚本如何工作

最近的Activiti 5.21.0版本的突出特点之一是“安全脚本”。 Activiti用户指南中详细介绍了启用和使用此功能的方法 。 在这篇文章中&#xff0c;我将向您展示我们如何实现其最终实现以及它在幕后所做的事情。 当然&#xff0c;由于这是我通常的签名风格&#xff0c;因此我们还将…

使用准现网的数据,使用本地的样式脚本,本地调试准现网页面(PC适用)

原理&#xff1a; 本地逻辑&#xff0c;重新渲染 步骤&#xff1a; 1.安装插件&#xff1a;Tampermonkey 度盘&#xff1a;https://pan.baidu.com/s/1bpBVVT9 2.设置&#xff1a; 点击插件-->仪表盘 添加脚本 将此文本文档中的脚本复制到脚本编辑框处&#xff0c;并CtrlS保存…

FDATOOL设计滤波器

FDATOOL设计滤波器 分类&#xff1a; 数字信号处理 2006-04-20 11:251. 在Matlab中键入fdatool运行Filter Design and Analysis Tool。具体使用请参见Matlab Help中的Signal Processing Toolbox->FDATool。 2. 在fdatool工具中应该注意的几个问题&#xff1a;(a)Fstop&#…

大例外背后的真相

异常可能是最被滥用的Java语言功能。 这就是为什么 让我们打破一些神话。 没有牙仙子。 圣诞老人不是真实的。 TODO评论。 finalfinalversion-final.pdf。 无皂肥皂。 而且…例外实际上是例外。 后者可能需要更多说服力&#xff0c;但我们可以帮助您。 在这篇文章中&#xff…

MATLAB里面的filter和filtfilt的C语言源代码

MATLAB里面的filter和filtfilt的C语言源代码 嗯&#xff0c;算法非常简单&#xff0c;就是网上搜不到C代码实现。filter是个很万能的数字滤波器函数&#xff0c;只要有滤波器的差分方程系数&#xff0c;IIR呀FIR呀都能通过它实现。在MATLAB里面&#xff0c;filter最常用的格式是…

20172302『Java程序设计』课程 结对编程练习_四则运算第二周阶段总结

一.结对对象 姓名&#xff1a;周亚杰学号&#xff1a;20172302担任角色&#xff1a;驾驶员&#xff08;周亚杰&#xff09;伙伴第二周博客地址二.本周内容 (一)继续编写上周未完成代码 1.本周继续编写代码&#xff0c;使代码支持分数类计算 2.相关过程截图 a.下图是上周编写的生…

实践中的弹性基础架构

几周前&#xff0c;我获得了一个难得的机会&#xff0c;可以在基础设施领域弄脏双手。 在JVM内部的深入了解下&#xff0c;我每天的工作经历发生了有趣的变化&#xff0c;我想与您分享动机和成果。 希望它可以启发类似的问题类别。 背景 我将从解释需要解决方案的上下文开始。…

notepad++插件实现json、xml格式化

notepad比较出色的免费的数据编辑、格式化工具。。。 现在json、xml文件很流行、格式化也是必须的&#xff0c;方便查看关键信息&#xff01; 01、下载notepad及相关插件 npp_7.5.5-x86&#xff1a; https://files.cnblogs.com/files/xiaochina/npp_7.5.5-x86.zip npp-json:…

ActiveMQ 5.x中的消息持久性

我被问了很多关于ActiveMQ如何存储消息&#xff08;或在某些情况下不存储&#xff09;的基本知识。 这是它的高级解释。 注意&#xff0c;上下文在JMS中。 如果您使用ActiveMQ的非JMS客户端&#xff08;即STOMP&#xff0c;AMQP&#xff0c;MQTT等&#xff09;&#xff0c;则在…

一个select元素自定义设计的新思路:appearance: none之后利用符号制造小箭头

最近工作时解决了一个前端小问题&#xff08;如下图所示&#xff09;&#xff1a;在Safari中&#xff0c;select的控件之上有不和谐的灰色部分。 刚开始时我以为是backgrand或是border设置不当之类产生的问题&#xff0c;在搜索了很久之后终于找到了问题所在&#xff1a;这个灰…