Packages
espec
0.8.5
1.10.0
1.9.2
1.9.1
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.0
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.8.28
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.7
0.3.5
0.3.0
0.2.0
0.1.0
BDD testing framework for Elixir inspired by RSpec.
Current section
Files
Jump to
Current section
Files
lib/espec/example_runner.ex
defmodule ESpec.ExampleRunner do
@moduledoc """
Contains all the functions need to run a 'spec' example.
"""
@dict_keys [:ok, :shared]
@doc """
Runs one specific example and returns an `%ESpec.Example{}` struct.
The sequence in the following:
- evaluates 'befores' and 'lets'. 'befores' fill the map for `shared`, 'lets' can access `shared` ;
- runs 'example block';
- evaluate 'finally's'
The struct has fields `[status: :success, result: result]` or `[status: failed, error: error]`
The `result` is the value returned by example block.
`error` is a `%ESpec.AssertionError{}` struct.
"""
def run(example) do
contexts = ESpec.Example.extract_contexts(example)
cond do
example.opts[:skip] || Enum.any?(contexts, &(&1.opts[:skip])) ->
run_skipped(example)
example.opts[:pending] ->
run_pending(example)
true ->
run_example(example, :os.timestamp)
end
end
defp run_example(example, start_time) do
try do
assigns = before_example_actions(example)
result = case apply(example.module, example.function, [assigns]) do
{ESpec.ExpectTo, res} -> res
res -> res
end
duration = duration_in_ms(start_time, :os.timestamp)
example = %ESpec.Example{example | status: :success, result: result, duration: duration}
ESpec.Output.example_info(example)
after_example_actions(assigns, example)
example
rescue
error in [ESpec.AssertionError] ->
duration = duration_in_ms(start_time, :os.timestamp)
example = %ESpec.Example{example | status: :failure, error: error, duration: duration}
ESpec.Output.example_info(example)
example
other_error ->
error = %ESpec.AssertionError{message: format_other_error(other_error)}
duration = duration_in_ms(start_time, :os.timestamp)
example = %ESpec.Example{example | status: :failure, error: error, duration: duration}
ESpec.Output.example_info(example)
example
after
unload_mocks
end
end
defp before_example_actions(example) do
%{}
|> run_config_before(example)
|> run_befores_and_lets(example)
end
def after_example_actions(assigns, example) do
run_finallies(assigns, example)
|> run_config_finally(example)
end
defp format_other_error(error) do
error_message = Exception.format_banner(:error, error)
stacktrace = Exception.format_stacktrace(System.stacktrace)
error_message <> "\n" <> stacktrace
end
defp run_skipped(example) do
example = %ESpec.Example{example | status: :pending, result: ESpec.Example.skip_message(example)}
ESpec.Output.example_info(example)
example
end
defp run_pending(example) do
example = %ESpec.Example{example | status: :pending, result: ESpec.Example.pending_message(example)}
ESpec.Output.example_info(example)
example
end
defp run_config_before(assigns, _example) do
func = ESpec.Configuration.get(:before)
if func, do: fill_dict(assigns, func.()), else: assigns
end
defp run_befores_and_lets(assigns, example) do
ESpec.Example.extract_befores_and_lets(example)
|> Enum.reduce(assigns, fn(before_or_let, map) ->
case before_or_let.__struct__ do
ESpec.Before ->
before = before_or_let
returned = apply(before.module, before.function, [map])
fill_dict(map, returned)
ESpec.Let ->
let = before_or_let
ESpec.Let.agent_put({self, let.module, let.var}, apply(example.module, let.function, [map, let.keep_quoted]))
map
end
end)
end
defp run_finallies(assigns, example) do
ESpec.Example.extract_finallies(example)
|> Enum.reduce(assigns, fn(finally, map) ->
returned = apply(finally.module, finally.function, [map])
fill_dict(map, returned)
end)
end
defp run_config_finally(assigns, _example) do
func = ESpec.Configuration.get(:finally)
if func do
if is_function(func, 1), do: func.(assigns), else: func.()
end
end
defp fill_dict(map, res) do
case res do
{key, list} when key in @dict_keys and is_list(list) ->
if Keyword.keyword?(list) do
Enum.reduce(list, map, fn({k,v}, a) -> Dict.put(a, k, v) end)
else
map
end
_ -> map
end
end
defp unload_mocks, do: ESpec.Mock.unload
defp duration_in_ms(start_time, end_time) do
div(:timer.now_diff(end_time, start_time), 1000)
end
end