InfoQ

新闻

RSpec增加了众所翘首以待的RBehave功能以供集成测试所需

作者 Sean Miller译者 张海龙 发布于 2007年10月31日 上午9时56分

社区
Ruby,
Agile
主题
质量交付,
客户及需求
标签
BDD,
测试,
RBehave,
RSpec

RSpec是 一个为Ruby编写的基于行为驱动开发(简称BDD,即Behaviour-Driven Development)的验收测试框架,同时也可用于Java(事实上它一直都可以运行于JRuby中),它提供了一种机制,即由开发人员从业务中获取 验收标准并将它们转换为可读、可运行的示例,以此替代文档、测试和适用于业务的构建报告。

尽管RSpec对单元级测试很有用,但它在集成测试中一直存在一个盲点。Dan North创建了一个独立的扩展,RBehave,它用Given…With…Then…这样的格式以一系列的步骤从故事级别来描述行为。(North最早是在JBehave中描述了这种用于获得需求故事的模式)

David Chelimsky现在已经向RSpec trunk中合并了一个纯文本故事运行器(Plain Text Story Runner),它给RSpec添加了RBehave功能,就像他 他的 博客中描述的那样。

现在看看North的经典RBehave示例:

So, North's classic RBehave example:
require ‘rubygems’
require ‘rbehave’
require ’spec’ # for "should" method

require ‘account’ # the actual application code

Story "transfer to cash account",
%(As a savings account holder
  I want to transfer money from my savings account
  So that I can get cash easily from an ATM) do

  Scenario "savings account is in credit" do
    Given "my savings account balance is", 100 do |balance|
      @savings_account = Account.new(balance)
    end
    Given "my cash account balance is", 10 do |balance|
      @cash_account = Account.new(balance)
    end
    When "I transfer", 20 do |amount|
      @savings_account.transfer_to(@cash_account, amount)
    end
    Then "my savings account balance should be", 80 do |expected_amount|
      @savings_account.balance.should == expected_amount
    end
    Then "my cash account balance should be", 30 do |expected_amount|
      @cash_account.balance.should == expected_amount
    end
  end

  Scenario "savings account is overdrawn" do
    Given "my savings account balance is", -20
    Given "my cash account balance is", 10
    When "I transfer", 20
    Then "my savings account balance should be", -20
    Then "my cash account balance should be", 10
  end
end

在新的RSpec中它可以变成这样,由一个Ruby文件定义可用的步骤:

class AccountSteps < Spec::Story::StepGroup
  steps do |define|
    define.given("my savings account balance is $balance") do |balance|
      @savings_account = Account.new(balance.to_f)
    end

    define.given("my cash account balance is $balance" do |balance|
      @cash_account = Account.new(balance.to_f)
    end

    define.then("my savings account balance should be $expected_amount" do |expected_amount|
      @savings_account.balance.should == expected_amount.to_f
    end

    define.then("my cash account balance should be $expected_amount" do |expected_amount|
      @cash_account.balance.should == expected_amount.to_f
    end
  end
end

steps = AccountSteps.new do |define|
  define.when("I transfer $amount") do |amount|
    @savings_account.transfer_to(@cash_account, amount.to_f)
  end
end
在一个纯文本文件中按照那些步骤定义故事的行为:
Story: transfer to cash account
  As a savings account holder
  I want to transfer money from my savings account
  So that I can get cash easily from an ATM

  Scenario: savings account is in credit
    Given my savings account balance is 100
    And my cash account balance is 10
    When I transfer 20
    Then my savings account balance should be 80
    And my cash account balance should be 30

  Scenario: savings account is overdrawn
    Given my savings account balance is -20
    And my cash account balance is 10
    When I transfer 20
    Then my savings account balance should be -20
    And my cash account balance should be 10

由一个Ruby文件将他们粘在一起,并运行这些故事:

require 'spec'
require 'path/to/your/library/files'
require 'path/to/file/that/defines/account_steps.rb'

# assumes the other story file is named the same as this file minus ".rb"
runner = Spec::Story::Runner::PlainTextStoryRunner.new(File.expand_path(__FILE__).gsub(".rb",""))
runner.steps << AccountSteps.new
runner.run

纯文本文件中的那些步骤描述,必须与StepGroup中定义的步骤相匹配,这些描述可能会随着步骤数量的增加变得难以理解。Aslak Hellesøy正在为一个基于浏览器的编缉器工作,它将提供步骤的自动补全,并可以在恰当的位置对参数进行编辑,从而使这一问题得以简化。

查看英文原文RSpec Trunk Now Includes RBehave-like Story Runner

1 条回复

回复

RSpec 用起来还是相当棒的 发表人 Raecoo cao 发表于 2007年11月2日 下午10时1分
  1. 返回顶部

    RSpec 用起来还是相当棒的

    2007年11月2日 下午10时1分 发表人 Raecoo cao

    RSpec 用起来还是相当棒的
    特别是以测试代码来表现文档,不需要再去特意撰写相关文档
    希望有机会可以和大家一起交流
    raecoo AT gmail.com

独家内容

专访开源项目Amoeba架构师陈思儒

DBA notes站长冯大辉(Fenng)代表InfoQ中文站采访了分布式数据库Proxy开源项目Amoeba的架构师和主要开发者陈思儒,内容包括Amoeba项目的起因、功能及其愿景等。

使用JSF、Ajax和Seam开发Portlets(2/3)

作为三期系列文章的第二部分,本文延续了上一期内容,介绍了RichFaces,包括如何把RichFaces集成到之前提到的示例应用中、如何部署RichFaces porlet和RichFaces的多种特性和功能。

Jeff Barr谈论Amazon Web服务

Amazon Web Services(AWS)的传道者Jeff Barr讨论了SimpleDB、S3、EC2、SQS、云计算、Amazon的不同服务如何与应用交互、AWS的起源、SimpleDB和微软SQL Server Data Services、AWS cloud的全球化、三月份的AWS停机。

用Erlang实现领域特定语言

Erlang的并发模型很有名,它的健壮性也很有名。但其他方面呢?在这篇文章里,Dennis Byrne演示了如何用Erlang建立内部DSL。

基于Rails的企业级应用剖析

本视频主要以FreeWheel为例,对一个基于Rails的企业级应用进行了剖析。其中包括:FreeWheel的架构、部署、数据库的问题、REST API、敏捷开发过程、如何去写测试以及持续集成等等。

JavaFX技术预览

JavaFX显示了Sun的Java系列产品市场方向的一个重大转变。随着1.0版的即将发布,InfoQ以JavaFX预览版为参考,与Sun高级工程师Joshua Marinacci探讨了即将发布的1.0正式版。

剖析短迭代

敏捷教练Dave Nicolette提出:我们应该如何设定迭代长度?是要根据发布周期的时间么?使用短迭代又有哪些好处?

应用JSF、Ajax和Seam开发Portlets(1/3)

本文主要讲述了如何用JBoss Portlet Container 和JBoss Portlet Bridge创建新项目,怎样配置一个JSF应用去使用JBoss Portlet Bridge,以及JBoss Portlet Bridge所具备的功能。