"output" name collission with RSpec::Matchers::BuiltIn::Output

14 views
Skip to first unread message

Ralph Shnelvar

unread,
Jul 16, 2017, 1:17:56 PM7/16/17
to Ruby on Rails: Talk
I'm following along in The RSpec Book on page 43

The book is careful to specify all the version of the gems it uses.  My problem is likely I am using current gems.

The code I downloaded looks like this
#---
# Excerpted from "The RSpec Book",
# published by The Pragmatic Bookshelf.
# Copyrights apply to this code. It may not be used to create training material,
# courses, books, articles, and the like. Contact us if you are in doubt.
# We make no guarantees that this code is fit for any purpose.
# Visit http://www.pragmaticprogrammer.com/titles/achbd for more book information.
#---
class Output
 
def messages
   
@messages ||= []
 
end

 
def puts(message)
    messages
<< message
 
end
end

def output
 
@output ||= Output.new
end

Given /^I am not yet playing$/ do
end

When /^I start a new game$/ do
  game
= Codebreaker::Game.new(output)
  game
.start
end

Then /^I should see "([^"]*)"$/ do |message|
  output.messages.should include(message)
end

The author says he's creating a "test double" with the lines
class Output
 
def messages
   
@messages ||= []
 
end

 
def puts(message)
    messages
<< message
 
end
end

def output
 
@output ||= Output.new
end

If I use the above code, RSpec will say
  Scenario: start game                          # features/codebreaker_starts_game.feature:7
   
Given I am not yet playing                  # features/step_definitions/codebreaker_steps.rb:34
   
When I start a new game                     # features/step_definitions/codebreaker_steps.rb:37
    Then I should see "Welcome to Codebreaker!" # features/step_definitions/codebreaker_steps.rb:41
      undefined method `messages' for #<RSpec::Matchers::BuiltIn::Output:0x0055e95ffb9728> (NoMethodError)
      ./features/step_definitions/codebreaker_steps.rb:44:in `/^I should see "([^"]*)"$/'
      features/codebreaker_starts_game.feature:10:in `Then I should see "Welcome to Codebreaker!"'
    And I should see "Enter guess:"             # features/step_definitions/codebreaker_steps.rb:41

The "undefined method" message immediately above is not what the book says should be generated.

If, on the other hand, I rename the method named output with output_ralph (see immediately below)
# This works

#---
# Excerpted from "The RSpec Book",
# published by The Pragmatic Bookshelf.
# Copyrights apply to this code. It may not be used to create training material,
# courses, books, articles, and the like. Contact us if you are in doubt.
# We make no guarantees that this code is fit for any purpose.
# Visit http://www.pragmaticprogrammer.com/titles/achbd for more book information.
#---

require "byebug"
# byebug

class Output
 
def messages
   
@messages ||= []
 
end

 
def puts(message)
    messages
<< message
 
end
end

# byebug
def output_ralph
 
# byebug
 
@output ||= Output.new
  ret
= @output
 
# byebug
  ret
end

Given /^I am not yet playing$/ do
end

When /^I start a new game$/ do
 
# byebug
  game
= Codebreaker::Game.new(output_ralph)
  game
.start
end

Then /^I should see "([^"]*)"$/ do |message|
  # output.messages.should include(message)
  # byebug
  # x = output_ralph.messages
  # byebug
 
  expect(
output_ralph.messages).to include(message)
end

then I get the output the book says I should get (immediately below)
  Scenario: start game                          # features/codebreaker_starts_game.feature:7
   
Given I am not yet playing                  # features/step_definitions/codebreaker_steps.rb:34
   
When I start a new game                     # features/step_definitions/codebreaker_steps.rb:37
   
Then I should see "Welcome to Codebreaker!" # features/step_definitions/codebreaker_steps.rb:43
     
expected [] to include "Welcome to Codebreaker!" (RSpec::Expectations::ExpectationNotMetError)
     
./features/step_definitions/codebreaker_steps.rb:49:in `/^I should see "([^"]*)"$/'
      features/codebreaker_starts_game.feature:10:in `
Then I should see "Welcome to Codebreaker!"'
    And I should see "Enter guess:"             # features/step_definitions/codebreaker_steps.rb:43


I suspect I have a name collision with Class: RSpec::Matchers::BuiltIn::Output but I'm damned if I can figure out why.

I guess I could leave the code as-is but ... advice would be appreciated.

Frederick Cheung

unread,
Jul 18, 2017, 10:30:51 AM7/18/17
to Ruby on Rails: Talk


On Sunday, July 16, 2017 at 6:17:56 PM UTC+1, Ralph Shnelvar wrote:

I suspect I have a name collision with Class: RSpec::Matchers::BuiltIn::Output but I'm damned if I can figure out why.

I guess I could leave the code as-is but ... advice would be appreciated.

You are correct. rspec added the ability to test that some code has written something to stdout. You use it like this:

expect { print('foo') }.to output('foo').to_stdout

To make this work, rspec defines an output method (that returns an Output matcher, which is the class that you see) which is the thing colliding with your method

Fred
Reply all
Reply to author
Forward
0 new messages