Michael Cordell's Blog

Guard and Capybara's save_and_open_page

I noticed a problem while running Guard where it would appear to malfunction and become unresponsive. The tests would still run or at least complete (according to growl), but I wouldn’t see errors and the guard prompt would never return. I wasn’t sure quite why this was happening. Here’s a sample of what would come up:

Running tests with args ["--drb", "-f", "progress", "-r", "/Users/michael/.rvm/gems/ruby-1.9.3-p392/gems/guard-rspec-1.2.1/lib/guard/rspec/formatters/notification_rspec.rb", "-f", "Guard::RSpec::Formatter::NotificationRSpec", "--out", "/dev/null", "--failure-exit-code", "2", "spec/requests/trick_pages_spec.rb"]...

It would hang here indefinitely, but would apparently still be working because it would run tests on save (growl notified me). It wasn’t clear initially that this was due to me using Capybara’s save_and_open_page but I am fairly convinced that this is why. Here is my relevant installed gems:

Using capybara (1.1.2)
Using guard (1.6.2)
Using guard-livereload (1.3.0)
Using guard-rspec (1.2.1)
Using spork (0.9.2)
Using guard-spork (1.5.0)
Using rspec-core (2.11.1)
Using rspec-expectations (2.11.3)
Using rspec-mocks (2.11.3)
Using rspec (2.11.0)
Using rspec-rails (2.11.0)

According to this SO question and this github issue STDOUT and STDERR are being switched by capybara, therefore Guard is no longer outputting to the terminal.

The SO gives the answer, but isn’t quite clear about where the solution should go. Also, it includes the STDOUT, STDERR line which I omitted because it doesn’t appear to actually fix the issue and instead generates a bunch of constant overwriting warnings. So, add this to “spec_helper” in your spec directory:

RSpec.configure do |config|
  config.before(:each) do
    @old_stdout, @old_stderr = STDOUT, STDERR

  config.after(:each) do
    $stdout, $stderr = @old_stdout, @old_stderr

And guard will now function happily. As a final note, you can put this before and after blocks in your individual test files (where you use save_and_open_page) if you want to reduce the theoretical overhead of doing this on every test.