I've added an Around hook to my Cucumber features that I had hoped would cause pry-rescue to start pry when an exception was thrown:
Around do |scenario, block|
Pry::rescue do
block.call
end
end
The Around hook is definitely being called, however exceptions thrown within steps aren't rescued. E.g. this step:
When(/^I perform the action$/) do
raise 'hell'
end
... causes the feature to fail, but doesn't drop me into pry at the console.
Is it possible to use pry-rescue with Cucumber? I've raised this as an issue as well, as I suspect it might be a bug.
Updated: as per a suggestion from AdamT in the comments, I've:
@allow-rescue
tag to the feature calling the deliberately broken stepputs
logging to verify that the Around
hook is being calledIt's still failing to enter pry when the exception is raised, but I can see from the puts
statements that it's entering the Around hook.
To invoke the debugger, place binding. pry somewhere in your code. When the Ruby interpreter hits that code, execution stops, and you can type in commands to debug the state of the program.
I wanted to do the same thing - debug when a step fails. Your hook cannot work because a failing step exception is caught already. There seems to be no standard way of doing what you want with cucumber. But if you look at lib/cucumber/ast/step_invocation.rb
the invoke(runtime, configuration)
method, you will see what I am talking about.
In the method step level exceptions are caught. And the last rescue
block is where we want to insert our debugging code. So in latest cucumber
1.3.12, on line 74 I inserted:
require 'byebug'
byebug
And now once the transient failure happens I get a prompt:
[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
You can insert other debugging code in there though.
I'm thinking if cucumber project will accept a contribution to have a hook there instead.
UPDATE: here's my latest version. The positives in that version are that you get failure log before falling into a debugger. Also you can reach (at least with pry) to the cucumber World
and launch pry inside to play around as if this is your test code. I've opened a discussion in the cuke google group to see if something similar can be implemented upstream. Give your voice and suggestions if you want to have it standard in cucumber.
So just put the below code in 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
In the version of Cucumber 2.4.0 the #accept
method is resided in Cucumber::Formatter::LegacyApi::Ast::StepInvocation
so redefine it and proceed the required action inside it:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With