开发人员看测试之细说JBehave

上篇我们说到如何从Github上clone出一个JBehave项目,既是为了学习JBehava,也是为了熟悉下Github
从clone下来的项目看来,基本没什么问题,稍微捋一捋就可以运行,但是就clone下来的代码来看,自己还是遇到一个问题(不知道是代码问题,还是我自己的操作有问题),就是没有办法运行(后面会详说)。
正如上篇所说,构建一个JBehave的应用的5大步骤:

  1. Write story
  2. Map steps to Java
  3. Configure Stories
  4. Run Stories
  5. View Reports

这里,我们结合clone下来的项目分别对应这五个步骤了解JBehave是如何运行的并完成测试的。
1.Write story,设定一个story,给出一个情景,使用通用语言进行表示,不管是开发或是非开发的都能看懂
本项目有两个测试案例,一个是模拟登录的story:

loginYahoo.story:
Narrative: 

In order to show the yahoo function
As a user
I want to login yahoo

Scenario: normal login

Given yahoo login address by.bouncer.login.yahoo.com
Then print successful

  

另一个是模拟浏览的story:

TestStroies.story:
Browse Etsy.com

Meta:
@category browsing
@color red

Narrative: 

In order to show the browsing cart functionality
As a user
I want to browse in a gallery

Scenario: Browsing around the site for items

Given I am on localhost
Then print hello world

!--Examples:
!--|host|hello|
!--|localhost|hello world|
!--|www.baidu.com|hello baidu|

  

2.Map steps to Java, 将上述的每个story细分成每一个step,给出Given条件,则会得到Then的结果,从而将通用语言转换成可以通过代码逻辑描述的问题
loginYahoo.story对应的steps类TestLogin.java:

public class TestLogin {
		@Given("yahoo login address $url")
		public void getHostPage(String url){
			System.out.println("++++++++++++++++++++++++++++++"+url);
		}

		@Then("print $successful")
		public void hello(String successful){
			System.out.println("++++++++++++++++++++++++++++++"+successful);
		}
}

  

TestStories.story对应的steps类TestStep.java:

public class TestStep {
	@Given("I am on $host")
	public void getHostPage(String host){
		System.out.println("----------------------"+host);
	}

	@Then("print $hello")
	public void hello(String hello){
		System.out.println("----------------------"+hello);
	}
}

  

3.Configure Stories 配置一些映射关系,比如如何找到并加载story文件等

public class EmbedderBase extends Embedder{

	@Override
    public EmbedderControls embedderControls() {
        return new EmbedderControls().doIgnoreFailureInStories(true).doIgnoreFailureInView(true);
    }

	@Override
    public  Configuration configuration() {
        Class<? extends EmbedderBase> embedderClass = this.getClass();
      //MostUsefulConfiguration使用默认的配置
        return new MostUsefulConfiguration()
        	//设置story文件的加载路径
            .useStoryLoader(new LoadFromClasspath(embedderClass.getClassLoader()))
            //设定生成报告的相关配置
            .useStoryReporterBuilder(new StoryReporterBuilder()
                .withCodeLocation(CodeLocations.codeLocationFromClass(embedderClass))
                .withFormats(Format.CONSOLE, Format.TXT)
                .withCrossReference(new CrossReference()))
             //设定相关参数的转换
            .useParameterConverters(new ParameterConverters()
                    .addConverters(new DateConverter(new SimpleDateFormat("yyyy-MM-dd")))) // use custom date pattern
            .useStepMonitor(new SilentStepMonitor());
    }
}

  

4.Run Stories

public class TraderStoryRunner {
	@Test(groups={"test"})
    public void runClasspathLoadedStoriesAsJUnit() {
        // Embedder defines the configuration and candidate steps
        Embedder embedder = new TestStories();
        List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/TestStories.story",""); // use StoryFinder to look up paths
        embedder.runStoriesAsPaths(storyPaths);
    }
	@Test(groups={"test"})
    public void runClasspathLoadedStories() {
        // Embedder defines the configuration and candidate steps
        Embedder embedder = new loginYahoo();
        List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/loginYahoo.story",""); // use StoryFinder to look up paths
        embedder.runStoriesAsPaths(storyPaths);
    }
}

  

这里可以看出,声明了两个类TestStories和loginYahoo。
TestStories.java

public class TestStories extends EmbedderBase {

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new InstanceStepsFactory(configuration(), new TestStep());//设定需要映射的step类
    }

}

  

loginYahoo.java:

public class loginYahoo extends EmbedderBase {

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new InstanceStepsFactory(configuration(), new TestLogin());//设定需要映射的step类
    }

}

  

这两个类是一个桥梁的作用,用于设定从story到step的映射,注意这里的两个类是继承类EmbedderBase的,而EmbedderBase类又是Embedder的子类

这是项目给出的测试类TraderStoryRunner,但是这里有一个问题,就是没有找到运行的入口,点击右键,除了一些maven的操作,并没有其他可以运行的指标,比如junit。
所以通过摸索,按照自己的方法,发现首先要做的就是添加junit测试库,这是必须的。具体步骤:
右键项目->Build path->Configured build path

