(转自:http://www.cnblogs.com/jarodzz/archive/2012/07/02/2573014.html)

第一次看到Cucumber和BDD(Behavior Driven Development, 行为驱动开发),是在四年前。那时才開始工作,对软件測试工具相当着迷。仅仅要是开源的、免费的,我就一定要下载,安装,试用。有的工具用途单一、好懂(如Jmeter,Watir);有的工具,则涉及到一些软件领域的独有概念,不好懂,(如STAF,Cucumber)。好懂的,我上手、试用、推广,不亦乐乎;不好懂的,就仅仅能丢在一边,这里面就包含Cucumber。

再次看到Cucumber,已是两年前。我对软件开发的理解也深了些,这一看,可真是个好东西。之后我与Cucumber间发生的故事,稍后慢慢向大家交代。这开篇的第一章,我想献给如当年的我一样,偶然见到了Cucumber和BDD,却不明所以将之丢在一边的家伙们。

初闻Cucumber的人,第一件事一定是来到Cucumber的首页,第一眼看到的一定是

非常不幸的是,这六张图不太好懂。由于它们依照BDD的流程来编写的。为了让它们好懂些,我们抛开BDD,採用传统的软件开发模型(设计->编码->測试)来看它。传统流程例如以下:

图1,这是一个被測系统——用ruby编写的计算器。

为了便于大家理解,我试着改动了一些。

?
class Calculator 
  def push(n)   
#记数
    @args ||=
[]
#初始化空数组
    @args <<
  end
  def sum()     
#返回全部数字和
    sum
=
0
    @args.each do |i|
      sum
+= i
    end
    @result =
sum
  end
  def result
    @result
  end
end

计算器Calculator提供两个功能: 记数push;加和sum。push将数字一一记录在@args数组中;sum则将全部@args数组中的数字累加得和,存入@result中。写完了被測系统,我们来编写測试用例。

图2,这是为了測试上述计算器,使用Cucumber描写叙述的測试用例。

原图中的英文描写叙述,被我翻译成了中文。:

?
Feature:
计算器
  Scenario:
两数相加
    Given
我有一个计算器
    And
我向计算器输入
50
    And
我向计算器输入
70
    When
我点击累加
    Then
我应该看到结果
120

支持中、英等自然语言,是Cucumber的特点之中的一个。在Cucumber的帮助文档里,声明它支持包含中文简体、繁体中文、日文、韩文和英文在内的45种语言。

注意:我并未将全部英文都翻译成中文,而是留下了几个keyword:

  • Feature(功能)
  • Scenario(情景)
  • Given(给定)
  • And(和)
  • When(当)
  • Then(则)

它们的含义与原有自己主动化測试工具中的概念同样,类比方下:

Cucumber Unit Test
Feature (功能) test suite (測试用例集)
Scenario(情景) test case (測试用例)
Given(给定) setup(创建測试所需环境)
When(当) test(触发被測事件)
Then(则) assert(断言,验证结果)

Cucumber放弃了原有的keyword,而选择了左边五种,仅仅是为了更加流畅地支持自然语言。使用Cucumber的keyword,创建了測试用例,接下来,要怎样使用Cucumber来执行它呢?

图3,这是执行Cucumber时的画面。

在一台安装好Cucumber的机器上,执行上述測试用例,便能够看到下列输出:

?
Feature:
计算器
 
  Scenario:
两数相加   
#
features/calculator.feature:3
    Given
我有一个计算器  
#
features/calculator.feature:4
    And
我向计算器输入
50   #
features/calculator.feature:5
    And
我向计算器输入
70   #
features/calculator.feature:6
    When
我点击累加     
#
features/calculator.feature:7
    Then
我应该看到结果
120 #
features/calculator.feature:8
 
1 scenario
(
1 undefined)
5 steps
(
5 undefined)
0m0.005s
 
You
can implement step definitions
for undefined
steps with these snippets:
 
Given
/^我有一个计算器$/
do
  pending
#
express the regexp above with the code you wish you had
end
 
Given
/^我向计算器输入(\d+)$/
do |arg1|
  pending
#
express the regexp above with the code you wish you had
end
 
When
/^我点击累加$/
do
  pending
#
express the regexp above with the code you wish you had
end
 
Then
/^我应该看到结果(\d+)$/
do |arg1|
  pending
#
express the regexp above with the code you wish you had
end

Cucumber首先输出的是測试用例的描写叙述,然后3行总结性地输出:本功能(Feature)有1个情景(1 scenario);5个步骤(5 steps),所有5个步骤均没有定义(undefined);执行耗时0.005秒。这里出现了两个新名词:步骤(steps)和步骤定义(step definitions)。在Cucumber中,以keywordGiven, And, When, Then开头的每一行,为一个步骤。在两数相加的情景中,一共同拥有5行。因此,结果显示:5个步骤。

怎样定义一个步骤,在Cucumber的执行结果中也给出了具体的办法。在3行总结性输出后,紧接着便是:You can implement…即:你能够使用以下的代码段实现步骤定义,然后是4个小的代码段。这些代码段,便是Cucumber按照情境中我们使用的5个步骤,帮助我们生成的步骤定义框架。每一个框架都将内容部分空白出来,等待填充。以下,我们来进行步骤定义。

图4, 这是一个步骤定义的代码示范。

我们按照图2的样子,向中文步骤中填入代码,例如以下:

?
Given
/^我有一个计算器$/
do
  @c =
Calculator.
new
end
 
Given
/^我向计算器输入(\d+)$/
do |num|
  @c.push(num.to_i)
end
 
When
/^我点击累加$/
do
  @c.sum
end
 
Then
/^我应该看到结果(\d+)$/
do |result|
  @c.result.should
== result.to_i
end

步骤定义的过程,就是向代码段——步骤定义框架——中填入代码的过程,即:用代码来描写叙述你期望的,该步骤应该运行的动作。完整的步骤定义是一个函数,它:

  • 以正則表達式作为函数名
  • 匹配值作为參数
  • 以測试人员输入的代码作为内容

由于有了正則表達式的匹配,5个步骤仅须要4个步骤定义。“我向计算器输入50、70”两个步骤,都能够用“我向计算器输入(\d+)”一个正則表達式来描写叙述。匹配值被自己主动提取出来作为參数,传入代码。注意:全部匹配值,即參数,都是以字符串的形式传递,因此,我增加了num.to_i
与 result.to_i,将得到的字符串转为整形。步骤定义完毕,再次运行Cucumber。屏幕将会显示一片绿色。

图5,它是一个运行Cucumber測试用例,并成功通过的画面。

步骤定义完毕后,再次执行Cucumber。Cucumber会找到步骤定义,并依照其代码去执行。结果例如以下:

?
Feature:
加法
 
  Scenario:
两数相加   
#
features/calculator.feature:3
    Given
我有一个计算器  
#
features/step_definitions/a.rb:2
    And
我向计算器输入
50   #
features/step_definitions/a.rb:6
    And
我向计算器输入
70   #
features/step_definitions/a.rb:6
    When
我点击累加     
#
features/step_definitions/a.rb:10
    Then
我应该看到结果
120 #
features/step_definitions/a.rb:14
 
1 scenario
(
1 passed)
5 steps
(
5 passed)
0m0.003s

步骤定义被我保存在目录step_definitions下的a.rb其中。步骤定义所在文件与起始行数,被打印在每一个步骤结尾,以方便查找和改动。最后,Cucumber总结性地输出执行结果:1个情景,5个步骤,所有通过。

图6, 这是一个运行Cucumber測试用例,但失败的画面。

为了让这个已经十分简单的计算器产生bug,我仅仅好将它改错为:

?
class Calculator
  def sum()
    sum
=
0
    @args.each do |n|
      sum
= n   
#此处原为:sum
+= n
    end
    @result =
sum
  end
end

再次执行Cucumber,结果为:

?
Feature:
加法
 
  Scenario:
两数相加   
#
features/calculator.feature:3
    Given
我有一个计算器  
#
features/step_definitions/a.rb:2
    And
我向计算器输入
50   #
features/step_definitions/a.rb:6
    And
我向计算器输入
70   #
features/step_definitions/a.rb:6
    When
我点击累加     
#
features/step_definitions/a.rb:10
    Then
我应该看到结果
120 #
features/step_definitions/a.rb:14
      expected:
120
           got:
70 (using
==) (RSpec::Expectations::ExpectationNotMetError)
      ./features/step_definitions/a.rb:15:in `/^我应该看到结果(\d+)$/'
      features/calculator.feature:8:in `Then
我应该看到结果
120'
 
Failing
Scenarios:
cucumber
features/calculator.feature:
3 #
Scenario: 两数相加
 
1 scenario
(
1 failed)
5 steps
(
1 failed,
4 passed)
0m0.004s

失败的步骤是用红色标示出来的。在最后一个步骤中,Cucumber期待的结果为120,但得到的是70。注意:失败的情景列表(Failing Scenarios)里列出的是:“两数相加”这个情景所在的文件与起始行数。这是由于一个功能文件内,可能含有多个情景,这样的输出能够便于找到出错的情景。

接下来的总结性结果为:1个情景失败(1 failed),5个步骤中,4个通过,1个失败。

作为自己主动化測试工具的Cucumber,就介绍到这里。

在继续之前,我们先回想一下本章内容。

回想:

    • Cucumber是一个自己主动化測试工具
    • 它提供了自然语言的支持,我们能够用自然语言描写叙述、并运行測试用例
    • 它提供了自然语言与代码的衔接,通过步骤与步骤定义
    • 它提供了自然语言对代码的调用,当步骤定义结束后,执行Cucumber,它会自己主动调用步骤定义内的代码执行
    • 它提供了良好的断言(assert)机制。当运行失败时,我们能够看到完毕的測试用例,以及明白的失败原因。

Cucumber 入门一的更多相关文章

  1. 使用calabash测试开源中国Android客户端

    Calabash-android是支持android的UI自动化测试框架,前面已经介绍过<中文Win7下成功安装calabash-android步骤>,这篇博文尝试测试一个真实应用:开源中 ...

  2. cucumber java从入门到精通(4)Scenario Outline及数据驱动

    cucumber java从入门到精通(4)Scenario Outline及数据驱动 到目前为止,我们的TodoList类工作良好,不过离我们的预期--任务清单系统还是有不少差距,究其原因不过如下: ...

  3. cucumber java从入门到精通(3)简单实现及断言

    cucumber java从入门到精通(3)简单实现及断言 上一节里我们定义了step的java代码实现文件,step就是测试步骤及断言的集合,我们先定义出来,以后可以驱动开发以及在持续集成时重用. ...

  4. cucumber java从入门到精通(2)用代码定义步骤

    cucumber java从入门到精通(2)用代码定义步骤 上一节里我们定义了feature文件,feature文件就是自然语言描述的用例文件,它有一定的章法,具体的潜规则是: 使用Feature关键 ...

  5. cucumber java从入门到精通(1)初体验

    cucumber java从入门到精通(1)初体验 cucumber在ruby环境下表现让人惊叹,作为BDD框架的先驱,cucumber后来被移植到了多平台,有cucumber-js以及我们今天要介绍 ...

  6. Apple Swift编程语言入门教程

    Apple Swift编程语言入门教程 作者: 日期: 布衣君子 2015.09.22 目录 1   简介 2   Swift入门 3   简单值 4   控制流 5   函数与闭包 6   对象与类 ...

  7. Swift语言入门之旅

    Swift语言入门之旅  学习一门新的计算机语言,传统来说都是从编写一个在屏幕上打印"Hello world"的程序開始的.那在 Swift,我们使用一句话来实现它: printl ...

  8. [转]Swift 编程语言入门教程

    今天在网上看到一篇非常好的教程,分享给大家 原文地址:http://gashero.iteye.com/blog/2075324 目录 1   简介 2   Swift入门 3   简单值 4   控 ...

  9. Apple Swift编程语言入门

    1   简单介绍 今天凌晨Apple刚刚公布了Swift编程语言,本文从其公布的书籍<The Swift Programming Language>中摘录和提取而成.希望对各位的iOS&a ...

随机推荐

  1. 【转】android Apk打包过程概述_android是如何打包apk的

    最近看了老罗分析android资源管理和apk打包流程的博客,参考其他一些资料,做了一下整理,脱离繁琐的打包细节和数据结构,从整体上概述了apk打包的整个流程.   流程概述: 1.打包资源文件,生成 ...

  2. Android平台程序崩溃的类型及原因列举

    Android平台程序崩溃大家都应该遇到过,force close和ANR应该是大家遇到较多的. 这里把Android平台程序崩溃的各种类型做一个简述和原因列举. 1.ANR(可见ANR): 发生场景 ...

  3. linux中waitpid及wait的用法

    wait(等待子进程中断或结束) 表头文件      #include<sys/types.h>      #include<sys/wait.h> 定义函数 pid_t wa ...

  4. [Everyday Mathematics]20150109

    设 $A$ 是 $n$ 阶复方阵, 其特征多项式为 $$\bex f(\lm)=(\lm-\lm_1)^{n_1}\cdots(x-\lm_s)^{n_s}, \eex$$ 其中 $\lm_i$ 互不 ...

  5. ylbtech-数据库设计与优化-对作为复选框/单选列表的集合表的设计

    ylbtech-DatabaseDesgin:ylbtech-数据库设计与优化-对作为复选框/单选列表的集合表的设计 -- DatabaseName:通用表结构-- -- 主要是针对将要设计的表对象, ...

  6. Request、Request.Form和Request.QueryString的区别

    Request.Form:获取以POST方式提交的数据(接收Form提交来的数据): Request.QueryString:获取地址栏参数(以GET方式提交的数据) Request:包含以上两种方式 ...

  7. qt集成到vs2010

    因为要正式开始学习图形处理相关的知识了,所以要搭建开发平台.我所要用到的平台主要是vs和qt.虽然现在已经出了vs2013了,并且外观看起来特别漂亮,但是我所要用到的qt4版本中,没有对于的qtAdd ...

  8. 去除下载电影和电视剧文件名中的多余字符[python实现]

    讨厌下载电影和电视剧文件名中的多余字符(如网址和广告字样),,搞得文件名好长,可以使用下面的Python代码,自行修改即可. #!\usr\bin\env python # -*- coding: u ...

  9. 怎么使用PHPMailer实现邮件的发送??

    来源:http://www.ido321.com/1103.html 发送邮件是常用的功能,LZ今天在项目中也碰到了,特此分享一下. 首先,去下载PHPMailer 1.https://github. ...

  10. J2SE7规范_2013.2_类

    8.1 类的定义   包括普通类和枚举类,枚举(略) 下面都是指普通类:   public只能用于外部类,成员类,不能用于局部类,匿名类 protected和private用于成员类时(待解) sta ...