1. 仕様

  • 3で割り切れる場合は「Fizz」を出力する。

  • 5で割り切れる場合は「Buzz」を出力する。

  • 両者で割り切れる場合は「FizzBuzz」を出力する。

  • 上記以外の場合は与えられた数字を出力する。

  • 指定された回数だけ繰り返し実行する。

2. 設計

2.1. TODOリスト

  • ✓ 「Fizz」を出力できるようにする

  • ✓ 「Buzz」を出力できるようにする

  • ✓ 「FizzBuzz」を出力できるようにする

  • ✓ 繰り返し実行できるようにする

2.2. ユースケース図

diag 18b116208c0839035ae385fac67dfa1d

2.3. クラス図

diag adeda49ba7b0005cfe35cfe3af0a606e

2.4. シーケンス図

diag bcd05c6241086fc666de4ee53d6558c0

3. 開発

3.1. テストコード

require 'test/unit'
require 'simplecov'
SimpleCov.start
require_relative '../../../fizz_buzz/fizz_buzz'

class FizzBuzzTest < Test::Unit::TestCase
  test '3ならFizzを返す' do
    assert_equal('Fizz', FizzBuzz.generate(3))
    assert_not_equal('Fizz', FizzBuzz.generate(1))
  end

  test '5ならBuzzを返す' do
    assert_equal('Buzz', FizzBuzz.generate(5))
    assert_not_equal('Buzz', FizzBuzz.generate(1))
  end

  test '15ならFizzBuzzを返す' do
    assert_equal('FizzBuzz', FizzBuzz.generate(15))
    assert_not_equal('FizzBuzz', FizzBuzz.generate(1))
  end

  test '条件を満たさない場合は値を返す' do
    assert_equal('1', FizzBuzz.generate(1))
    assert_equal('101', FizzBuzz.generate(101))
  end

  test "5ならば[1, 2, 'Fizz', 4, 'Buzz']を返す" do
    assert_equal(%w[1 2 Fizz 4 Buzz], FizzBuzz.iterate(5))
  end

  test "15ならば[1, 2, 'Fizz', 4, 'Buzz', 6, 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz']を返す" do
    assert_equal(%w[1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz], FizzBuzz.iterate(15))
  end
end
# frozen_string_literal: true

require 'json'
require 'test/unit'
require 'mocha/test_unit'
require 'simplecov'
SimpleCov.start
require_relative '../../../fizz_buzz/app'

class FizzBuzzTest < Test::Unit::TestCase
  sub_test_case '#generate' do
    def test_3ならばFizzを返す
      @mock_response = {
          statusCode: 200,
          body: 'Fizz'
      }
      @event = {
          queryStringParameters: { number: '3' },
      }
      expects(:generate).with(event: @event, context: '').returns(@mock_response)

      response = generate(event: @event, context: '')
      result = response[:body]

      assert_equal(200, response[:statusCode])
      assert_equal('Fizz', result)
    end
  end

  sub_test_case '#iterate' do
    def test_5ならば配列を返す
      @mock_response = {
          statusCode: 200,
          'body': ['1', '2', 'Fizz', '4', 'Buzz']
      }
      @event = {
          "body" => "{\"count\": \"5\"}"
      }
      expects(:iterate).with(event: @event, context: '').returns(@mock_response)

      response = iterate(event: @event, context: '')
      result = response[:body]

      assert_equal(200, response[:statusCode])
      assert_equal(%w[1 2 Fizz 4 Buzz], result)
    end
  end
end

3.2. プロダクトコード

# frozen_string_literal: true

class FizzBuzz
  def self.generate(number)
    value = number

    if (number % 3).zero? && (number % 5).zero?
      value = 'FizzBuzz'
    elsif (number % 3).zero?
      value = 'Fizz'
    elsif (number % 5).zero?
      value = 'Buzz'
    end

    value.to_s
  end

  def self.iterate(count)
    array = []
    (1..count).each { |n| array.push(FizzBuzz.generate(n)) }
    array
  end
end
# frozen_string_literal: true

require 'httparty'
require 'json'
require_relative 'fizz_buzz'

def generate(event:, context:)
  data = nil
  number = 0
  unless event['queryStringParameters'].nil?
    unless event['queryStringParameters']['number'].nil?
      number = event['queryStringParameters']['number']
    end
  end

  begin
    data = FizzBuzz.generate(number.to_i)
  rescue HTTParty::Error => error
    puts "Application error occurred: #{error.inspect}"
    create_response(500, error.inspect)
  end

  puts "Application execute with params: #{number}"
  create_response(200, data)
end

def iterate(event:, context:)
  data = nil
  params = { Item: JSON.parse(event['body']) }
  begin
    count = params[:Item]['count']
    data = FizzBuzz.iterate(count.to_i)
  rescue HTTParty::Error => error
    puts "Application error occurred: #{error.inspect}"
    create_response(500, error.inspect)
  end

  puts "Application execute with params: #{params[:Item]}"
  create_response(200, data)
end

private

def create_response(status_code, data)
  {
      statusCode: status_code,
      headers: {
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': '*'
      },
      body: data
  }
end

4. 参照