打开对话框,选择Libraries->Add Library->JUnit,点击next,选择junit4->finished。

添加完Junit后,新建一个Junit测试类

将TraderStoryRunner类的主体方法放进去,命名为Tc.java

import static org.junit.Assert.*;
import java.util.List;
import org.jbehave.core.embedder.Embedder;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.StoryFinder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.story.TestStories;
import com.story.loginYahoo;
public class Tc {
 @BeforeClass
 public static void setUpBeforeClass() throws Exception {
 }
 @AfterClass
 public static void tearDownAfterClass() throws Exception {
 }
 @Before
 public void setUp() throws Exception {
 }
 @After
 public void tearDown() throws Exception {
 }

 // @Test : 表示这是一个测试用例,只有标识了改符号的函数才会被执行测试

 @Test
 public void runClasspathLoadedStoriesAsJUnit() {
     // Embedder defines the configuration and candidate steps
     Embedder embedder = new TestStories();
     List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/TestStories.story",""); // use StoryFinder to look up paths
     embedder.runStoriesAsPaths(storyPaths);
 }
	@Test
 public void runClasspathLoadedStories() {
     // Embedder defines the configuration and candidate steps
     Embedder embedder = new loginYahoo();
     List<String> storyPaths = new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(this.getClass()),"**/loginYahoo.story",""); // use StoryFinder to look up paths
     embedder.runStoriesAsPaths(storyPaths);
 }
}

至此,这个项目是可以运行起来了。

5.5.View Reports
点击运行上面的Tc.java类,可以得到:

Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=300,threads=1]

(BeforeStories)

Running story com/story/TestStories.story
Narrative:
In order to show the browsing cart functionality
As a user
I want to browse in a gallery
Browse Etsy.com
(com/story/TestStories.story)
Meta:
@category browsing
@color red

Scenario: Browsing around the site for items
----------------------localhost
Given I am on localhost
----------------------hello world

!--Examples:
!--|host|hello|
!--|localhost|hello world|
!--|www.baidu.com|hello baidu|
Then print hello world

!--Examples:
!--|host|hello|
!--|localhost|hello world|
!--|www.baidu.com|hello baidu|

(AfterStories)

Generating reports view to ‘C:\Program Files (x86)\Git\Jbehave\TestBehave_v2_testng\target\jbehave‘ using formats ‘[console, txt]‘ and view properties ‘{defaultFormats=stats, decorateNonHtml=true, viewDirectory=view, decorated=ftl/jbehave-report-decorated.ftl, reports=ftl/jbehave-reports-with-totals.ftl, maps=ftl/jbehave-maps.ftl, navigator=ftl/jbehave-navigator.ftl, views=ftl/jbehave-views.ftl, nonDecorated=ftl/jbehave-report-non-decorated.ftl}‘
Reports view generated with 0 stories (of which 0 pending) containing 0 scenarios (of which 0 pending)
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=300,threads=1]

(BeforeStories)

Running story com/story/loginYahoo.story
Narrative:
In order to show the yahoo function
As a user
I want to login yahoo

(com/story/loginYahoo.story)
Scenario: normal login
++++++++++++++++++++++++++++++by.bouncer.login.yahoo.com
Given yahoo login address by.bouncer.login.yahoo.com
++++++++++++++++++++++++++++++successful
Then print successful

(AfterStories)

Generating reports view to ‘C:\Program Files (x86)\Git\Jbehave\TestBehave_v2_testng\target\jbehave‘ using formats ‘[console, txt]‘ and view properties ‘{defaultFormats=stats, decorateNonHtml=true, viewDirectory=view, decorated=ftl/jbehave-report-decorated.ftl, reports=ftl/jbehave-reports-with-totals.ftl, maps=ftl/jbehave-maps.ftl, navigator=ftl/jbehave-navigator.ftl, views=ftl/jbehave-views.ftl, nonDecorated=ftl/jbehave-report-non-decorated.ftl}‘
Reports view generated with 0 stories (of which 0 pending) containing 0 scenarios (of which 0 pending)

 大体的思路,是将story和step对应起来,将story中的条件、参数传入step对应的类中,如果满足则通过测试,得到then给出的结果,否则得不到理想的结果。

  如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

  
时间: 2024-11-06 10:07:30

开发人员看测试之细说JBehave的相关文章

开发人员看测试之TDD和BDD

前言: 已经数月没有来园子了,写博客贵在坚持,一旦松懈了,断掉了,就很难再拾起来.但是每每看到自己博客里的博文的浏览量每天都在增加,都在无形当中给了我继续写博客的动力.最近这两天有听到Jbehave这个名词,上网查了一通,原来是和测试相关的,之前一直做开发,没有做过真正意义上的测试,对于测试的理解更是少之又少.通过这两天的查阅,现将自己的一些理解以及常见概念罗列出来. 正文: Behavior Driven Development,行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者.

