美文网首页程序员RubyCucumber
使用 cucumber 编写用户故事

使用 cucumber 编写用户故事

作者: 编程青年 | 来源:发表于2016-02-16 09:22 被阅读525次

    cucumber 是一款 BDD 的工具,通常用于集成测试。
    如果应用是一个只提供 API 给手机端调用的后端程序。本来并不是很适合使用 cucumber。
    不过随着开发的深入,我越来越觉得单纯的 API 测试(controller 层)无法表达用户的意图。
    而目在开发团队对产品的用例也不是非常清楚,没有文档可言的情况下,使用 cucumber 来编写用例也是一个不错的选择。

    使用 cucumber 的好处

    在开发应用时,我们会把大的功能点分解成小的功能。但是在理解业务逻辑时,我们要从更宏观的角度看待系统。
    Rails 框架的单体风格并不足以让人非常舒服的熟悉一个系统。因为 ActiveRecord 的特性,我们只能看到模型之间的关系,而看不到用户是是如何和它们交互的。
    这就像给你一堆齿轮,转轴和马达一样,你知道如何拼装它们,但你看不到它们所组成的到底是汽车,飞机还是轮船。
    通过用户故事,无论是开发人员还是业务人员都能对系统有一个快速直观的理解。
    而 cucumber 就是将用户故事代码化的一款工具。

    Get Started

    如果使用 rails 自带的 minitest 测试框架。添加 cucumber 的步骤如下。

    1. 在 Gemfile 中添加

      group :test, :development do
        gem 'cucumber-rails', :require => false
        gem 'database_cleaner'
      end
      
    2. 安装

      bundle install
      rails generate cucumber:install
      
    3. 编写第一个 feature

      @require_login
      Feature: XiaomiSports
        In order to know about my xiaomi sports
        As a care user with xiaomi profile binding
        I want list of my xiaomi sports
      
      Scenario: List of the xiaomi sports
        Given the system knows my xiaomi profile
        And the system knows about the following sports::
          |  record_on |  step |
          | 2015-05-25 |  8000 |
          | 2015-05-26 | 10000 |
          | 2015-05-27 | 12000 |
        When the client requests GET "/api/v1/xiaomi_profile/exercise_data?fromDate=2015-05-25&toDate=2015-05-27"
        Then response should be "200"
        And the JSON response should be an array with 3 "step" elements
      
    4. 执行 bin/rake cucumber 并且实现相应步骤
      cucumber 会自动输出实现步骤的提示代码类似于:

    You can implement step definitions for undefined steps with these snippets:
    
    Given(/^the system knows about the processions of my corp$/) do
         pending # express the regexp above with the code you wish you had
    end
    

    只要把上述代码拷贝到 features/step_definitions/xxxx_steps.rb中, 然后填写测试代码, 那么执行到这段"情节"时, 代码块中的代码就会被执行.

    tips

    一些实用小技巧

    使用 tag 来实现 AOP 的效果

    我在上面的代码中使用了 @require_login 这个 tag, 表示下面的步骤是需要在用户登录状态下才能完成的.

    可以对 tag 添加钩子函数来 DRY,features/support/hooks.rb

    Before('@require_login') do
      # login logic
    end
    

    table 的使用

    在 cucumber 中使用 table 可以非常直观的表达一组数据结构, 比如上面提到的:

    |  record_on |  step |
    | 2015-05-25 |  8000 |
    | 2015-05-26 | 10000 |
    | 2015-05-27 | 12000 |
    

    在 step 中可以这样获取:

    Given(/^the system knows about the following sports::$/) do |table|
        table.hashes #=> [{"record_on"=>"2015-05-25", "step"=>"8000"}, {"record_on"=>"2015-05-26", "step"=>"10000"}, {"record_on"=>"2015-05-27", "step"=>"12000"}]
    end
    

    request header 的设置方式

    直接上代码, 模拟客户端的请求

      @current_user = FactoryGirl.create(:access_token).user
      header 'Accept', 'application/json'
      header 'Content-Type', 'application/json'
      header 'Token', @current_user.access_tokens.last.token
    

    参考文档

    https://cucumber.io/docs/reference/rails
    http://anthonyeden.com/2013/07/10/testing-rest-apis-with-cucumber-and-rack.html
    http://www.emilsoman.com/blog/2013/05/18/building-a-tested/

    相关文章

      网友评论

        本文标题:使用 cucumber 编写用户故事

        本文链接:https://www.haomeiwen.com/subject/ddjukttx.html