【问题标题】:Writing Cucumber tests that pass extra information编写传递额外信息的 Cucumber 测试
【发布时间】:2018-07-09 14:54:24
【问题描述】:

我有一个在 Cucumber 中进行功能测试的 Ruby on Rails 程序。

我刚刚实现了一个功能,管理员可以为客户端用户创建新密码。现在,在“编辑客户端”页面上,有一个额外的按钮允许管理员设置密码。现在,我只需要做一个黄瓜测试。

我正在尝试基于客户端更改密码的正常测试和管理员更改用户信息的测试。我有的是这样的:

Feature: Analyst changes client's password
  As an Analyst
  I want to change client's password
  So that I can reset the client's account

  Background:
    Given the following client accounts
      | email             | password |
      | user1@someorg.com | password |
    And I am logged in as an admin

  @javascript
  Scenario: Update a Client user
    Given I navigate to the Clients Management Page
    When I edit the Client User "user1@someorg.com"
    And I click on "button"
    Then I should be on the Clients Password Page

  @javascript
  Scenario: Can change password if confirmation matches
    Given I navigate to the Clients Password Page
    And I enter "Password1" as the password
    And I enter "Password1" as the password confirmation
    And I submit the form
    Then I should be taken to the Client Landing Page
    And The client's password should be "Password1"

在步骤中,我有:

Given /^I navigate to the Clients Password Page$/ do
  client_management_index_page = ClientsPasswordPage.new Capybara.current_session
  client_management_index_page.visit
end

Then /^I should be on the Clients Password Page$/ do
  client_password_page = ClientsPasswordPage.new Capybara.current_session
  expect(client_password_page).to be_current_page
end

和客户密码页:

class ClientsPasswordPage
  include PageMixin
  include Rails.application.routes.url_helpers

  def initialize session
    initialize_page session, edit_admin_client_password_path
  end
end

除了 edit_admin_client_password_path 需要一个 :id,用于正在编辑的用户。我不知道如何将这些信息输入其中。

以防万一,我正在使用 Devise 来解决安全问题...

【问题讨论】:

  • 顺便说一句,由于在 stackExchange 领域没有任何地方可以询问,如果有人在 RoR 中有一个好的 Cucumber 教程,那也会很有用!

标签: ruby-on-rails devise cucumber capybara


【解决方案1】:

有几种方法可以做到这一点。最简单的方法是意识到你在测试期间只创建了一个客户端,所以

Client.first # whatever class represents clients

永远是那个客户。显然,如果您在测试中创建了一个多于客户端的测试,那么这将不起作用,因此您可以在黄瓜步骤中创建实例变量,这些步骤设置在 World 上,然后可以从其他步骤访问并传递给您的页面对象

When I edit the Client User "user1@someorg.com"
  @current_client = Client.find_by(email: "user1@someorg.com") # obviously would actually be a parameter to the step
  ...
end

Then /^I should be on the Clients Password Page$/ do
  client_password_page = ClientsPasswordPage.new Capybara.current_session, @current_client
  expect(client_password_page).to be_current_page
end

当然,如果没有页面对象开销,这将变成

Then /^I should be on the Clients Password Page$/ do
  expect(page).to have_current_path(edit_admin_client_password_path(@current_client))
end

【讨论】:

  • “我应该在客户密码页面”如何知道@current_client 是什么?
  • @BrianPostow 因为您在“当我编辑客户端用户时...”中设置了它 - 实例变量在黄瓜世界中创建,并且可用于该场景中的所有后续步骤 - docs.cucumber.io/cucumber/state/#world-object
【解决方案2】:

您可以做很多事情来简化这种情况。如果您有更简单的场景,使用更简单的步骤定义,那么解决实施问题会更容易,例如如何在一个步骤中让客户端在第二步中可用。

简化场景的主要方法是在场景中完全没有任何内容来解释您是如何实现该功能的。如果您将所有点击按钮、填写字段和访问页面的工作都排除在您的场景之外,您就可以专注于业务问题。

怎么样

Background
  Given there is a client
  And I am logged in as an admin

Scenario: Change clients password
  When I change the clients password
  Then the client should have a new password

注意:这会立即引发“客户如何发现新密码?”的问题,这是好的简单场景所做的,它们会让您提出有价值的问题。回答这个问题可能超出了这里的范围。

现在让我们看看实现。

Given 'there is a client' do
  @client = create_new_client
end

When 'I change the clients password' do
  visit admin_change_password_path(@client)
  change_client_password(client: @client)
end

这可能足以让您走上正确的道路。另外像

Given 'I am logged in as an admin' do
  @i = create_admin_user
  login_as(user: @i)
end

会有帮助的。

我们在这里所做的是

  1. 将 HOW 下推到您的堆栈中,这样现在您有权完成这项工作的代码就不会出现在您的场景和步骤定义中了
  2. 使用变量在步骤之间进行通信 @client = create_new_client 行创建了一个全局变量(实际上是 Cucumber::World 的全局变量),该变量在所有步骤定义中都可用

您可以通过将模块添加到 Cucumber 世界并在其中定义方法来创建辅助方法。请注意,这些方法是全局的,因此您必须仔细考虑名称(这些方法是全局的有很好的理由)。所以

module UserStepHelper
  def create_new_client
    ...
  end

  def create_admin_user
    ...
  end

  def change_client_password(client: )
    ...
  end
end
World UserStepHelper

将创建一个可在任何步骤定义中使用的辅助方法。

您可以查看此方法的示例here。我在 CukeUp 2013 的演讲中使用的一个项目。也许您可以将其用作您的教程示例。

【讨论】:

    猜你喜欢
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多