Jbehave学习
JBehave行为驱动开发(BDD)是一个框架。BDD是测试驱动开发(TDD)和验收
测试驱动开发(ATDD)的一种演进,目的是使新手和专家开发实践起来更加方便
和直观。它改变了从被测试为基础到以行为为基础的词汇,将自己定位为一个设
计理念。
一、BDD课题研究之测试思想和方法总结
此次研究的课题是BDD,主要涉及两个方面:测试的思想和方法、技术框架。
这里做测试思想和方法的总结。
BDD是什么
全称:BehaviourDrivenDevelopment(行为驱动开发)。
BDD改变了我们对软件测试的认识。先前我对测试的认识是:从大的角度来讲,
软件测试就是对一个软件系统从功能上进行确认测试和验证测试,从性能上进行
压力测试和负载测试,以及对系统的配置测试和兼容性测试等,从类别上又有单
元测试,集成测试,回归测试,所有的这些测试工作都有一个目的:交付一套高
质量的软件系统。我们软件测试人员的工作就是:尽可能早的找出软件缺陷,
并确保其得以修复。顺理成章的,在我们的思维中是:我们先拿到系统的既成品,
然后开展测试工作,而BDD恰好颠覆了我们的思维。
回到BDD正题,BDD中有两个大的概念:测试先行和系统设计。
测试先行:BDD提倡我们在开发者的编码工作开展之前,先写测试用例,然后
由测试来推动着开发的工作,具体解释为:在设计如何实现一个功能前,先考虑
如何测试这个功能,测试的代码完成后,再编写功能实现代码,并且使得该测试
用例通过,即完成了系统的一个功能模块。
系统设计:在系统功能实现代码编写之前,我们需要先编写测试代码,在我
们的测试代码中实现对系统行为的描述,这个描述其实就是用一种接近自然语言
的方式对系统进行详细的设计,并且使项目相关人员,即使是非技术人员也能
很容易看懂。关于系统行为,举例说明:用户在一个特定的条件下对系统做请求,
系统在该条件下做什么样的处理,这就是系统的一个行为。
总结一下BDD的概念:在项目之初,由客户、开发人员、测试人员一起通过
充分的沟通对系统的行为进行设计,由测试人员以接近自然语言的方式编写可以
描述系统行为的测试用例,然后由开发人员编写相关的实现代码,并确保该测
试用例通过。循环这个过程实现整个系统的功能。
BDD的测试思想
先前在写日报的过程中,以关键字的形式来描述,这里用同样的方式来表达。
关键字:TDD,代码即文档,系统设计,合作。
全称:TestDrivenDevelopment(测试驱动开发)。
BDD是基于TDD发展起来的,BDD中测试先行的理念也是来自于TDD,测试驱
动开发,由测试来推动着开发的工作,在具体的项目实施中,测试的工作先行,
在功能代码编写前,先编写测试代码,再编写功能实现代码,并且使得该测试用
例测试通过,循环这个过程,来实现系统的其他功能。在一个项目的开发过程中,
针对于每一个阶段,都可用TDD的思想来开展工作。
BDD对TDD理念进行了扩展。TDD要求用测试来驱动开发,其重点偏向开发,
测试用例是在约束开发者,使开发者的目标明确,设计出满足需求的系统。BDD
要求在设计测试用例时对系统进行定义,倡导我们在测试用例中用通用语言把系
统的行为描述出来,把测试代码作为系统的定义文档,将系统的设计和测试用例
结合起来,进而驱动开发工作。
2.代码即文档
很多软件项目的失败源于项目团队人员对文档理解的差错。文档用来约束一个
项目团队成员,使得大家的目标保持一致,总之:文档很重要。
我们用需求文档管理需求,但是这些文档本身都因为容易变更,加上团队人员
主观上的理有误,最终做出不能满足产品需求的产品。
BDD的思想是:将我们的产品设计写在我们的测试用例中。把传统的产品说
明书的内容写在测试用例中,在测试用例中描述软件系统的具体行为,体现着系
统的设计,而且这是一份“活”的的文档,因为这是可以运行的测试用例,我
们由这些测试用例来驱动开发者的编码工作,开发者必须使这个测试用例通过,
才算满足最基本工作。假如用例不通过,显然我们的系统就存在缺陷,没有满
足用户的需求。这样,就算是开发人员对文档理解有误,也会满足系统的需求。
3.系统设计
在测试用例中描述系统的行为,体现出系统的每一步操作所带动相关事件的触
发,进而得到相关的结果,这是对一个产品详细的定义,也就要求我们在测试用
例中对系统的行为做出详细的设计。
4.合作
客户,需求分析人员,测试人员,和开发人员之间的合作,这个合作时间较
集中在项目的开始阶段,大家一起对系统的行为进行定义,测试发展起步较晚,
到现在开发人员还是有很多不重视测试,再加上测试人员的工作是找出他们代
码中存在的bug,所以开发人员和测试人员需要很多的相互沟通理解,处理好关
系,这样的合作,无疑提供给我们交流很大的一个空间。
BDD的测试方法
关键字:故事&场景,通用语言。
1.故事&场景
一个故事描述了系统的一个行为,对应着用户的一个需求。举例说明:外部
开发者开发好的应用经过小二的审核后发布在淘宝开发平台的服务平台上面,供
用户订购使用。现在有一个用户要访问一个应用,此时就发生了一个故事,用
户访问应用要经过top-container应用容器的校验,这个故事中描述了
top-Container做校验的行为。
在一个故事中又会有多个不同的场景。用户访问应用时,用户和应用之间有很
多种条件需要满足,每一种不同的情况都对应着一个场景。举例说明:用户在没
有订购此应用,并且此应用恰好又需要订购才能够访问,这种情况下,
top-Container拒绝其访问;再比如,用户没有订购过这个应用,此应用是一个
基础应用不需要用户订购,这种情况下,top-Container容许其访问。
故事和场景的作用就是定位,故事定位要描述系统的功能模块,场景定位要描
述该功能模块下哪种条件下的系统行为。
2.通用语言
语言是用于沟通,向别人表达自己的意思的工具,我们的基于BDD的测试用
例的代码描述着系统的一个行为,可以按照传统的写法将这个行为描述清楚,但
是别人来看时,肯定要花不少的精力。所以BDD提供一个通用的模板,并且要
客户,开发人员和测试人员一起定义一套通用语言来做描述,这样做,既可以方
便测试人员自己写测试代码,也能方便别人看懂,也可以为开发人员的实现代
码提供类名,方法名。
3.示例
通用模板示例:
Story:标题(描述故事)
Asa[角色]
Iwant[特征]
Sothat[利益]
Scenario1:标题(描述场景)
Given[上下文]
And[其他上下文]...
When[事件]
Then[结果]
And[其他结果]
举例说明:
Story:用户访问应用
Asa用户
Iwant访问淘宝开放平台的一个应用
Sothat我可以使用这个应用提供的服务
Scenario1:用户未订购此应用
Given一个应用
And此应用需要订购才能访问
And用户没有订购此应用
When该用户访问此应用
Then访问被拒绝
And返回用户没有订购此应用的错误码及错误信息。
BDD的优势
1.代码即文档,由测试用例管理需求,最大限度的消除项目团队人员对需求理解
不一致。
2.由测试代码监督,约束着开发代码。开发者需要时刻考虑去满足测试的需要。
这样使得开发者的代码保持着方向的正确性,也使开发者的代码足够的精练,产
生较少的垃圾代码。
3.开发者需要设计良好定义的接口,来满足测试的需要,降低系统模块的耦合度。
4.有测试用例的保障,系统代码可以放心的重构。
5.增强开发者的信心。一个测试用例的通过标志着系统一个需求的实现,这样的
成果可以增加开发者的成就感与信心。
BDD的缺点
1.测试用例只能体现系统细节设计,不能体现系统总体设计。
2.测试用例无法覆盖全部的测试工作。
3.约束开发者的发挥,开发者需要时刻考虑能否满足系统行为,能否使测试用例
通过,这样会局限创造力。
4.项目初期在测试方面投入过多,引起开发人员的不满。这一点上尤其对于新近
实行TDD理念的团队来说,这方面的怀疑更多。
总结
BDD基于TDD发展起来,具有很好的实践基础,并且越来越多的人开始接触并
且接受其的测试理念,受到了很多人的热捧。
个人认为,我们可以在小范围内用BDD的方式来开展项目开发工作,然后看效
果,调整成为最符合我们公司开发需要的方式,进而推广。
在我们的日常测试中,我们也可以借鉴其系统设计的概念,将我们的测试用
例设计成可以体现系统行为的风格,这样做的好处有两点,一是方便维护,别人
一看就懂得我们的测试用例的校验点在哪里;二是方便我们定位问题,导致用
例不通过的原因是系统的哪一步处理出错,不需要我们调试跟踪就直接看出来,
可以节约我们大量的时间。
最后,用一个博友的话来总结BDD:优美的测试代码,就是一个个优美的故事。
也用一句话说出我们所有测试人员的心声:我不做软件,但我使软件变得更好!
二、BDD课题研究之jbehave介绍
1、什么是JBehave
JBehave是一个用java编写的BDD(Behavior-Driven-Design)框架,java界
的Cucumber。(注:1、BDD主要的目的是能够从业务领域专家的视角来编写测试
用例,以解决技术人员和业务领域专家的沟通问题。2、Cucumber是基于Ruby
的BDD框架)
2、JBehave的特点
1)、纯Java实现,能调用javaAPI的地方就能使用。
2)、能够定义和执行基于文本的Story,让我们能够从用户价值出发进行开发。
(BDD都是这个目的)。
3)、Urstories可以放在classpath,也可通过外部URL传进来。
4)、Urstories可以并发执行且能够指定并发执行的线程数。
5)、可以通过一些用户定义的信息把UrStories形成一部完整文档。
6)、通过Anotation把Story的步骤对应到Java类中,还能够把自动把Story
中的String参数转换成方法对应的参数类型。(How?)
7)、基于Anotation的运行配置信息,指定Story对应的Steps类文件
8)、支持通过第三方IOC容器(Spring,Guice,PicoContainer,Weld)管理
配置信息和Steps类
9)、支持通过Groovy写配置信息和Steps文件
10)、支持报表,既可以生成可读性良好的报表格式(HTML,TXT),还支持
Json,XML格式供外部程序调用。
11)、未实现的步骤会自动标记Pending
12)、支持任何语言书写Story
13)、可以使用Junit或者任何基于anotation的测试框架运行Story测试
14)、支持Maven,Ant集成,通过脚本运行BDD测试脚本。
3、JBehave的结构
Story:系统想要具有的功能
Scenario:Story描述的功能的Key-Example。插一句,如果一个功能你不能想
出一个很好的例子,那么你就需要好好想想这个功能的价值了。个人感觉,此处
借用了《SpecificationByExamples》的思想,以实例说明功能更容易让人理
解。
Steps:Scenario中描述的实例的具体执行步骤。
4、JBehave的语法
下面就是一个JBehavestory的例子
Story代码
:
2.@categorybasic
3.@colorblue
4.
ive:
6.
rtoshowthebasiccartfunctionality
r
oaddandremoveitemsfromthecart
10.
io:Itemcanbeaddedtocart
12.
hatthecartimpty
14.!--Wedon'tcareforwhichitemisaddedtothecart
earchforanitem
temisaddedtothecart
ecartcontainsthatitem
18.
io:Itemcanberemovedfromcart
20.
hecartcontainsoneitem
eitemisremoved
ecartcontentsimpty
上面的例子中基本上涵盖了JBehave的所有关键字(标红的词语就是JBehave
的关键字)
Meta:以键值对的方式提供一些关于Story和Scenario的标签信息,我们在运行
Story的时候,可以通过这些标签作为过滤项,只运行我们想运行的信息。
Narrative:对当前Story对应功能的一个描述,和一般Story卡上的描述差不
多,Inorderto„.,Asa„„,Iwantto„„。
Scenario:关于当前场景的描述
Given:描述当前场景的Context的Step
!--:JBehave中的注释符
When:描述用户进行操作的Step
Then:描述验收用户操作结果的Step,
And:Step的辅助描述关键字,跟着哪个Step就表示哪个Step的意思,如跟
着When后面就表示When。
另外这个例子中未提到的关键字还有:
GivenStories:在当前Story中依赖另一个Story。
Examples:可以指定一系列的数据反复跑一个Scenario。
5、一个JBehave的BDD测试的实现步骤
1)、配置JBehave开发环境
2)、按照上面的语法和业务领域专家一起写文本Story。
3)、把文本Story对应到具体执行的java文件中(通过java的Anotation技
术)
4)、配置JBehave的运行规则。
5)、运行测试
6)、查看测试报告
三、BDD课题研究之jbehave实战
1、配置JBehave环境。
1)、添加JBehave依赖包,基本的只需要添加jbehave-core和Junit包就足够了。
2)、配置IntelliJ的JBehave插件,详情参见
/kumaraman21/IntelliJBehave/wiki
2、实现一个JBehave的Story基本过程
JBahave的测试用例主要由3部分组成,描述测试功能的story文件,story文件对应的
Steps类和基于Junit的运行配置文件。Steps类是通过Anotation和正则匹配技术把story
文件中的文本Step对应到Steps类中的方法,运行配置文件的主要作用是告诉junit去哪儿
找story文件和Steps文件,把其配置在同一个Context中。实现一个story的基本过程如
下:
1)、写Story
Story代码
:
2.
ive:
r
operformanaction
Icanachieveabusinessgoal
7.
io:traderisnotalertedbelowthreshold
9.
stockofsymbolSTK1andathresholdof10.0
estockistradedat5.0
ealertstatusshouldbeOFF
13.
io:traderisalertedabovethreshold
15.
stockofsymbolSTK1andathresholdof10.0
estockistradedat11.0
ealertstatusshouldbeON
2)、写Story对应的Steps类
Java代码1
classTraderSteps{//look,Ma,I'maPOJO!!
2.
eStockstock;
4.
5.@Given("astockofsymbol$symbolandathresholdof$threshold")
voidStock(@Named("symbol")Stringsymbol,@Named("threshold")
doublethreshold){
n("123");
=newStock(symbol,threshold);
9.}
10.
11.@When("thestockistradedat$price")
voidtheStockIsTradedAt(doubleprice){
t(price);
14.}
15.
16.@Then("thealertstatusshouldbe$status")
voidtheAlertStatusShouldBe(Stringstatus){
18.//asrtThat((tus().name()),equalTo(status));
n(status);
20.}
21.
22.}
Java代码2
classStock{
Stock(Stringsymbol,doublethreshold){
n("test1:"+symbol+","+threshold);
4.//TochangebodyofcreatedmethodsuFile|Settings|FileTemplat
es.
5.}
6.
voidtradeAt(doubleprice){
n("test2:"+price);
9.//TochangebodyofcreatedmethodsuFile|Settings|FileTemplates.
10.}
11.
ergetStatus(){
null;//TochangebodyofcreatedmethodsuFile|Settings
|FileTemplates.
14.}
15.}
16.
3)、配置运行环境
Java代码
classTraderStoryextendsJUnitStory{
2.
tedList
newStoryFinder().findPaths(tThread().getContextClassLo
ader().getResource(""),"**/*.story","");
5.}
6.
7.@Override
Configurationconfiguration(){
newMostUfulConfiguration().uStoryLoader(newLoadFromClasspath(t
ss()))
10..uStoryReporterBuilder(newStoryReporterBuilder()
11..withCodeLocation(cationFromClass(s
s()))
12..withDefaultFormats().withFormats(CONSOLE,HTML).withFailureTrace(t
rue)
13..withFailureTraceCompression(true));
14.
15.}
16.
17.@Test
voidrun()throwsThrowable{
19.//这个是我自己加的监听器。
20.//Set
21.//for(Class<?>clazz:cls){
22.//if(tationPrent()){
23.//er((StoryListener)tance());
24.//}
25.//}
26.//ryThreads()这是我自己定义在配置文件的线程数,可以通过非注解
来控制线程数
erembedder=configuredEmbedder();
28.//erControls().uThreads(1);
{
riesAsPaths(storyPaths());
31.}finally{
teCrossReference();
33.}
34.}
35.
36.@Override
InjectableStepsFactorystepsFactory(){
38.//AutoStep我自己定义的动作。
newInstanceStepsFactory(configuration(),newTraderSteps());
40.}
41.}
4)、执行结果,执行TraderStory类,即可得到运行结果。
本文发布于:2022-11-26 08:19:30,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/23925.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |