ドキュメントトリガーテスト駆動 Elixir ( Document Trigger Test Driven Elixir )
概要
Elixir でドキュメントの Example を元にテスト駆動開発をします
前提
Elixri の Doctests を利用します。
詳しくは下記記事を参照
Elixir | Doctests
仕様
FizzBuzzプログラムを作成します
- インターフェースは Fizzbuzz.fizzbuzz(from, to)
- from, to ともに Integer のみ許容
- Integer 以外を指定した場合は、RuntimeError を投げる
- from から to までの FizzBuzz の結果を配列として返却
- 15 の倍数は "FizzBuzz"
- 3 の倍数は "Fizz"
- 5 の倍数は "Buzz"
- 3/5/15 の倍数以外は 入力数値をそのまま返却
手順
プロジェクトの作成
mix
コマンドでプロジェクトテンプレートを生成します。
今回は
- lib/fizzbuzz.ex
- test/fizzbuzz_test.ex
のみを編集します。
$ mix new fizzbuzz
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/fizzbuzz.ex
* creating test
* creating test/test_helper.exs
* creating test/fizzbuzz_test.exs
テストを実行
自動生成直後は、空のプロダクトコードと成功するテスト Example が実装されているため、
1件テストをパスします。
$ mix test
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
.
Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 tests, 0 failures
テストコード:Example をテストするために doctest を呼び出します。
これ以降テストコードは一切変更しません
- test/fizzbuzz_test.exs
defmodule FizzbuzzTest do
use ExUnit.Case
doctest Fizzbuzz
end
- テストを実行。結果は 0 件
$ mix test --trace
FizzbuzzTest
Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
0 tests, 0 failures
プロダクトコード:数値をそのまま返却する Example を追加
- Example を追加
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
"""
def fizzbuzz(from, to) do
end
end
- テストを実行
未実装のためテストに失敗します
$ mix test --trace
lib/fizzbuzz.ex:11: warning: variable from is unused
lib/fizzbuzz.ex:11: warning: variable to is unused
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.00ms)
1) test doc at Fizzbuzz.fizzbuzz/2 (1) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed
code: Fizzbuzz.fizzbuzz(1,2) === [1, 2]
lhs: nil
stacktrace:
lib/fizzbuzz.ex:11: Fizzbuzz (module)
Finished in 0.07 seconds (0.07s on load, 0.00s on tests)
1 tests, 1 failures
Randomized with seed 926333
プロダクトコード:数値をそのまま返却する Example を実装
- lib/fizzbuzz.ex
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(&1))
end
end
- テストを実行
テストをパスしました
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (1) (5.7ms)
Finished in 0.07 seconds (0.07s on load, 0.00s on tests)
1 tests, 0 failures
プロダクトコード:Fizz の Example を追加
- lib/fizzbuzz.exs
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(&1))
end
end
- テストを実行
未実装のためテストに失敗します
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (1) (4.9ms)
* doc at Fizzbuzz.fizzbuzz/2 (2) (0.02ms)
1) test doc at Fizzbuzz.fizzbuzz/2 (2) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed
code: Fizzbuzz.fizzbuzz(3, 3) === ["Fizz"]
lhs: [3]
stacktrace:
lib/fizzbuzz.ex:18: Fizzbuzz (module)
Finished in 0.07 seconds (0.07s on load, 0.00s on tests)
2 tests, 1 failures
Randomized with seed 118398
プロダクトコード:Fizz を実装
- lib/fizzbuzz.ex
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
テストをパスしました
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (2) (4.4ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.06ms)
Finished in 0.09 seconds (0.09s on load, 0.00s on tests)
2 tests, 0 failures
Randomized with seed 629312
プロダクトコード:Buzz の Example を追加
- lib/fizzbuzz.exs
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
未実装のためテストに失敗します
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (2) (4.0ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.02ms)
* doc at Fizzbuzz.fizzbuzz/2 (3) (0.06ms)
1) test doc at Fizzbuzz.fizzbuzz/2 (3) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed
code: Fizzbuzz.fizzbuzz(5, 5) === ["Buzz"]
lhs: [5]
stacktrace:
lib/fizzbuzz.ex:23: Fizzbuzz (module)
Finished in 0.08 seconds (0.08s on load, 0.00s on tests)
3 tests, 1 failures
Randomized with seed 857202
プロダクトコード:Buzz を実装
- lib/fizzbuzz.ex
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) when rem(n, 5) == 0 do
"Buzz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
テストをパスしました
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (3) (3.9ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.02ms)
* doc at Fizzbuzz.fizzbuzz/2 (2) (0.1ms)
Finished in 0.08 seconds (0.08s on load, 0.00s on tests)
3 tests, 0 failures
Randomized with seed 677241
プロダクトコード:FizzBuzz の Example を追加
- lib/fizzbuzz.exs
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
# only FizzBuzz
iex> Fizzbuzz.fizzbuzz(15, 15)
["FizzBuzz"]
iex> Fizzbuzz.fizzbuzz(30, 30)
["FizzBuzz"]
# mix case
iex> Fizzbuzz.fizzbuzz(1, 15)
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) when rem(n, 5) == 0 do
"Buzz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
未実装のためテストに失敗します
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (2) (4.9ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.03ms)
* doc at Fizzbuzz.fizzbuzz/2 (3) (0.05ms)
* doc at Fizzbuzz.fizzbuzz/2 (5) (0.1ms)
1) test doc at Fizzbuzz.fizzbuzz/2 (5) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed
code: Fizzbuzz.fizzbuzz(1, 15) === [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
lhs: [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz",
13, 14, "Fizz"]
stacktrace:
lib/fizzbuzz.ex:33: Fizzbuzz (module)
* doc at Fizzbuzz.fizzbuzz/2 (4) (0.1ms)
2) test doc at Fizzbuzz.fizzbuzz/2 (4) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed
code: Fizzbuzz.fizzbuzz(15, 15) === ["FizzBuzz"]
lhs: ["Fizz"]
stacktrace:
lib/fizzbuzz.ex:33: Fizzbuzz (module)
Finished in 0.09 seconds (0.09s on load, 0.00s on tests)
5 tests, 2 failures
Randomized with seed 64741
プロダクトコード:FizzBuzz を実装
- lib/fizzbuzz.ex
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
# only FizzBuzz
iex> Fizzbuzz.fizzbuzz(15, 15)
["FizzBuzz"]
iex> Fizzbuzz.fizzbuzz(30, 30)
["FizzBuzz"]
# mix case
iex> Fizzbuzz.fizzbuzz(1, 15)
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
defp fizzbuzz(n) when rem(n, 15) == 0 do
"FizzBuzz"
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) when rem(n, 5) == 0 do
"Buzz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
テストをパスしました
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (2) (13.8ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.01ms)
* doc at Fizzbuzz.fizzbuzz/2 (4) (0.07ms)
* doc at Fizzbuzz.fizzbuzz/2 (3) (0.02ms)
* doc at Fizzbuzz.fizzbuzz/2 (5) (0.01ms)
Finished in 0.1 seconds (0.09s on load, 0.01s on tests)
5 tests, 0 failures
Randomized with seed 768461
プロダクトコード:from / to に不正な引数( Integer 以外)を指定する Example を追加
- lib/fizzbuzz.exs
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
# only FizzBuzz
iex> Fizzbuzz.fizzbuzz(15, 15)
["FizzBuzz"]
iex> Fizzbuzz.fizzbuzz(30, 30)
["FizzBuzz"]
# mix case
iex> Fizzbuzz.fizzbuzz(1, 15)
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
# args 'to' not integer
iex> Fizzbuzz.fizzbuzz("1", 15)
** (RuntimeError) invalid argument
(fizzbuzz) lib/fizzbuzz.ex:37: Fizzbuzz.fizzbuzz/2
# args 'to' not integer
iex> Fizzbuzz.fizzbuzz(1, "15")
** (RuntimeError) invalid argument
"""
def fizzbuzz(from, to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
defp fizzbuzz(n) when rem(n, 15) == 0 do
"FizzBuzz"
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) when rem(n, 5) == 0 do
"Buzz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
未実装のためテストに失敗します
$ mix test --trace
warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell)
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (6) (10.5ms)
1) test doc at Fizzbuzz.fizzbuzz/2 (6) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed: expected exception RuntimeError with message "invalid argument" but got Protocol.UndefinedError with message "protocol Range.Iterator not implemented for \"1\""
code: Fizzbuzz.fizzbuzz("1", 15)
stacktrace:
lib/fizzbuzz.ex:42: Fizzbuzz (module)
* doc at Fizzbuzz.fizzbuzz/2 (1) (1.4ms)
* doc at Fizzbuzz.fizzbuzz/2 (4) (1.8ms)
* doc at Fizzbuzz.fizzbuzz/2 (5) (1.2ms)
* doc at Fizzbuzz.fizzbuzz/2 (2) (0.07ms)
* doc at Fizzbuzz.fizzbuzz/2 (7) (6.9ms)
2) test doc at Fizzbuzz.fizzbuzz/2 (7) (FizzbuzzTest)
test/fizzbuzz_test.exs:3
Doctest failed: expected exception RuntimeError with message "invalid argument" but got FunctionClauseError with message "no function clause matching in Range.Iterator.Integer.next/2"
code: Fizzbuzz.fizzbuzz(1, "15")
stacktrace:
lib/fizzbuzz.ex:42: Fizzbuzz (module)
* doc at Fizzbuzz.fizzbuzz/2 (3) (0.2ms)
Finished in 0.1 seconds (0.1s on load, 0.02s on tests)
7 tests, 2 failures
Randomized with seed 32922
プロダクトコード:from / to に不正な引数( Integer 以外)を指定した場合に、RuntimeError を投げるように実装
- lib/fizzbuzz.ex
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
# only FizzBuzz
iex> Fizzbuzz.fizzbuzz(15, 15)
["FizzBuzz"]
iex> Fizzbuzz.fizzbuzz(30, 30)
["FizzBuzz"]
# mix case
iex> Fizzbuzz.fizzbuzz(1, 15)
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
# args 'to' not integer
iex> Fizzbuzz.fizzbuzz("1", 15)
** (RuntimeError) invalid argument
(fizzbuzz) lib/fizzbuzz.ex:37: Fizzbuzz.fizzbuzz/2
# args 'to' not integer
iex> Fizzbuzz.fizzbuzz(1, "15")
** (RuntimeError) invalid argument
"""
def fizzbuzz(from, to) when is_integer(from) and is_integer(to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
def fizzbuzz(_from, _to) do
raise "invalid argument"
end
defp fizzbuzz(n) when rem(n, 15) == 0 do
"FizzBuzz"
end
defp fizzbuzz(n) when rem(n, 3) == 0 do
"Fizz"
end
defp fizzbuzz(n) when rem(n, 5) == 0 do
"Buzz"
end
defp fizzbuzz(n) do
n
end
end
- テストを実行
テストをパスしました
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (6) (0.9ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (3.8ms)
* doc at Fizzbuzz.fizzbuzz/2 (4) (0.03ms)
* doc at Fizzbuzz.fizzbuzz/2 (7) (0.04ms)
* doc at Fizzbuzz.fizzbuzz/2 (2) (0.03ms)
* doc at Fizzbuzz.fizzbuzz/2 (3) (0.05ms)
* doc at Fizzbuzz.fizzbuzz/2 (5) (0.02ms)
Finished in 0.1 seconds (0.1s on load, 0.00s on tests)
7 tests, 0 failures
Randomized with seed 951920
プロダクトコード:リファクタリング
各プライベート関数の処理が短いので1行で記述するように修正します
- lib/fizzbuzz.ex
defmodule Fizzbuzz do
@doc ~S"""
FizzBuzz.
## Examples
# only other numbers
iex> Fizzbuzz.fizzbuzz(1,2)
[1, 2]
# only Fizz
iex> Fizzbuzz.fizzbuzz(3, 3)
["Fizz"]
iex> Fizzbuzz.fizzbuzz(6, 6)
["Fizz"]
# only Buzz
iex> Fizzbuzz.fizzbuzz(5, 5)
["Buzz"]
iex> Fizzbuzz.fizzbuzz(10, 10)
["Buzz"]
# only FizzBuzz
iex> Fizzbuzz.fizzbuzz(15, 15)
["FizzBuzz"]
iex> Fizzbuzz.fizzbuzz(30, 30)
["FizzBuzz"]
# mix case
iex> Fizzbuzz.fizzbuzz(1, 15)
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
# args 'to' not integer
iex> Fizzbuzz.fizzbuzz("1", 15)
** (RuntimeError) invalid argument
(fizzbuzz) lib/fizzbuzz.ex:37: Fizzbuzz.fizzbuzz/2
# args 'to' not integer
iex> Fizzbuzz.fizzbuzz(1, "15")
** (RuntimeError) invalid argument
"""
def fizzbuzz(from, to) when is_integer(from) and is_integer(to) do
from..to |> Enum.map(&(fizzbuzz/1))
end
def fizzbuzz(_from, _to), do: raise "invalid argument"
defp fizzbuzz(num) when rem(num, 15) == 0, do: "FizzBuzz"
defp fizzbuzz(num) when rem(num, 5) == 0, do: "Buzz"
defp fizzbuzz(num) when rem(num, 3) == 0, do: "Fizz"
defp fizzbuzz(num), do: num
end
- テストを実行
テストをパスしました。
テストを壊さずにリファクタリングに成功しました。
$ mix test --trace
Compiled lib/fizzbuzz.ex
Generated fizzbuzz.app
FizzbuzzTest
* doc at Fizzbuzz.fizzbuzz/2 (4) (4.8ms)
* doc at Fizzbuzz.fizzbuzz/2 (7) (1.9ms)
* doc at Fizzbuzz.fizzbuzz/2 (1) (0.1ms)
* doc at Fizzbuzz.fizzbuzz/2 (2) (0.1ms)
* doc at Fizzbuzz.fizzbuzz/2 (5) (0.1ms)
* doc at Fizzbuzz.fizzbuzz/2 (3) (0.1ms)
* doc at Fizzbuzz.fizzbuzz/2 (6) (0.08ms)
Finished in 0.1 seconds (0.1s on load, 0.01s on tests)
7 tests, 0 failures
Randomized with seed 216728
完成したプロジェクトを実行
$ mix run -e 'IO.inspect Fizzbuzz.fizzbuzz(1, 30)'
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14,
"FizzBuzz", 16, 17, "Fizz", 19, "Buzz", "Fizz", 22, 23, "Fizz", "Buzz", 26,
"Fizz", 28, 29, "FizzBuzz"]
$ mix run -e 'IO.inspect Fizzbuzz.fizzbuzz("1", 30)'
** (RuntimeError) invalid argument
(fizzbuzz) lib/fizzbuzz.ex:46: Fizzbuzz.fizzbuzz/2
(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
(stdlib) erl_eval.erl:865: :erl_eval.expr_list/6
(stdlib) erl_eval.erl:407: :erl_eval.expr/5
(elixir) lib/code.ex:140: Code.eval_string/3
(elixir) lib/enum.ex:537: Enum."-each/2-lists^foreach/1-0-"/2
$ mix run -e 'IO.inspect Fizzbuzz.fizzbuzz(1, "30")'
** (RuntimeError) invalid argument
(fizzbuzz) lib/fizzbuzz.ex:46: Fizzbuzz.fizzbuzz/2
(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
(stdlib) erl_eval.erl:865: :erl_eval.expr_list/6
(stdlib) erl_eval.erl:407: :erl_eval.expr/5
(elixir) lib/code.ex:140: Code.eval_string/3
(elixir) lib/enum.ex:537: Enum."-each/2-lists^foreach/1-0-"/2
$ mix run -e 'IO.inspect Fizzbuzz.fizzbuzz(15, 1)'
["FizzBuzz", 14, 13, "Fizz", 11, "Buzz", "Fizz", 8, 7, "Fizz", "Buzz", 4, "Fizz", 2, 1]
Complete!
明日は @keithseahus さんです。