Merge pull request #41 from ukutaht/test_our_koans

Test our koans
This commit is contained in:
Uku Taht
2016-03-12 17:09:24 +02:00
7 changed files with 124 additions and 28 deletions

8
lib/ast_mangler.ex Normal file
View File

@@ -0,0 +1,8 @@
defmodule ASTMangler do
def expand(ast, replacement) do
Macro.prewalk(ast, fn(node) -> update(node, replacement) end)
end
def update(:__, replacement), do: replacement
def update(node, _), do: node
end

View File

@@ -1,6 +1,7 @@
defmodule Koans do defmodule Koans do
defmacro koan(name, body) do defmacro koan(name, body) do
compiled_name = String.to_atom(name) compiled_name = String.to_atom(name)
mangled_body = ASTMangler.expand(body, quote do: answer)
quote do quote do
@koans unquote(compiled_name) @koans unquote(compiled_name)
def unquote(compiled_name)() do def unquote(compiled_name)() do
@@ -11,6 +12,11 @@ defmodule Koans do
e in _ -> e e in _ -> e
end end
end end
def unquote(compiled_name)(answer) do
unquote(mangled_body)
:ok
end
end end
end end

View File

@@ -2,22 +2,22 @@ defmodule Equalities do
use Koans use Koans
koan "We shall contemplate truth by testing reality, via equality" do koan "We shall contemplate truth by testing reality, via equality" do
assert true == true assert true == :__
end end
koan "To understand reality, we must compare our expectations against reality" do koan "To understand reality, we must compare our expectations against reality" do
assert 2 == 1 + 1 assert 2 == 1 + :__
end end
koan "Some things may appear different, but be the same" do koan "Some things may appear different, but be the same" do
assert 1 == 2 / 2 assert 1 == 2 / :__
end end
koan "Something is not equal to nothing" do koan "Something is not equal to nothing" do
assert !(1 == nil) assert !(:__ == nil)
end end
koan "When things cannot be equal, they must be different" do koan "When things cannot be equal, they must be different" do
refute :something == 4 refute :__ == 4
end end
end end

View File

@@ -2,67 +2,70 @@ defmodule Lists do
use Koans use Koans
koan "We can see what is ahead" do koan "We can see what is ahead" do
assert List.first([1, 2, 3]) == 1 assert List.first([1, 2, 3]) == :__
end end
koan "Checking what's trailing is also simple" do koan "Checking what's trailing is also simple" do
assert List.last([1, 2, 3]) == 3 assert List.last([1, 2, 3]) == :__
end end
koan "Diversity is embraced" do koan "Diversity is embraced" do
assert [1, 2] ++ [:a, "b"] == [1, 2, :a, "b"] assert [1, 2] ++ [:a, "b"] == :__
end end
koan "Things can evolve" do koan "Things can evolve" do
assert [1, 2, 3] -- [3] == [1, 2] assert [1, 2, 3] -- [3] == :__
end end
koan "Evolution can have different forms" do koan "Evolution can have different forms" do
assert List.delete([1, 2, 2, 3], 2) == [1, 2, 3] assert List.delete([1, 2, 2, 3], 2) == :__
end end
koan "Precision is also valued" do koan "Precision is also valued" do
assert List.delete_at([1, 2, 3], 1) == [1, 3] assert List.delete_at([1, 2, 3], 1) == :__
end end
koan "Replication is also possible" do koan "Replication is also possible" do
assert List.duplicate("life", 3) == ["life", "life", "life"] assert List.duplicate("life", 3) == :__
end end
koan "Sometimes levelling the playing field is desired" do koan "Sometimes levelling the playing field is desired" do
assert List.flatten([1, [2, 3], 4, [5]]) == [1, 2, 3, 4, 5] assert List.flatten([1, [2, 3], 4, [5]]) == :__
end end
koan "Same rules apply to new members that arrive late" do koan "Same rules apply to new members that arrive late" do
assert List.flatten([1, [2, 3]], [4]) == [1, 2, 3, 4] assert List.flatten([1, [2, 3]], [4]) == :__
end end
koan "Order can also be specified for new members" do koan "Order can also be specified for new members" do
assert List.insert_at([1, 2, 3], 1, 4) == [1, 4, 2, 3] assert List.insert_at([1, 2, 3], 1, 4) == :__
end end
koan "We can replace things at specified positions" do koan "We can replace things at specified positions" do
assert List.replace_at([1, 2, 3], 0, 10) == [10, 2, 3] assert List.replace_at([1, 2, 3], 0, 10) == :__
end end
koan "Replacing something which is not" do koan "Replacing something which is not" do
assert List.replace_at([1, 2, 3], 10, 0) == [1, 2, 3] assert List.replace_at([1, 2, 3], 10, 0) == :__
end end
koan "Order is bound by nature's laws" do koan "Order is bound by nature's laws" do
assert List.insert_at([1, 2, 3], 10, 4) == [1, 2, 3, 4] assert List.insert_at([1, 2, 3], 10, 4) == :__
assert List.insert_at([1, 2, 3], -1, 4) == [1, 2, 3, 4] end
koan "Sometimes its faster to loop around back" do
assert List.insert_at([1, 2, 3], -1, 4) == :__
end end
koan "We can also transform ourselves completely" do koan "We can also transform ourselves completely" do
assert List.to_tuple([1, 2, 3]) == {1, 2, 3} assert List.to_tuple([1, 2, 3]) == :__
end end
koan "Wrapping other values is a handy option" do koan "Wrapping other values is a handy option" do
assert List.wrap("value") == ["value"] assert List.wrap("value") == :__
end end
koan "Zipping can be a useful operation" do koan "Zipping can be a useful operation" do
assert List.zip([[1, 2], [3, 4], [5, 6]]) == [{1, 3, 5}, {2, 4, 6}] assert List.zip([[1, 2], [3, 4], [5, 6]]) == :__
end end
end end

View File

@@ -30,7 +30,11 @@ defmodule Runner do
koans = module.all_koans koans = module.all_koans
passed = Enum.take_while(koans, fn(name) -> passed = Enum.take_while(koans, fn(name) ->
run_koan(module, name) == :passed case run_koan(module, name) do
:passed -> true
{:failed, error, module, name} -> Display.show_failure(error, module, name)
false
end
end) end)
if Enum.count(koans) == Enum.count(passed) do if Enum.count(koans) == Enum.count(passed) do
@@ -40,12 +44,10 @@ defmodule Runner do
end end
end end
def run_koan(module, name) do def run_koan(module, name, args \\ []) do
case apply(module, name, []) do case apply(module, name, args) do
:ok -> :passed :ok -> :passed
error -> error -> {:failed, error, module, name}
Display.show_failure(error, module, name)
:failed
end end
end end
end end

31
test/ast_mangler_test.exs Normal file
View File

@@ -0,0 +1,31 @@
defmodule ASTManglerTest do
use ExUnit.Case, async: true
test "simple replacement" do
ast = quote do: 1 + :__
mangled = ASTMangler.expand(ast, 37)
assert {:+, [context: ASTManglerTest, import: Kernel], [1, 37]} == mangled
end
def complex_example do
[head | tail] = [1,2,3,4]
assert head == 1
assert tail == [2,3,4]
end
def foo(answer) do
if answer == :yes do
:bar
else
:batz
end
end
test "complex example" do
ast = [do: {:assert, [line: 5], [{:==, [line: 5], [true, :__]}]}]
assert [do: {:assert, [line: 5], [{:==, [line: 5], [true, true]}]}] == ASTMangler.expand(ast, true)
end
end

View File

@@ -0,0 +1,46 @@
defmodule KoansHarnessTest do
use ExUnit.Case
test "Equalities" do
answers = [true,
1,
2,
1,
:something]
test_all(Equalities, answers)
end
test "Lists" do
answers = [1,
3,
[1,2,:a,"b"],
[1,2],
[1,2,3],
[1,3],
["life", "life", "life"],
[1, 2, 3, 4, 5],
[1, 2, 3, 4],
[1, 4, 2, 3],
[10, 2, 3],
[1, 2, 3],
[1, 2, 3, 4],
[1, 2, 3, 4],
{1, 2, 3},
["value"],
[{1, 3, 5}, {2, 4, 6}]
]
test_all(Lists, answers)
end
def test_all(module, answers) do
module.all_koans
|> Enum.zip(answers)
|> run_all(module)
end
def run_all(pairs, module) do
Enum.map(pairs, fn ({koan, answer}) -> Runner.run_koan(module, koan, [answer]) end)
end
end