This question is related to the codebreaker example found in the RSpec book.
See code here: https://github.com/kristianmandrup/rspec-book-codebreaker/tree/master/features
I was wondering if anyone has made a full solution for the codebreaker game.
I am keen to see how to test the outer loop, which decides if the game should continue or not.
The functionality may look like this
- You found the secret code!
- Would you like to try again? : n
- Good-bye
If the user selects ‘y’ then the game starts again.
I am interested to see the scenarios and step definitions.
Would it be something like:
Scenario: user finds secret code
Given the secret code is "1234"
When I guess "1234"
Then I should see "You found the secret code!"
And I should see "Would you like to try again?"
Another spec file:
Background: Found secret code
Given the secret code is "1234"
And I guess "1234"
Scenario: user chooses to quit the game
Given I see "Would you like to try again?"
When I enter "n"
Then I should see "Good-bye"
Scenario: user chooses to continue with the game
Given I see "Would you like to try again?"
When I enter "y"
Then I should see "Enter guess:"
As seen in the link above, currently a double (mock) output object is passed in. All output is captured by this double and then is used in assertions. Input is a bit different. When the application displays “Would you like to try again?”, then the input mock needs reply with ‘y’ or ‘n’, depending on the test. Perhaps this is not the way to go about it?
There is something similar to mimic a user guessing, that step definition looks like this:
When /^I guess "([^\"]*)"$/ do |guess|
@game.guess(guess)
end
This is the current main method:
def generate_secret_code
options = %w[1 2 3 4 5 6]
(1..4).map { options.delete_at(rand(options.length))}.join
end
game = Codebreaker::Game.new(STDOUT)
secret_code = generate_secret_code
at_exit { puts "\n***\nThe secret code was: #{secret_code}\n***" }
game.start(secret_code)
while guess = gets.chomp
game.guess(guess)
end
The outer loop was added without any tests. I would like to know how to deal with the gets.chomp – how can I ‘mock’ that behaviour? Is this how to handle interactive input form the console?
I am actually using SpecFlow and C#, if possible provide a solution for C#.
A Ruby solution may also help…
Thanks
It is possible to launch a console application and attach to its standard input and output streams. See the example in the documentation of
ProcessStartInfo.RedirectStandardInput.A cleaner way (which would also make the tests faster, but wouldn’t qualify as full end-to-end system testing) would be to restructure the application somewhat, so that it uses regular
Streamobjects instead ofConsole.InandConsole.Out; themain()method can pass these classes to the rest of the application. Then, your tests can invoke the other methods directly and passMemoryStreamobjects as the input/output streams.