4

I'm trying to use Pry with RSpec. Goal is to be able to drop binding in method and debug it.

Here is what I have.

lib/play.rb

class Play
  def self.hello
    print 'Hello world!'
    require 'pry'; binding.pry
  end
end

spec/play_spec.rb

require_relative '../lib/play'

describe Play do
  it 'Play#hello should print message' do
    expect {Play.hello}.to output('Hello world!').to_stdout
    #require 'pry'; binding.pry
  end
end

If I uncomment binding in spec file and run rspec I'm getting into Pry which behaves as expected

Frame number: 0/23

From: /Users/iiezhachenko/Documents/Repos/bdd-ruby-      playground/spec/play_spec.rb @ line 6 :

    1: require_relative '../lib/play'
    2:
    3: describe Play do
    4:   it 'Play#hello should print message' do
    5:     expect {Play.hello}.to output('Hello world!').to_stdout
 => 6:     require 'pry'; binding.pry
    7:   end
    8: end

[1] pry(#<RSpec::ExampleGroups::Play>)> ls
RSpec::Core::MemoizedHelpers#methods: is_expected  should  should_not  subject
RSpec::Core::Pending#methods: pending  skip
RSpec::Mocks::ArgumentMatchers#methods:

If I comment out binding.pry in spec fill, put it in method which is tested and invoke "rspec" again. I'm getting into completely messed Pry.

[1] pry(Play)> ls
[2] pry(Play)> fghjk
[3] pry(Play)> kweutyalfh 
[4] pry(Play)> exit
F

Failures:

  1) Play Play#hello should print message
     Failure/Error: expect {Play.hello}.to output('Hello world!').to_stdout

       expected block to output "Hello world!" to stdout, but output "Hello world!\n\e[1mFrame number:\e[0m 0/32\n\n\e[1mFrom:\e[0m /Users/iiezhachenko/Documents/Repos/bdd-ruby-playground/lib/play.rb @ line 4 Play.hello:\n\n    \e[1;34m2\e[0m: \e[32mdef\e[0m \e[1;36mself\e[0m.\e[1;34mhello\e[0m\n    \e[1;34m3\e[0m:   print \e[31m\e[1;31m'\e[0m\e[31mHello world!\e[1;31m'\e[0m\e[31m\e[0m\n => \e[1;34m4\e[0m:   require \e[31m\e[1;31m'\e[0m\e[31mpry\e[1;31m'\e[0m\e[31m\e[0m; binding.pry\n    \e[1;34m5\e[0m: \e[32mend\e[0m\n\n\e[0G\e[1m\e[1;34mPlay.methods\e[0m\e[0m: hello\n\e[1m\e[1;34mlocals\e[0m\e[0m: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_\nNameError: undefined local variable or method `fghjk' for Play:Class\nfrom (pry):1:in `hello'\nNameError: undefined local variable or method `kweutyalfh' for Play:Class\nfrom (pry):2:in `hello'\n"
       Diff:
       @@ -1,2 +1,17 @@
        Hello world!
       +Frame number: 0/32
       +
       +From: /Users/iiezhachenko/Documents/Repos/bdd-ruby-playground/lib/play.rb @ line 4 Play.hello:
       +
       +    2: def self.hello
       +    3:   print 'Hello world!'
       + => 4:   require 'pry'; binding.pry
       +    5: end
       +
Play.methods: hello
       +locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
       +NameError: undefined local variable or method `fghjk' for Play:Class
       +from (pry):1:in `hello'
       +NameError: undefined local variable or method `kweutyalfh' for Play:Class
       +from (pry):2:in `hello'
     # ./spec/play_spec.rb:5:in `block (2 levels) in <top (required)>'

Anyone faced such issue?

Iezgen
  • 45
  • 4
  • 2
    Doesn't surprise me too much; I would expect RSpec has to grab stdout (and possible stdin) in order to test expectations. Yet another good reason to abstract stuff like the output stream away from the mainline code. – Dave Newton May 15 '16 at 12:23
  • Interesting. I changed code to be: spec/play_spec.rb ` it 'should modify var' do expect(Play.hello(3)).to eq 4 end` lib/play.rb ` def self.hello(arg) var = 1 require 'pry'; binding.pry return var + arg end` Now Pry worked as it should. But what is the reason for such behaviour? And how to workaround it? I need to check that my CLI app prints proper messages. – Iezgen May 15 '16 at 12:36
  • Yup, you have more than one object which is reading/writing to STDIN/STDOUT respectively at the same time. As a result, you're getting weird stuff in your console. – Anthony E May 15 '16 at 12:39
  • If the point is to ensure you're seeing the proper messages then you should either actually test message generation, or provide an abstraction over where those messages go. – Dave Newton May 15 '16 at 13:08
  • Thank you. This is exactly what I will do now. – Iezgen May 15 '16 at 14:17

2 Answers2

0

As the answer by OP indicates, the problem involves console output suppression, which can inadvertently break Pry.

If you check your spec/spec_helper.rb file, there is likely some code inside the RSpec configuration block that is referring to $stderr and/or $stdout. Removing those lines of code should fix the problem.

For other examples of how this output might be getting suppressed, see the answers to this question: Suppress console output during RSpec tests

Dave Powers
  • 2,051
  • 2
  • 30
  • 34
-2

Issue resolved by removing stdout capturing from test. Thanks everyone.

Iezgen
  • 45
  • 4