开发人员看测试之运行Github中的JBehave项目

本文要阐述的主要有两点,一是介绍自动化测试框架JBehave,二是介绍如何在Github上拉项目,编译成myeclipse环境中的项目,并最终导入Myeclipse中运行. JBehave是何物? JBehave是基于BDD框架的开源自动化测试框架.提供Web集成的BDD层扩展. JBehave特征: JBehave是纯Java实现,可以利用Java丰富的API为己所用: 具有基于文本的story,可以对其进行定义并执行,比较灵活和易扩展: 基于注解(Annotation)的运行配置信息,指定s

写给Android App开发人员看的Android底层知识(2)

(五)AMS 如果站在四大组件的角度来看,AMS就是Binder中的Server. AMS全称是ActivityManagerService,看字面意思是管理Activity的,但其实四大组件都归它管.估计是Android底层开发人员先写了ActivityManagerService用来管理Activity,后来写Service.Receiver.CP的时候发现代码都差不多,于是就全都用ActivityManagerService,但是却忘记改名字了——我也是猜的,纯属八卦. 由此而说到了插件化

写给Android App开发人员看的Android底层知识(6)

(十一)BroadcastReceiver BroadcastReceiver,也就是广播,简称Receiver. 很多App开发人员表示,从来没用过Receiver.其实吧,对于音乐播放类App,用Service和Receiver还是蛮多的,如果你用过QQ音乐,App退到后台,音乐照样播放不会停止,这就是你写的Service在后台起作用. 在前台的Activity,点击停止按钮,就会给后台Service发送一个Receiver,通知它停止播放音乐:点击播放按钮,仍然是发送这个Receiver,

推荐开发人员看的较有影响力的书籍

转载:http://blog.csdn.net/crzy_sparrow/article/details/7422962 对于一个程序员而言,在学校里学不到多少工作中真正需要的知识,只有在工作中实践积累并且看一些优秀的书籍,把实践和理论结合起来才能够更好的工作.尤其是在技术日益发展和变化的今天,每个开发者更应该主动的看书去学习编程技巧并且改变编程方法,才能应付工作中各种复杂的项目.同时也可以在程序设计中更高效.弹性和准确的解决问题.下面列出了 11 本对开发人员很有益的书籍,大家可以从中选取感兴

写给Android App开发人员看的Android底层知识(8)

(十)PMS及App安装过程 PMS,全称PackageManagerService,是用来获取Apk包的信息的. 在前面分析四大组件与AMS通信的时候,我们介绍过,AMS总是会使用PMS加载包的信息,将其封装在LoadedApk这个类对象中,然后我们就可以从中取出在manifest声明的四大组件信息了. (一) 在下载并安装App的过程,会把Apk存放在data/app目录下. Apk是一个zip压缩包,在文件头会记录压缩包的大小,所以后续在文件尾巴就算是追加一部小电影,也不会对解压造成影响—

《写给Web开发人员看的HTML5教程》

周末了!在家里敲作业,主要是html表格的练习. 我发现当有人问你问题时,我会很有动力学习. 为了很好回答他人的问题,我想我要学得更多,比如预习复习. 同时,被人问题也是一件很开心的事儿,这表示别人认同你,觉得你有这个能力. 为了不让人失望,你就会想方设法去学得更多. 第三章中,作者给我们介绍了许多HTML5中关于表单的新扩展功能. WEB开发者的美好时代来了,因为在使用日期和时间之类的常规输入元素时,他们不再需要用到JavaScipt库,尤其是对于手机输入来说.鉴于通常用手机输入比用计算机要难

如何有效地与开发人员一起工作(三)

合作可能会失败 紧密的合作关系是对时间的投资.有时候投资免不了得不到回报: 你的程序员是如此的固执以致你尖叫起来 – 只可惜很可能你的尖叫声还没他尖叫着说你固执来得响亮. 程序员可能会看起来故意阻碍或令人误解.(他也许在尝试通过使用公正的手段或不正当的手段来指示你从而节省他的时间.但是有时候他就是不可避免地粗心大意,或尝试隐藏他的无能,或其他什么原因.) 你的期望值没有达到.程序员对你做的事情不高兴. 我个人倾向于向糟糕的投资倾注更多的精力,更多的时间.那是错误的.有时候你必须承认计划失败并转向

软件测试之单元测试:开发人员的测试

说到单元测试,几乎所有人都知道,由开发人员完成.可是为什么要进行单元测试呢? 开发人员写单元测试的时间几乎和他写产品代码的时间相当,因此,当做项目计划的时候,把单元测试考虑进去是合理的.尽管单元测试增加了相当大的开发工作量,看上去开发时间延长了,但实际上对于一个长期不断改进和维护的项目而言,我们不能忽视级联效应,要从项目整体来看. 单元测试可以保证最基本的缺陷尽早的发现并解决,因此,用来解决被流转到后期的测试阶段的缺陷时间实际上就会缩短. 而如果问开发人员是否进行了单元测试,他们通常也会说,是的