【问题标题】:Including shared example from rspec inside of cucumber包括来自黄瓜内部 rspec 的共享示例
【发布时间】:2019-12-21 13:41:35
【问题描述】:

最终目标是包含在 rails_helper.rb 中的 shared_examples.rb。 shared_examples.rb 是该文件的副本

https://github.com/tinfoil/devise-two-factor/blob/master/lib/devise_two_factor/spec_helpers/two_factor_authenticatable_shared_examples.rb

我想在我的黄瓜测试中引用 shared_examples.rb 以便我可以使用方法it_behaves_like 'two_factor_authenticatable'

我有以下文件夹结构:

更新以包含@morissetcl 建议的结构

features
    step_definitions
        sample_step.rb
    support
        env.rb
    sample.feature

spec
    models
        user_spec.rb
    support
        shared_examples
            shared_example.rb
    rails_helper.rb
    spec_helper.rb

features 和 spec 文件夹都位于我的 rails 项目的根目录中。

我试图将位于 spec 文件夹中的 rails_helper.rb 包含在 sample_step.rb 文件中。

我尝试在 sample_step.rb 文件中使用不同类型的 require,如下所示。

需要'spec/spec_helpers/shared_examples'

需要'../../spec/spec_helpers/shared_examples'

require_relative '../../spec/spec_helpers/shared_examples'

我不断收到以下错误

undefined method `it_behaves_like' for main:Object (NoMethodError)

【问题讨论】:

  • 好的做法是将您的 shared_example 放在支持文件夹 spec/support/shared_examples/the_name_of_your_shared.rb 中,然后在您的 rails_helper 添加以下行 Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} 将用于加载您的文件(在此方式你不需要什么东西)。此外,我想将spec_helper 用作文件夹会令人困惑。
  • 感谢您的建议。我确实进行了您提供的更改,但是,我的共享示例仍然找不到 it_behaves_like 方法。这是错误的 sn-p:undefined method it_behaves_like for #<Cucumber::Rails::World:0x00007fe383683968> (NoMethodError)
  • 也许真正要问的问题是黄瓜是否允许包含来自 rspec 的共享示例? shared_example 是一个 rspec 共享示例。

标签: ruby cucumber ruby-on-rails-5 rspec-rails


【解决方案1】:

it_behaves_like 是特定于 rspec 的。它的作用是允许一个规范为特定对象运行另一个规范,因此这在 Cucumber 中不起作用。

您需要做的是拥有一个包含一些杯子和一些规格的测试套件。您在 rspec 中详细介绍了两因素身份验证,如果您必须始终使用两因素身份验证来登录您的 cukes,您需要编写一个辅助方法以便您可以做到这一点。

为此,我将执行以下操作

  1. 编写一些步骤定义来支持登录,将工作委托给辅助方法。

  2. 编写辅助方法

  3. 让辅助方法调用其他方法以支持双因素身份验证

  4. 将辅助方法添加到 cucumber 的世界对象中,以便在步骤 def 中调用它们

所以

# features/step_defintions/login
module LoginStepHelper
  def login(user: )
    login_fill_form_and_submit(user: user)
    login_two_factor(user: user)
    submit_form

  end

  def login_fill_form_and_submit(user: )
    fill_in :email, user.email
    fill_in :password, user.password
  end

  def login_two_factor(user: )
    code = retrieve_2factor_code(user: user)
    fill_in :2factor, code
  end

  ...

end
World(LoginStepHeler)

所以现在你必须弄清楚测试如何获得 2factor 代码。 完成此操作后,您就有了一个工具,您的步骤定义可用于登录,因此您可以编写类似

Given 'I am logged in' do
  login user: @i
end

Given 'I login as Fred' do
  login user: @fred
end

...

注意:有多少 step defs 可以使用您的辅助方法。

您可以在此处https://github.com/diabolo/cuke_up 找到有关此方法的更多详细信息,其中包括有关如何创建我们在上述代码中传递给登录函数的测试用户的详细信息

【讨论】:

  • 感谢您的建议。所以我有点听从你说的。我让它工作的方式是在黄瓜的步骤中,我需要使用两个因素登录,我必须复制共享示例如何在成功运行两个因素之前设置数据。
【解决方案2】:

我想出的解决方案是使用@diabolist 提出的一些建议。我查看了共享示例文件:https://github.com/tinfoil/devise-two-factor/blob/master/lib/devise_two_factor/spec_helpers/two_factor_authenticatable_shared_examples.rb

然后我使用了#validate_and_consume_otp!场景并使用 before :each 块中的信息设置数据。

结果和我的黄瓜规格一样:

When('I fill in the login form with two factor code') do
  Timecop.freeze(Time.current)
  otp_secret = '2z6hxkdwi3uvrnpn'
  @user.otp_secret = otp_secret
  otp = ROTP::TOTP.new(otp_secret).at(Time.now)
  @user.save # <- This is important to save it so the user has the otp you will pass
  Timecop.return

  fill_in 'user_email', with: 'user@example.com'
  fill_in 'user_password', with: 'password'
  fill_in 'user_otp_attempt', with: otp
  click_button 'Login'
end

设置可以被清理并放入一个方法,就像@diabolist 描述的那样,它可以被其他测试重用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多