Skip to content

Commit 47a0449

Browse files
committed
Add more tests for pp
1 parent b4a5ccc commit 47a0449

File tree

3 files changed

+100
-41
lines changed

3 files changed

+100
-41
lines changed

lib/gradient/elixir_type.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ defmodule Gradient.ElixirType do
2828
end
2929

3030
def pretty_print({:ann_type, _, [var_name, var_type]}) do
31-
pretty_print(var_name) <> pretty_print(var_type)
31+
pretty_print(var_name) <> " :: " <> pretty_print(var_type)
3232
end
3333

3434
def pretty_print({:type, _, :map, :any}) do

test/gradient/elixir_type_test.exs

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,14 @@ defmodule Gradient.ElixirTypeTest do
33
doctest Gradient.ElixirType
44

55
alias Gradient.ElixirType
6+
alias Gradient.TypeData
67

7-
test "pp integer()" do
8-
type = {:integer, 0, 12}
9-
expected = "12"
10-
actual = ElixirType.pretty_print(type)
11-
assert expected == actual
12-
end
13-
14-
test "pp atom()" do
15-
type = {:atom, 0, :ok}
16-
expected = ":ok"
17-
actual = ElixirType.pretty_print(type)
18-
assert expected == actual
19-
end
20-
21-
test "pp nil()" do
22-
type = {:atom, 0, nil}
23-
expected = "nil"
24-
actual = ElixirType.pretty_print(type)
25-
assert expected == actual
26-
end
27-
28-
test "pp false boolean()" do
29-
type = {:atom, 0, false}
30-
expected = "false"
31-
actual = ElixirType.pretty_print(type)
32-
assert expected == actual
33-
end
34-
35-
test "pp true boolean()" do
36-
type = {:atom, 0, true}
37-
expected = "true"
38-
actual = ElixirType.pretty_print(type)
39-
assert expected == actual
40-
end
41-
42-
test "pp binary()" do
43-
type = {:type, 0, :binary, []}
44-
expected = "binary()"
45-
actual = ElixirType.pretty_print(type)
46-
assert expected == actual
8+
describe "pretty print" do
9+
for {name, type, expected} <- TypeData.all_pp_test_data() do
10+
test "#{name}" do
11+
type = unquote(Macro.escape(type))
12+
assert unquote(expected) == ElixirType.pretty_print(type)
13+
end
14+
end
4715
end
4816
end

test/support/type_data.ex

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
defmodule Gradient.TypeData do
2+
@spec all_pp_test_data() :: [{name :: String.t(), type :: tuple(), expected :: String.t()}]
3+
def all_pp_test_data() do
4+
[
5+
value_test_data(),
6+
buildin_types_test_data(),
7+
op_types_test_data(),
8+
fun_types_test_data(),
9+
map_types_test_data(),
10+
tuple_types_test_data(),
11+
other_types_test_data()
12+
]
13+
|> List.flatten()
14+
end
15+
16+
def value_test_data() do
17+
[
18+
{"integer value", {:integer, 0, 12}, "12"},
19+
{"atom value", {:atom, 0, :ok}, ":ok"},
20+
{"boolean false", {:atom, 0, false}, "false"},
21+
{"boolean true", {:atom, 0, true}, "true"},
22+
{"nil", {:atom, 0, nil}, "nil"}
23+
]
24+
end
25+
26+
def buildin_types_test_data() do
27+
[
28+
{"integer type", {:type, 0, :integer, []}, "integer()"},
29+
{"float type", {:type, 0, :float, []}, "float()"},
30+
{"atom type", {:type, 0, :atom, []}, "atom()"},
31+
{"boolean type", {:type, 0, :boolean, []}, "boolean()"},
32+
{"binary type", {:type, 0, :binary, []}, "binary()"},
33+
{"range type", {:type, 0, :range, [{:integer, 0, 1}, {:integer, 0, 10}]}, "1..10"},
34+
{"list type", {:type, 0, :list, []}, "list()"},
35+
{"nonempty_list type", {:type, 0, :nonempty_list, []}, "nonempty_list()"},
36+
{"nil() or []", {:type, 0, nil, []}, "[]"},
37+
{"type with args", {:type, 0, :list, [{:type, 0, :integer, []}]}, "list(integer())"}
38+
]
39+
end
40+
41+
def op_types_test_data() do
42+
[
43+
{"binary operator", {:op, 0, :+, {:integer, 0, 1}, {:integer, 0, 2}}, "1 + 2"},
44+
{"unary operator", {:op, 0, :not, {:var, 0, :status}}, "not status"}
45+
]
46+
end
47+
48+
def fun_types_test_data() do
49+
[
50+
{"any fun type", {:type, 0, :fun, []}, "fun()"},
51+
{"fun accepts any args that returns specified type",
52+
{:type, 0, :fun, [{:type, 0, :any}, {:atom, 0, :ok}]}, "(... -> :ok)"},
53+
{"fun accepts specified args and return specified type",
54+
{:type, 0, :fun, [{:type, 0, :product, [{:type, 0, :atom, []}]}, {:type, 0, :atom, []}]},
55+
"(atom() -> atom())"}
56+
]
57+
end
58+
59+
def map_types_test_data() do
60+
[
61+
{"any map type", {:type, 0, :map, :any}, "map()"},
62+
{"complex map type",
63+
{:type, 0, :map,
64+
[
65+
{:type, 0, :map_field_assoc, [{:atom, 0, :value_a}, {:integer, 0, 5}]},
66+
{:type, 0, :map_field_exact, [{:atom, 0, :value_b}, {:atom, 0, :neo}]}
67+
]}, "%{optional(:value_a) => 5, required(:value_b) => :neo}"}
68+
]
69+
end
70+
71+
def tuple_types_test_data() do
72+
[
73+
{"any tuple type", {:type, 0, :tuple, :any}, "tuple()"},
74+
{"tuple {:ok, 8}", {:type, 0, :tuple, [{:atom, 0, :ok}, {:integer, 0, 8}]}, "{:ok, 8}"}
75+
]
76+
end
77+
78+
def other_types_test_data() do
79+
[
80+
{"var type", {:var, 0, :a}, "a"},
81+
{"anotated type", {:ann_type, 0, [{:var, 0, :name}, {:type, 0, :integer, []}]},
82+
"name :: integer()"},
83+
{"remote type without args",
84+
{:remote_type, 0, [{:atom, 0, MyModule}, {:atom, 0, :my_fun}, []]}, "MyModule.my_fun()"},
85+
{"remote type with args",
86+
{:remote_type, 0, [{:atom, 0, MyModule}, {:atom, 0, :my_fun}, [{:type, 0, :integer, []}]]},
87+
"MyModule.my_fun(integer())"},
88+
{"user type", {:user_type, 0, :my_type, [{:type, 0, :atom, []}]}, "my_type(atom())"}
89+
]
90+
end
91+
end

0 commit comments

Comments
 (0)