【问题标题】:Using pry-rescue to debug exceptions in Cucumber steps使用 pry-rescue 调试 Cucumber 步骤中的异常
【发布时间】:2013-10-23 02:24:28
【问题描述】:

我在我的 Cucumber 功能中添加了一个 Around 钩子,我希望它会在引发异常时导致 pry-rescue 开始 pry:

Around do |scenario, block|
  Pry::rescue do
    block.call
  end
end

Around 钩子肯定会被调用,但是在步骤中抛出的异常不会被挽救。例如。这一步:

When(/^I perform the action$/) do
  raise 'hell'
end

... 导致功能失败,但不会让我在控制台中窥探。

是否可以对 Cucumber 使用 pry-rescue?我也将此作为issue 提出,因为我怀疑这可能是一个错误。

更新: 根据 cmets 中 AdamT 的建议,我已经:

  • @allow-rescue标签添加到调用故意破坏步骤的功能中
  • 添加了puts 日志记录以验证Around 钩子正在被调用

引发异常时仍然无法进入pry,但我可以从puts 语句中看到它正在进入Around hook。

【问题讨论】:

  • 您是否验证了 Around 钩子是由 puts 或具有讽刺意味的 binding.pry 触发的?
  • @AdamT:我已经验证了 Around 钩子正在被触发,并且我还在一个失败的步骤中测试了 Pry::rescue,并且效果很好。我只是没有设置好,以便 all 异常触发 pry。
  • 您是否查看过@allow-rescue 的标记测试? github.com/cucumber/cucumber/wiki/Tags
  • @AdamT:感谢您的建议-我刚刚尝试过,但失败了:(我会相应地更新问题文本。
  • 我假设您使用rescue rails server 启动服务器?还是rescue cucumber

标签: ruby cucumber pry


【解决方案1】:

我想做同样的事情 - 在步骤失败时进行调试。您的钩子无法工作,因为已经捕获了失败的步骤异常。似乎没有标准的方法可以用黄瓜做你想做的事。但是如果你看看lib/cucumber/ast/step_invocation.rbinvoke(runtime, configuration)方法,你就会明白我在说什么。

在方法步骤级别的异常被捕获。最后一个rescue 块是我们要插入调试代码的地方。所以在最新的cucumber 1.3.12 的第 74 行,我插入了:

        require 'byebug'
        byebug

现在一旦发生瞬时故障,我会收到提示:

[71, 80] in /home/remote/akostadi/.rvm/gems/ruby-2.1.1/gems/cucumber-1.3.10/lib/cucumber
/ast/step_invocation.rb
   71:             failed(configuration, e, false)
   72:             status!(:failed)
   73:           rescue Exception => e
   74:             require 'byebug'
   75:             byebug
=> 76:             failed(configuration, e, false)
   77:             status!(:failed)
   78:           end
   79:         end
   80:       end

您可以在其中插入其他调试代码。

我在想,黄瓜项目是否会接受捐款,以便在那里有一个钩子。

更新:这是我的最新版本。该版本的优点是您在进入调试器之前会获得失败日志。你也可以到达(至少用撬)到黄瓜World 并在里面启动撬来玩,就好像这是你的测试代码一样。我打开了discussion in the cuke google group,看看是否可以在上游实现类似的东西。如果你想让黄瓜成为标准,请给出你的声音和建议。 所以只要把下面的代码放在support/env.rb:

  Cucumber::Ast::StepInvocation.class_eval do
    ## first make sure we don't lose original accept method
    unless self.instance_methods.include?(:orig_accept)
      alias_method :orig_accept, :accept
    end

    ## wrap original accept method to catch errors in executed step
    def accept(visitor)
      orig_accept(visitor)
      if @exception
        unless @exception.class.name.start_with?("Cucumber::")
          # @exception = nil # to continue with following steps
          # cd visitor.runtime/@support_code
          # cd @programming_languages[0].current_world
          # binding.pry
          require 'pry'
          binding.pry
        end
      end
    end
  end

【讨论】:

  • 您还在使用上面的解决方案吗?没有添加任何钩子?
  • @Erik,是的,仍然适用于 1.3.x 系列。对于即将到来的 2.x,我只使用 After 钩子,它不允许我在步骤失败后继续场景,但没有时间摆弄 2.x 并使其像 1.3 一样工作
【解决方案2】:

在 Cucumber 2.4.0 版本中,#accept 方法位于 Cucumber::Formatter::LegacyApi::Ast::StepInvocation,因此重新定义它并在其中执行所需的操作:

Cucumber::Formatter::LegacyApi::Ast::StepInvocation.class_eval do
  alias_method :orig_accept, :accept

  def accept formatter
    orig_accept(formatter)
    if status == :failed
      formatter.runtime.support_code.ruby.current_world.instance_eval do
        # do something as if you are inside the cuke test step
        # like: expect(something).to be_something_else
      end
    end
  end
end

【讨论】:

    【解决方案3】:

    你有没有试过打电话:

    binding.pry
    

    只需在失败的测试中调用它并环顾四周。

    【讨论】:

    • 问题是没有一个失败的测试;测试在不同的地方间歇性地失败。因此,每当出现异常时,我都希望触发 pry。
    • 我现在也正在经历这个过程。需要注意的是驱动程序。不确定这是否有助于您调试,但对我们来说,我们意识到 firefox 驱动程序始终失败,而 poltergeist 一致。不过似乎提出了更多问题......
    • 你有没有得到任何地方?我彻底失败了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多