rspec/rspec-core — pull request #639 by myronmarston (2012-06-16 20:40:10+00:00)
Title: Improve `debugger` so that an IRB session is started when ruby-debug is not loaded.

This is just crazy, random idea I had today. I'm looking for feedback more than anything at this point.

I frequently receive the `use -d or --debug` warning, for a few reasons:

* At work, I'm building lots of new small, internal gems, and I don't pull in a debugger gem as a dependency until I really need it...so I'll be working on something, and will put `debugger` in a spec, and won't realize it can't work yet.
* Occasionally, I need to debug a spec failure on our CI server, where we usually `bundle install --without debugger`--so ruby-debug isn't installed.
* For a while after I started using 1.9.3, there wasn't a viable debugger gem to use. There still isn't a 1.9.3 compatible release of `ruby-debug`. cldwalker/debugger has dealt with this problem and I use that now, but it was frustrating to not have a debugger for a while. It may happen again (e.g. with the release of ruby 1.9.4 or 2.0).

90% of the time, I don't need the power of a full debugger--I just want to poke around in an IRB session at a particular point in the code. It turns out, we can easily provide that functionality directly in rspec for cases when a debugger is not loaded. So...this is a first pass implementation that makes our `debugger` print a message and start an IRB session with `self` set to the receiver of `debugger`. Here's what the output looks like:

```
*****************************************************************
A `debugger` statement has been encountered but ruby-debug is not
loaded. For a full debugger, install `ruby-debug` and use the -d
or --debug option.

The `debugger` statement was encounted at:
/Users/myron/code/rspec-dev/repos/rspec-core/spec/rspec/core/example_spec.rb:21:in `block (3 levels) in '

16 end
17 end
18
19 describe "#exception", :focus do
20 it "supplies the first exception raised, if any" do
=> 21 debugger
22 example = example_group.example { raise "first" }
23 example_group.after { raise "second" }
24 example_group.run
25 example.exception.message.should eq("first")
26 end

We've setup an IRB sessionso you can poke around here
a bit. Type `exit` to continue.
*****************************************************************
```

A couple thoughts/concerns I have:

* A debugger doesn't really belong in rspec-core. Adding this opens up the door to people requesting additions to it (e.g. `next`, `step`, up/down the callstack, etc), but I think it's important we don't go down that route. What's hear is appealing to me because it's just IRB, which is already in the stdlib.
* This has the potential to break non-interactive spec runs (e.g. on a CI server or whatever). Before, `debugger` would just print a warning and continue happily on its way...now it stops and waits for user input. Is there a way to tell if rspec is running in an interactive terminal?
* There are some extra edge cases this needs to handle (e.g. `listing` needs to handle source files that have less than 11 lines of code). (I'm mostly mentioning this so I don't forget, if we do decide to merge this).

Thoughts?