Skip to content

Instantly share code, notes, and snippets.

@ljsc
Created November 12, 2013 05:40
Show Gist options
  • Save ljsc/7426053 to your computer and use it in GitHub Desktop.
Save ljsc/7426053 to your computer and use it in GitHub Desktop.
East oriented fizzbuzz
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