379 lines
9.0 KiB
Elixir
379 lines
9.0 KiB
Elixir
Code.require_file "test_helper.exs", __DIR__
|
|
|
|
defmodule ExUnitTest do
|
|
use ExUnit.Case
|
|
|
|
import ExUnit.CaptureIO
|
|
|
|
test "it supports many runs" do
|
|
defmodule SampleTest do
|
|
use ExUnit.Case
|
|
|
|
test "true" do
|
|
assert false
|
|
end
|
|
|
|
test "false" do
|
|
assert false
|
|
end
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
assert capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 2, skipped: 0, total: 2}
|
|
end) =~ "2 tests, 2 failures"
|
|
end
|
|
|
|
test "it doesn't hang on exits" do
|
|
defmodule EventServerTest do
|
|
use ExUnit.Case
|
|
|
|
test "spawn and crash" do
|
|
spawn_link(fn ->
|
|
exit :foo
|
|
end)
|
|
receive after: (1000 -> :ok)
|
|
end
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
assert capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 1, skipped: 0, total: 1}
|
|
end) =~ "1 test, 1 failure"
|
|
end
|
|
|
|
test "it supports timeouts" do
|
|
defmodule TimeoutTest do
|
|
use ExUnit.Case
|
|
|
|
@tag timeout: 10
|
|
test "ok" do
|
|
:timer.sleep(:infinity)
|
|
end
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
output = capture_io(fn -> ExUnit.run end)
|
|
assert output =~ "** (ExUnit.TimeoutError) test timed out after 10ms"
|
|
assert output =~ ~r"\(stdlib\) timer\.erl:\d+: :timer\.sleep/1"
|
|
end
|
|
|
|
test "it supports configured timeout" do
|
|
defmodule ConfiguredTimeoutTest do
|
|
use ExUnit.Case
|
|
|
|
test "ok" do
|
|
:timer.sleep(:infinity)
|
|
end
|
|
end
|
|
|
|
ExUnit.configure(timeout: 5)
|
|
ExUnit.Server.cases_loaded()
|
|
output = capture_io(fn -> ExUnit.run end)
|
|
assert output =~ "** (ExUnit.TimeoutError) test timed out after 5ms"
|
|
after
|
|
ExUnit.configure(timeout: 60_000)
|
|
end
|
|
|
|
test "filtering cases with tags" do
|
|
defmodule ParityTest do
|
|
use ExUnit.Case
|
|
|
|
test "zero", do: :ok
|
|
|
|
@tag even: false
|
|
test "one", do: :ok
|
|
|
|
@tag even: true
|
|
test "two", do: assert 1 == 2
|
|
|
|
@tag even: false
|
|
test "three", do: :ok
|
|
end
|
|
|
|
{result, output} = run_with_filter([], []) # Empty because it is already loaded
|
|
assert result == %{failures: 1, skipped: 0, total: 4}
|
|
assert output =~ "4 tests, 1 failure"
|
|
|
|
{result, output} = run_with_filter([exclude: [even: true]], [ParityTest])
|
|
assert result == %{failures: 0, skipped: 1, total: 4}
|
|
assert output =~ "4 tests, 0 failures, 1 skipped"
|
|
|
|
{result, output} = run_with_filter([exclude: :even], [ParityTest])
|
|
assert result == %{failures: 0, skipped: 3, total: 4}
|
|
assert output =~ "4 tests, 0 failures, 3 skipped"
|
|
|
|
{result, output} = run_with_filter([exclude: :even, include: [even: true]], [ParityTest])
|
|
assert result == %{failures: 1, skipped: 2, total: 4}
|
|
assert output =~ "4 tests, 1 failure, 2 skipped"
|
|
|
|
{result, output} = run_with_filter([exclude: :test, include: [even: true]], [ParityTest])
|
|
assert result == %{failures: 1, skipped: 3, total: 4}
|
|
assert output =~ "4 tests, 1 failure, 3 skipped"
|
|
end
|
|
|
|
test "log capturing" do
|
|
defmodule LogCapturingTest do
|
|
use ExUnit.Case
|
|
|
|
require Logger
|
|
|
|
setup_all do
|
|
:ok = Logger.remove_backend(:console)
|
|
on_exit(fn -> Logger.add_backend(:console, flush: true) end)
|
|
end
|
|
|
|
@tag :capture_log
|
|
test "one" do
|
|
Logger.debug("one")
|
|
assert 1 == 1
|
|
end
|
|
|
|
@tag :capture_log
|
|
test "two" do
|
|
Logger.debug("two")
|
|
assert 1 == 2
|
|
end
|
|
|
|
@tag capture_log: []
|
|
test "three" do
|
|
Logger.debug("three")
|
|
assert 1 == 2
|
|
end
|
|
|
|
test "four" do
|
|
Logger.debug("four")
|
|
assert 1 == 2
|
|
end
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
output = capture_io(&ExUnit.run/0)
|
|
assert output =~ "[debug] two"
|
|
refute output =~ "[debug] one"
|
|
assert output =~ "[debug] three"
|
|
refute output =~ "[debug] four"
|
|
end
|
|
|
|
test "supports multi errors" do
|
|
capture_io :stderr, fn ->
|
|
defmodule MultiTest do
|
|
use ExUnit.Case
|
|
|
|
test "multi" do
|
|
error1 =
|
|
try do
|
|
assert 1 = 2
|
|
rescue e in ExUnit.AssertionError ->
|
|
{:error, e, System.stacktrace}
|
|
end
|
|
|
|
error2 =
|
|
try do
|
|
assert 3 > 4
|
|
rescue e in ExUnit.AssertionError ->
|
|
{:error, e, System.stacktrace}
|
|
end
|
|
|
|
raise ExUnit.MultiError, errors: [error1, error2]
|
|
end
|
|
end
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
output = capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 1, skipped: 0, total: 1}
|
|
end)
|
|
|
|
assert output =~ "1 test, 1 failure"
|
|
assert output =~ "1) test multi (ExUnitTest.MultiTest)"
|
|
assert output =~ "Failure #1"
|
|
assert output =~ "Failure #2"
|
|
|
|
assert_raise ExUnit.MultiError, ~r/oops/, fn ->
|
|
error = {:error, RuntimeError.exception("oops"), System.stacktrace}
|
|
raise ExUnit.MultiError, errors: [error]
|
|
end
|
|
end
|
|
|
|
test "raises friendly error for duplicate test names" do
|
|
message = ~S("test duplicate" is already defined in ExUnitTest.TestWithSameNames)
|
|
|
|
assert_raise ExUnit.DuplicateTestError, message, fn ->
|
|
defmodule TestWithSameNames do
|
|
use ExUnit.Case
|
|
|
|
test "duplicate" do
|
|
assert true
|
|
end
|
|
|
|
test "duplicate" do
|
|
assert true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
test "produces error on not implemented tests" do
|
|
defmodule TestNotImplemented do
|
|
use ExUnit.Case
|
|
|
|
setup context do
|
|
assert context[:not_implemented]
|
|
:ok
|
|
end
|
|
|
|
test "this is not implemented yet"
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
output = capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 1, skipped: 0, total: 1}
|
|
end)
|
|
|
|
assert output =~ "Not yet implemented"
|
|
assert output =~ "1 test, 1 failure"
|
|
end
|
|
|
|
test "skips tagged test with skip" do
|
|
defmodule TestSkipped do
|
|
use ExUnit.Case
|
|
|
|
setup context do
|
|
assert context[:not_implemented]
|
|
:ok
|
|
end
|
|
|
|
@tag :skip
|
|
test "this will raise", do: raise "oops"
|
|
|
|
@tag skip: "won't work"
|
|
test "this will also raise", do: raise "oops"
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
output = capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 0, skipped: 2, total: 2}
|
|
end)
|
|
|
|
assert output =~ "2 tests, 0 failures, 2 skipped"
|
|
end
|
|
|
|
test "filtering cases with :case tag" do
|
|
defmodule FirstTestCase do
|
|
use ExUnit.Case
|
|
test "ok", do: :ok
|
|
end
|
|
|
|
defmodule SecondTestCase do
|
|
use ExUnit.Case
|
|
test "false", do: assert false
|
|
end
|
|
|
|
{result, output} = run_with_filter([exclude: :case], []) # Empty because it is already loaded
|
|
assert result == %{failures: 0, skipped: 2, total: 2}
|
|
assert output =~ "2 tests, 0 failures, 2 skipped"
|
|
|
|
{result, output} =
|
|
[exclude: :test, include: [case: "ExUnitTest.SecondTestCase"]]
|
|
|> run_with_filter([FirstTestCase, SecondTestCase])
|
|
assert result == %{failures: 1, skipped: 1, total: 2}
|
|
assert output =~ "1) test false (ExUnitTest.SecondTestCase)"
|
|
assert output =~ "2 tests, 1 failure, 1 skipped"
|
|
end
|
|
|
|
test "raises on reserved tag :file in module" do
|
|
assert_raise RuntimeError, "cannot set tag :file because it is reserved by ExUnit", fn ->
|
|
defmodule ReservedTagFile do
|
|
use ExUnit.Case
|
|
|
|
@tag file: "oops"
|
|
test "sample", do: :ok
|
|
end
|
|
end
|
|
end
|
|
|
|
test "raises on reserved tag :async in module" do
|
|
assert_raise RuntimeError, "cannot set tag :async because it is reserved by ExUnit", fn ->
|
|
defmodule ReservedTagAsync do
|
|
use ExUnit.Case
|
|
|
|
@tag async: true
|
|
test "sample", do: :ok
|
|
end
|
|
end
|
|
end
|
|
|
|
test "raises on reserved tag :file in setup" do
|
|
defmodule ReservedSetupTagFile do
|
|
use ExUnit.Case
|
|
|
|
setup do
|
|
{:ok, file: :foo}
|
|
end
|
|
|
|
test "sample", do: :ok
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
output = capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 1, skipped: 0, total: 1}
|
|
end)
|
|
|
|
assert output =~ "trying to set reserved field :file"
|
|
end
|
|
|
|
test "raises on reserved tag :async in setup" do
|
|
defmodule ReservedSetupTagAsync do
|
|
use ExUnit.Case
|
|
|
|
setup do
|
|
{:ok, async: true}
|
|
end
|
|
|
|
test "sample", do: :ok
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
output = capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 1, skipped: 0, total: 1}
|
|
end)
|
|
|
|
assert output =~ "trying to set reserved field :async"
|
|
end
|
|
|
|
test "does not raise on reserved tag in setup_all (lower priority)" do
|
|
defmodule ReservedSetupAllTag do
|
|
use ExUnit.Case
|
|
|
|
setup_all do
|
|
{:ok, file: :foo}
|
|
end
|
|
|
|
test "sample", do: :ok
|
|
end
|
|
|
|
ExUnit.Server.cases_loaded()
|
|
|
|
capture_io(fn ->
|
|
assert ExUnit.run == %{failures: 0, skipped: 0, total: 1}
|
|
end)
|
|
end
|
|
|
|
defp run_with_filter(filters, cases) do
|
|
Enum.each(cases, &ExUnit.Server.add_sync_case/1)
|
|
ExUnit.Server.cases_loaded()
|
|
opts = Keyword.merge(ExUnit.configuration, filters)
|
|
output = capture_io fn -> Process.put(:capture_result, ExUnit.Runner.run(opts, nil)) end
|
|
{Process.get(:capture_result), output}
|
|
end
|
|
end
|