Skip to content

Commit 6512fcb

Browse files
committed
Add import: option to doctests. It is false by default.
1 parent c2d1699 commit 6512fcb

File tree

2 files changed

+42
-11
lines changed

2 files changed

+42
-11
lines changed

lib/ex_unit/lib/ex_unit/doc_test.ex

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ defmodule ExUnit.DocTest do
107107
* `:only` — generate tests only forfunctions listed
108108
(list of `{function, arity}` tuples)
109109
110+
* `:import` — if false, do not auto-import the current module into the
111+
evaluted example. If true, one can test a function
112+
defined in the module without referring to the module
113+
name. However, this is not feasible when there is a clash
114+
with a number module like Kernel. In these cases, `import`
115+
should be set to `false` and a full `M.f` construct should
116+
be used. False by default.
117+
118+
110119
## Examples
111120
112121
doctest MyModule, except: [trick_fun: 1]
@@ -125,21 +134,22 @@ defmodule ExUnit.DocTest do
125134
def __doctests__(module, opts) do
126135
only = opts[:only] || []
127136
except = opts[:except] || []
137+
do_import = Keyword.get(opts, :import, false)
128138

129139
tests = Enum.filter(extract(module), fn(test) ->
130140
fa = test.fun_arity
131141
Enum.all?(except, &1 != fa) and Enum.all?(only, &1 == fa)
132142
end)
133143

134144
Enum.map_reduce(tests, 1, fn(test, acc) ->
135-
{ compile_test(test, module, acc), acc + 1 }
145+
{ compile_test(test, module, do_import, acc), acc + 1 }
136146
end) |> elem(0)
137147
end
138148

139149
## Compilation of extracted tests
140150

141-
defp compile_test(test, module, n) do
142-
{ test_name(test, module, n), test_content(test, module) }
151+
defp compile_test(test, module, do_import, n) do
152+
{ test_name(test, module, n), test_content(test, module, do_import) }
143153
end
144154

145155
defp test_name(Test[fun_arity: nil], m, n) do
@@ -150,16 +160,16 @@ defmodule ExUnit.DocTest do
150160
:"test doc at #{inspect m}.#{f}/#{a} (#{n})"
151161
end
152162

153-
defp test_content(Test[expected: { :ok, expected }] = test, module) do
163+
defp test_content(Test[expected: { :ok, expected }] = test, module, do_import) do
154164
line = test.line
155165
file = module.__info__(:compile)[:source]
156166

157167
expr_ast = string_to_ast(line, file, test.expr)
158168
expected_ast = string_to_ast(line, file, expected)
159169

170+
quoted =
160171
quote do
161172
try do
162-
import unquote(module)
163173
v = unquote(expected_ast)
164174
case unquote(expr_ast) do
165175
^v -> :ok
@@ -186,21 +196,34 @@ defmodule ExUnit.DocTest do
186196
stack
187197
end
188198
end
199+
if do_import do
200+
quoted = quote do
201+
import unquote(module)
202+
unquote(quoted)
203+
end
204+
end
205+
quoted
189206
end
190207

191-
defp test_content(Test[expected: { :error, exception, message }] = test, module) do
208+
defp test_content(Test[expected: { :error, exception, message }] = test, module, do_import) do
192209
line = test.line
193210
file = module.__info__(:compile)[:source]
194211

195212
expr_ast = string_to_ast(line, file, test.expr)
196213

214+
quoted =
197215
quote do
198-
import unquote(module)
199-
200216
assert_raise unquote(exception), unquote(message), fn ->
201217
unquote(expr_ast)
202218
end
203219
end
220+
if do_import do
221+
quoted = quote do
222+
import unquote(module)
223+
unquote(quoted)
224+
end
225+
end
226+
quoted
204227
end
205228

206229
defp string_to_ast(line, file, expr) do

lib/ex_unit/test/ex_unit/doc_test_test.exs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,19 @@ defmodule ExUnit.DocTestTest.SomewhatGoodModule1 do
5252
def test_fun1, do: 1
5353
end
5454

55+
defmodule ExUnit.DocTestTest.NoImport do
56+
@doc """
57+
iex> ExUnit.DocTestTest.NoImport.min(1,2)
58+
2
59+
"""
60+
def min(a,b), do: max(a,b)
61+
end
5562
defmodule ExUnit.DocTestTest do
5663
use ExUnit.Case
5764

5865
doctest ExUnit.DocTest
59-
doctest ExUnit.DocTestTest.GoodModule
60-
doctest ExUnit.DocTestTest.SomewhatGoodModule, only: [test_fun: 0]
61-
doctest ExUnit.DocTestTest.SomewhatGoodModule1, except: [test_fun1: 0]
66+
doctest ExUnit.DocTestTest.GoodModule, import: true
67+
doctest ExUnit.DocTestTest.SomewhatGoodModule, only: [test_fun: 0], import: true
68+
doctest ExUnit.DocTestTest.SomewhatGoodModule1, except: [test_fun1: 0], import: true
69+
doctest ExUnit.DocTestTest.NoImport
6270
end

0 commit comments

Comments
 (0)