Skip to content

Instantly share code, notes, and snippets.

@mislav
Forked from ryanb/quiz.rb
Created May 15, 2009 18:18
Show Gist options
  • Save mislav/112354 to your computer and use it in GitHub Desktop.
Save mislav/112354 to your computer and use it in GitHub Desktop.
Ryan Bates community challenge solution
# COMMUNITY CHALLENGE
#
# How would you test this Quiz#problem method? Only two rules:
#
# 1. You must test the order the gets/puts happen. The tests should not
# still pass if "gets" happens before "puts", etc.
#
# 2. No changing the Quiz class implementation/structure. But you can
# use whatever framework you want for the tests.
#
# Note: The first rule used to be "no mocking" but I changed it. If you
# can accomplish the first rule with mocks then go ahead. I'm looking
# for the simplest/cleanest solution whatever that may be.
#
class Quiz
def initialize(input = STDIN, output = STDOUT)
@input = input
@output = output
end
def problem
first = rand(10)
second = rand(10)
@output.puts "What is #{first} + #{second}?"
answer = @input.gets
if answer.to_i == first + second
@output.puts "Correct!"
else
@output.puts "Incorrect!"
end
end
end
require "test/unit"
require "stringio"
require "rubygems"
require "mocha"
# special StringIO with a separate read cursor that can
# be used to re-read the IO from beginning unobtrusively
class RereadableStringIO < StringIO
def initialize(*args)
super
@read_pos = pos
end
def rereading
old_pos = pos
begin
seek @read_pos
result = yield self
@read_pos = pos
return result
ensure
seek old_pos
end
end
def reread
rereading { read }
end
end
# mocks a STDIN; only supports `gets`
class FakeInput
def initialize
@responses = []
end
def push(*args, &block)
val = args.empty?? block : args.first
@responses.push(val)
end
def gets
val = @responses.pop
val.respond_to?(:call) ? val.call : val
end
end
class QuizTest < Test::Unit::TestCase
def setup
@input = FakeInput.new
@output = RereadableStringIO.new
end
def test_correct
@input.push {
question = @output.reread
_, first, second = question.match(/^What is (\d+) \+ (\d+)\?\n$/).to_a
(first.to_i + second.to_i).to_s + $/
}
quiz = Quiz.new(@input, @output)
quiz.problem
assert_equal "Correct!\n", @output.reread
end
def test_incorrect
@input.push("-1#{$/}")
quiz = Quiz.new(@input, @output)
quiz.problem
@output.rereading { |io| io.gets }
assert_equal "Incorrect!\n", @output.reread
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment