The private method "puts"? Can't pass cucumber test in RSpec Book Codebreaker example
I am following in RSpec Book and I am unable to pass the cucumber test to pass a specific location. I even tried to run the cucumber in the source code from the book and it still won't work. I'm not sure if it's a fact that I am using a newer version of cucumber, but there must be a way to do it!
When I get to the point where the program should start a new game, I'm told that the undefined method "puts". Why is it undefined, and how else am I supposed to grab what the program puts
exited in Cucumber? Running a test in RSpec to make sure the game is posting a message is working fine, not sure how to do it in cucumbers.
(cucumber version 1.3.17, Ruby version 2.1.2)
Basically, I have the following possibilities:
Feature: code-breaker starts game
As a code-breaker
I want to start a game
So that I can break the code
Scenario: start game
Given I am not yet playing
When I start a new game
Then I should see "Welcome to Codebreaker!"
And I should see "Enter guess:"
and these step definitions:
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
and this ruby code:
module Codebreaker
class Game
def initialize(output)
@output = output
end
def start
@output.puts 'Welcome to Codebreaker!'
end
end
end
and I am getting this error:
When I start a new game # features/step_definitions/codebreaker_steps.rb:16
private method `puts' called for #<RSpec::Matchers::BuiltIn::Output:0x007fa4ea200ad0> (NoMethodError)
./lib/codebreaker/game.rb:10:in `start'
./features/step_definitions/codebreaker_steps.rb:18:in `/^I start a new game$/'
features/codebreaker_starts_game.feature:7:in `When I start a new game'
How do I fix this so that it runs in a cucumber?
source to share
There are many things that have changed since this RSpec book was published, but I got it by replacing your file code_break_steps.rb
with this:
Given /^I am not yet playing$/ do
end
When /^I start a new game$/ do
@messenger = StringIO.new
game = Codebreaker::Game.new(@messenger)
game.start
end
Then /^I should see "([^"]*)"$/ do |message|
expect(@messenger.string.split("\n")).to include(message)
end
RSpec 3 has a class that you are trying to overwrite with a name Output
and this is causing too much confusion. I just simplified it so you are still talking to each other along with stdout
.
You can use the same syntax should
on the last line, but it will soon be deprecated, so it's better to get used to the syntax expect
I was using. For now, if you're more confusing, you can still use:
@messenger.string.split("\n").should include(message)
source to share
I am following this book right now and tried Anthony's technique. But I got into trouble again a little later in the book (most likely because I'm kind of new to Rails and couldn't translate Anthony's technique to another case ^^). But anyway, I found an easier way to not interfere with the RSpec Output class and still not reject the flow of lessons too much:
- rename the class
Output
to something else, sayOOutput
- and change all variables
Output
too_output
.
Et voilà; -)
source to share
I was only able to accomplish this specific example with two changes to the same "codebreaker_steps.rb" file, so you can still follow the book's tutorial. You don't need to touch the class name, only the output () method following it.
RSpec 3 contains an output () method that causes conflicts when trying to define another output () method. So, knowing this, take the instructions for the book:
def output
@output ||= Output.new
end
and rename it to:
def see_output #new
@output ||= Output.new
end
(or name something that makes sense for the project)
Then go to the definition of the When () method:
When /^I start a new game$/ do
game = Codebreaker::Game.new(output)
game.start
end
and update the second line:
When ("I start a new game") do
game = Codebreaker::Game.new(see_output) #new
game.start
end
source to share