Extract pure executor of koans

This commit is contained in:
Felipe Sere
2016-04-09 19:16:42 +01:00
parent 153a9df599
commit 7e03cc37a9
5 changed files with 72 additions and 44 deletions

48
lib/execute.ex Normal file
View File

@@ -0,0 +1,48 @@
defmodule Execute do
def run_module(module) do
run_until_failure(module, &run_koan/2)
end
def run_until_failure(module, callback) do
Enum.reduce_while(module.all_koans, :passed, fn(it, _acc) ->
result = callback.(module, it)
if result == :passed do
{:cont, :passed}
else
{:halt, result}
end
end)
end
def run_koan(module, name, args \\ []) do
parent = self()
spawn fn -> exec(module, name, args, parent) end
receive do
:ok -> :passed
error -> {:failed, error, module, name}
end
end
def exec(module, name, args, parent) do
result = apply(module, name, args)
send parent, expand(result)
Process.exit(self(), :kill)
end
def expand(:ok), do: :ok
def expand(error) do
{file, line} = System.stacktrace
|> Enum.drop_while(&in_ex_unit?/1)
|> List.first
|> extract_file_and_line
%{error: error, file: file, line: line}
end
defp in_ex_unit?({ExUnit.Assertions, _, _, _}), do: true
defp in_ex_unit?(_), do: false
defp extract_file_and_line({_, _, _, [file: file, line: line]}) do
{file, line}
end
end

View File

@@ -34,50 +34,10 @@ defmodule Runner do
def run_module(module) do
Display.considering(module)
koans = module.all_koans
passed = Enum.take_while(koans, fn(name) ->
case run_koan(module, name) do
:passed -> true
case Execute.run_module(module) do
{:failed, error, module, name} -> Display.show_failure(error, module, name)
false
end
end)
if Enum.count(koans) == Enum.count(passed) do
:passed
else
:failed
:failed
_ -> :passed
end
end
def run_koan(module, name, args \\ []) do
parent = self()
spawn fn -> exec(module, name, args, parent) end
receive do
:ok -> :passed
error -> {:failed, error, module, name}
end
end
def exec(module, name, args, parent) do
result = apply(module, name, args)
send parent, expand(result)
Process.exit(self(), :kill)
end
def expand(:ok), do: :ok
def expand(error) do
{file, line} = System.stacktrace
|> Enum.drop_while(&in_ex_unit?/1)
|> List.first
|> extract_file_and_line
%{error: error, file: file, line: line}
end
defp in_ex_unit?({ExUnit.Assertions, _, _, _}), do: true
defp in_ex_unit?(_), do: false
defp extract_file_and_line({_, _, _, [file: file, line: line]}), do: {file, line}
end

13
test/executor_test.exs Normal file
View File

@@ -0,0 +1,13 @@
defmodule RunnerTest do
use ExUnit.Case
test "passes a koan" do
assert :passed == Execute.run_module(PassingKoan)
end
test "stops at the first failing koan" do
{:failed, %{error: _, file: file, line: line}, SampleKoan, _name} = Execute.run_module(SampleKoan)
assert file == 'test/support/sample_koan.ex'
assert line == 5
end
end

View File

@@ -232,6 +232,6 @@ defmodule KoansHarnessTest do
end
def run_all(pairs, module) do
Enum.map(pairs, fn ({koan, answer}) -> Runner.run_koan(module, koan, [answer]) end)
Enum.map(pairs, fn ({koan, answer}) -> Execute.run_koan(module, koan, [answer]) end)
end
end

View File

@@ -0,0 +1,7 @@
defmodule PassingKoan do
use Koans
koan "hi there" do
assert 1 == 1
end
end