• Cucumber 入门一


    (转自: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 << n 
      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)机制。当运行失败时,我们能够看到完毕的測试用例,以及明白的失败原因。
  • 相关阅读:
    101. Symmetric Tree(js)
    100. Same Tree(js)
    99. Recover Binary Search Tree(js)
    98. Validate Binary Search Tree(js)
    97. Interleaving String(js)
    96. Unique Binary Search Trees(js)
    95. Unique Binary Search Trees II(js)
    94. Binary Tree Inorder Traversal(js)
    93. Restore IP Addresses(js)
    92. Reverse Linked List II(js)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4056463.html
Copyright © 2020-2023  润新知