Created
November 12, 2013 05:40
-
-
Save ljsc/7426053 to your computer and use it in GitHub Desktop.
East oriented fizzbuzz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module FizzBuzz | |
class Runner | |
attr_writer :handlers | |
def initialize(output) | |
@output = output | |
end | |
def run(n) | |
n.times { |n| round(n+1) } | |
end | |
def round(n) | |
handlers.each do |handler| | |
handler.match(n, @output) do return self end | |
end | |
end | |
private | |
def handlers | |
@handlers || [FizzBuzz, Buzz, Fizz, Boring].map(&:new) | |
end | |
class Fizz | |
def match(value, output) | |
if value % 3 == 0 | |
output.print("Fizz") | |
yield | |
end | |
end | |
end | |
class Buzz | |
def match(value, output) | |
if value % 5 == 0 | |
output.print("Buzz") | |
yield | |
end | |
end | |
end | |
class FizzBuzz | |
def match(value, output) | |
if value % 15 == 0 | |
output.print("FizzBuzz") | |
yield | |
end | |
end | |
end | |
class Boring | |
def match(value, output) | |
output.print(value.to_s) | |
yield | |
end | |
end | |
end | |
require 'minitest' | |
require 'rspec/mocks' | |
class Test < MiniTest::Test | |
def setup | |
RSpec::Mocks.setup(self) | |
end | |
def teardown | |
RSpec::Mocks.verify | |
ensure | |
RSpec::Mocks.teardown | |
end | |
end | |
class AcceptanceTests < Test | |
def test_all | |
result = fizzbuzz_upto(15) | |
assert_equal %w{1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz}, result | |
end | |
class TestOutput | |
require 'stringio' | |
def initialize | |
@buffer = StringIO.new | |
end | |
def print(string) | |
@buffer.puts(string) | |
end | |
def result | |
@buffer.string.split("\n") | |
end | |
end | |
def fizzbuzz_upto(n) | |
output = TestOutput.new | |
runner = Runner.new(output) | |
runner.run(n) | |
output.result | |
end | |
end | |
class RunnerTests < Test | |
def setup | |
super | |
@output = double | |
end | |
def run_with_handler | |
runner = Runner.new(@output) | |
runner.handlers = [@handler] | |
runner.round(1) | |
end | |
def test_delegation_when_match | |
@handler = double(match: true) | |
expect(@handler).to receive(:match).and_yield | |
run_with_handler | |
end | |
def test_no_match | |
@handler = double(match: false) | |
expect(@handler).to receive(:match) | |
run_with_handler | |
end | |
end | |
module HandlerTests | |
module HitTest | |
def test_handler_hit | |
@output = double | |
expect(@output).to receive(:print).with(label) | |
expect(self).to receive(:block_called) | |
handler.match(value, @output) { block_called } | |
end | |
end | |
module MissTest | |
def test_handler_miss | |
@output = double | |
expect(@output).not_to receive(:print).with(label) | |
expect(self).not_to receive(:block_called) | |
handler.match(value+1, @output) { block_called } | |
end | |
end | |
class FizzTest < Test | |
include HitTest | |
include MissTest | |
def handler; Runner::Fizz.new end | |
def label; "Fizz" end | |
def value; 3 end | |
end | |
class BuzzTest < Test | |
include HitTest | |
include MissTest | |
def handler; Runner::Buzz.new end | |
def label; "Buzz" end | |
def value; 5 end | |
end | |
class FizzBuzzTest < Test | |
include HitTest | |
include MissTest | |
def handler; Runner::FizzBuzz.new end | |
def label; "FizzBuzz" end | |
def value; 15 end | |
end | |
class BoringTest < Test | |
include HitTest | |
def handler; Runner::Boring.new end | |
def label; "2" end | |
def value; 2 end | |
end | |
end | |
end | |
if $0 == __FILE__ | |
require 'minitest/autorun' | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment