Current section

Files

Jump to
espec lib espec runner.ex
Raw

lib/espec/runner.ex

defmodule ESpec.Runner do
@moduledoc """
Defines functions which runs the examples.
Uses GenServer behavior.
"""
alias __MODULE__.Queue
alias ESpec.Configuration
alias ESpec.Example
alias ESpec.Output
alias ESpec.SuiteRunner
alias Mix.Utils.Stale
@doc "Starts the `ESpec.Runner` server"
def start do
Queue.start(:input)
Queue.start(:output)
Task.Supervisor.start_link(name: ESpec.TaskSupervisor)
end
@doc "Runs all examples."
def run do
do_run(ESpec.specs(), Configuration.all())
end
@doc false
def stop do
Queue.stop(:input)
Queue.stop(:output)
Supervisor.stop(ESpec.TaskSupervisor)
end
defp do_run(specs, opts) do
examples =
if Configuration.get(:order) do
run_suites(specs, opts, false)
else
seed_random!()
run_suites(specs, opts)
end
success = !Enum.any?(Example.failure(examples))
Configuration.add(finish_specs_time: :os.timestamp())
stale_manifest_and_output(examples, stale: opts[:stale], success: success)
success
end
defp stale_manifest_and_output(examples, stale: true, success: success) do
if success, do: Stale.agent_write_manifest()
case examples do
[] -> Mix.shell().info("No stale tests to run...")
examples -> Output.final_result(examples)
end
end
defp stale_manifest_and_output(examples, _opts) do
Output.final_result(examples)
end
defp run_suites(specs, opts, shuffle \\ true) do
specs
|> Enum.reverse()
|> Enum.map(fn module ->
SuiteRunner.run(module, opts, shuffle)
end)
|> List.flatten()
end
defp seed_random! do
conf_seed =
if seed = Configuration.get(:seed) do
seed
else
seed = :os.timestamp() |> elem(2)
Configuration.add(seed: seed)
seed
end
seed =
cond do
is_number(conf_seed) -> conf_seed
is_binary(conf_seed) -> String.to_integer(conf_seed)
true -> :no_way
end
:rand.seed(:exs64, {3172, 9814, seed})
end
defmodule Queue do
@moduledoc """
Implements queue.
"""
def push(name, el), do: Agent.update(name, &[el | &1])
def pop(name) do
Agent.get_and_update(name, fn state ->
case state do
[el | tail] -> {el, tail}
[] -> {nil, []}
end
end)
end
def all(name), do: Agent.get(name, & &1)
def start(name), do: Agent.start_link(fn -> [] end, name: name)
def clear(name), do: Agent.update(name, fn _ -> [] end)
def stop(name), do: Agent.stop(name)
end
end