Merge pull request #1 from heruku/autorunner

Autorunner
This commit is contained in:
Makis Otman
2015-12-18 08:51:46 +00:00
6 changed files with 83 additions and 33 deletions

44
lib/display.ex Normal file
View File

@@ -0,0 +1,44 @@
defmodule Display do
alias IO.ANSI
@current_dir File.cwd!
def show_failure(%{expr: expr}, module, name) do
IO.puts("")
IO.puts("Now meditate upon #{display_module(module)}")
IO.puts("---------------------------------------")
IO.puts("Assertion failed in #{source_file(module)}:#{line_number(expr)}")
IO.puts(display_koan(name))
IO.puts(format_red(Macro.to_string(expr)))
end
def considering(module) do
IO.puts("Considering #{display_module(module)}...")
end
def before_run do
IO.puts("")
IO.puts("")
end
defp line_number({_, [line: line], _}) do
line
end
defp source_file(module) do
module.__info__(:compile)
|> Dict.get(:source)
|> Path.relative_to(@current_dir)
end
defp format_red(str) do
Enum.join([ANSI.red, str, ANSI.reset], "")
end
defp display_module(module) do
Module.split(module) |> List.last
end
defp display_koan(name) do
String.replace(to_string(name), Koans.prefix, "")
end
end

View File

@@ -1,6 +1,8 @@
defmodule Koans do
@prefix "koan: "
defmacro koan(name, body) do
compiled_name = :"koan: #{name}"
compiled_name = :"#{prefix}#{name}"
quote do
def unquote(compiled_name)() do
try do
@@ -19,4 +21,8 @@ defmodule Koans do
import ExUnit.Assertions
end
end
def prefix do
@prefix
end
end

View File

@@ -2,7 +2,11 @@ defmodule Mix.Tasks.Meditate do
use Mix.Task
def run(_) do
Application.ensure_all_started(:elixir_koans)
Code.compiler_options(ignore_module_conflict: true)
Watcher.start
Runner.run
:timer.sleep(:infinity)
end
end

View File

@@ -1,31 +1,32 @@
defmodule Runner do
alias IO.ANSI
@modules [
Equalities,
Lists
]
def run do
IO.puts("")
Enum.take_while(@modules, fn(mod) ->
run(Equalities)
end
def run(start_module) do
Display.before_run
start_idx = Enum.find_index(@modules, &(&1 == start_module))
Enum.drop(@modules, start_idx)
|> Enum.take_while(fn(mod) ->
run_module(mod) == :passed
end)
end
def run_module(module) do
IO.puts("Considering #{display_module(module)}...")
Display.considering(module)
functions = module.__info__(:functions)
koans = Enum.map(functions, fn({name, _arity}) -> name end)
|> Enum.filter(&koan?/1)
koans = extract_koans_from(module)
passed = Enum.take_while(koans, fn(name) ->
run_koan(module, name) == :passed
end)
if Enum.count(koans) == Enum.count(passed) do
:passed
else
@@ -37,33 +38,18 @@ defmodule Runner do
case apply(module, name, []) do
:ok -> :passed
error ->
show_failure(error, module, name)
Display.show_failure(error, module, name)
:failed
end
end
def show_failure(%{expr: expr}, module, name) do
IO.puts("")
IO.puts("Now meditate upon #{display_module(module)}")
IO.puts("---------------------------------------")
IO.puts("Assertion failed!")
IO.puts(display_koan(name))
IO.puts(format_red(Macro.to_string(expr)))
end
def format_red(str) do
Enum.join([ANSI.red, str, ANSI.reset], "")
defp extract_koans_from(module) do
module.__info__(:functions)
|> Enum.map(fn({name, _arity}) -> name end)
|> Enum.filter(&koan?/1)
end
defp koan?(fun_name) do
String.starts_with?(to_string(fun_name), "koan: ")
end
defp display_module(module) do
Module.split(module) |> List.last
end
defp display_koan(name) do
String.replace(to_string(name), "koan: ", "")
String.starts_with?(to_string(fun_name), Koans.prefix)
end
end

View File

@@ -0,0 +1,10 @@
defmodule Watcher do
use ExFSWatch, dirs: ["lib/koans"]
def callback(file, events) do
if Enum.member?(events, :modified) do
[{mod, _}] = Code.load_file(file)
Runner.run(mod)
end
end
end

View File

@@ -9,7 +9,7 @@ defmodule Koans.Mixfile do
end
def application do
[applications: [:logger]]
[applications: [:exfswatch, :logger]]
end
defp deps do