@@ -10,13 +10,13 @@ defmodule ExUnit.ManifestTest do
test "ignores skipped tests since we know nothing about their pass/fail status" do
test = %ExUnit.Test{state: {:skipped, "reason"}}

assert add_test(%{}, test) == %{}
assert add_test(new(), test) == new()
end

test "ignores excluded tests since we know nothing about their pass/fail status" do
test = %ExUnit.Test{state: {:excluded, "reason"}}

assert add_test(%{}, test) == %{}
assert add_test(new(), test) == new()
end

test "stores passed tests, keyed by module and name" do
@@ -27,13 +27,9 @@ defmodule ExUnit.ManifestTest do
tags: %{file: "file"}
}

assert add_test(%{}, test) == %{
{SomeMod, :t1} =>
entry(
last_run_status: :passed,
file: "file"
)
}
assert add_test(new(), test) == [
{{SomeMod, :t1}, entry(last_run_status: :passed, file: "file")}
]
end

test "stores failed tests, keyed by module and name" do
@@ -44,13 +40,9 @@ defmodule ExUnit.ManifestTest do
tags: %{file: "file"}
}

assert add_test(%{}, test) == %{
{SomeMod, :t1} =>
entry(
last_run_status: :failed,
file: "file"
)
}
assert add_test(new(), test) == [
{{SomeMod, :t1}, entry(last_run_status: :failed, file: "file")}
]
end

test "stores invalid tests as failed, keyed by module and name" do
@@ -61,13 +53,9 @@ defmodule ExUnit.ManifestTest do
tags: %{file: "file"}
}

assert add_test(%{}, test) == %{
{SomeMod, :t1} =>
entry(
last_run_status: :failed,
file: "file"
)
}
assert add_test(new(), test) == [
{{SomeMod, :t1}, entry(last_run_status: :failed, file: "file")}
]
end
end

@@ -77,39 +65,39 @@ defmodule ExUnit.ManifestTest do
test "can roundtrip a manifest", context do
manifest = non_blank_manifest()

in_tmp context.test, fn ->
in_tmp(context.test, fn ->
assert write!(manifest, @manifest_path) == :ok
assert read(@manifest_path) == manifest
end
end)
end

test "returns a blank manifest when loading a file that does not exit" do
path = tmp_path() <> "missing.manifest"
refute File.exists?(path)
assert read(path) == %{}
assert read(path) == new()
end

test "returns a blank manifest when the file is corrupted", context do
manifest = non_blank_manifest()

in_tmp context.test, fn ->
in_tmp(context.test, fn ->
assert write!(manifest, @manifest_path) == :ok
corrupted = "corrupted" <> File.read!(@manifest_path)
File.write!(@manifest_path, corrupted)
assert read(@manifest_path) == %{}
end
assert read(@manifest_path) == new()
end)
end

test "returns a blank manifest when the file was saved at a prior version", context do
manifest = non_blank_manifest()

in_tmp context.test, fn ->
in_tmp(context.test, fn ->
assert write!(manifest, @manifest_path) == :ok
assert {vsn, ^manifest} = @manifest_path |> File.read!() |> :erlang.binary_to_term()
File.write!(@manifest_path, :erlang.term_to_binary({vsn + 1, manifest}))

assert read(@manifest_path) == %{}
end
assert read(@manifest_path) == new()
end)
end
end

@@ -121,7 +109,7 @@ defmodule ExUnit.ManifestTest do
tags: %{file: "file"}
}

add_test(%{}, test)
add_test(new(), test)
end

describe "merge/2" do
@@ -139,93 +127,97 @@ defmodule ExUnit.ManifestTest do
def test_2(_), do: :ok
end

defp merge_and_sort(old, new) do
old |> ExUnit.Manifest.merge(new) |> Enum.sort()
end

test "returns the new manifest when the old manifest is blank" do
new_manifest = %{{TestMod1, :test_1} => entry()}
new_manifest = [{{TestMod1, :test_1}, entry()}]

assert ExUnit.Manifest.merge(%{}, new_manifest) == new_manifest
assert merge_and_sort(new(), new_manifest) == new_manifest
end

test "replaces old entries with their updated status" do
old_manifest = %{
{TestMod1, :test_1} => entry(last_run_status: :failed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :passed, file: @existing_file_1)
}
old_manifest = [
{{TestMod1, :test_1}, entry(last_run_status: :failed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :passed, file: @existing_file_1)}
]

new_manifest = %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :failed, file: @existing_file_1)
}
new_manifest = [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :failed, file: @existing_file_1)}
]

assert ExUnit.Manifest.merge(old_manifest, new_manifest) == new_manifest
assert merge_and_sort(old_manifest, new_manifest) == new_manifest
end

test "keeps old entries for test modules in existing files that were not part of this run" do
old_manifest = %{
{UnknownMod1, :test_1} => entry(last_run_status: :failed, file: @existing_file_1),
{UnknownMod1, :test_2} => entry(last_run_status: :passed, file: @existing_file_1)
}
old_manifest = [
{{UnknownMod1, :test_1}, entry(last_run_status: :failed, file: @existing_file_1)},
{{UnknownMod1, :test_2}, entry(last_run_status: :passed, file: @existing_file_1)}
]

new_manifest = %{
{TestMod2, :test_1} => entry(last_run_status: :passed, file: @existing_file_2),
{TestMod2, :test_2} => entry(last_run_status: :failed, file: @existing_file_2)
}
new_manifest = [
{{TestMod2, :test_1}, entry(last_run_status: :passed, file: @existing_file_2)},
{{TestMod2, :test_2}, entry(last_run_status: :failed, file: @existing_file_2)}
]

assert ExUnit.Manifest.merge(old_manifest, new_manifest) == %{
{UnknownMod1, :test_1} => entry(last_run_status: :failed, file: @existing_file_1),
{UnknownMod1, :test_2} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod2, :test_1} => entry(last_run_status: :passed, file: @existing_file_2),
{TestMod2, :test_2} => entry(last_run_status: :failed, file: @existing_file_2)
}
assert merge_and_sort(old_manifest, new_manifest) == [
{{TestMod2, :test_1}, entry(last_run_status: :passed, file: @existing_file_2)},
{{TestMod2, :test_2}, entry(last_run_status: :failed, file: @existing_file_2)},
{{UnknownMod1, :test_1}, entry(last_run_status: :failed, file: @existing_file_1)},
{{UnknownMod1, :test_2}, entry(last_run_status: :passed, file: @existing_file_1)}
]
end

test "keeps old entries for tests that were loaded but skipped as part of this run" do
old_manifest = %{
{TestMod1, :test_1} => entry(last_run_status: :failed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :passed, file: @existing_file_1)
}
old_manifest = [
{{TestMod1, :test_1}, entry(last_run_status: :failed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :passed, file: @existing_file_1)}
]

new_manifest = %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1)
}
new_manifest = [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)}
]

assert ExUnit.Manifest.merge(old_manifest, new_manifest) == %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :passed, file: @existing_file_1)
}
assert merge_and_sort(old_manifest, new_manifest) == [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :passed, file: @existing_file_1)}
]
end

test "drops old entries from test files that no longer exist" do
old_manifest = %{
{TestMod2, :test_1} => entry(last_run_status: :failed, file: @missing_file),
{TestMod2, :test_2} => entry(last_run_status: :passed, file: @missing_file)
}
old_manifest = [
{{TestMod2, :test_1}, entry(last_run_status: :failed, file: @missing_file)},
{{TestMod2, :test_2}, entry(last_run_status: :passed, file: @missing_file)}
]

new_manifest = %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :failed, file: @existing_file_1)
}
new_manifest = [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :failed, file: @existing_file_1)}
]

assert ExUnit.Manifest.merge(old_manifest, new_manifest) == %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :failed, file: @existing_file_1)
}
assert merge_and_sort(old_manifest, new_manifest) == [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :failed, file: @existing_file_1)}
]
end

test "drops old entries for deleted tests from loaded modules" do
old_manifest = %{
{TestMod2, :missing_1} => entry(last_run_status: :failed, file: @existing_file_1),
{TestMod2, :missing_2} => entry(last_run_status: :passed, file: @existing_file_2)
}

new_manifest = %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :failed, file: @existing_file_1)
}

assert ExUnit.Manifest.merge(old_manifest, new_manifest) == %{
{TestMod1, :test_1} => entry(last_run_status: :passed, file: @existing_file_1),
{TestMod1, :test_2} => entry(last_run_status: :failed, file: @existing_file_1)
}
old_manifest = [
{{TestMod2, :missing_1}, entry(last_run_status: :failed, file: @existing_file_1)},
{{TestMod2, :missing_2}, entry(last_run_status: :passed, file: @existing_file_2)}
]

new_manifest = [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :failed, file: @existing_file_1)}
]

assert merge_and_sort(old_manifest, new_manifest) == [
{{TestMod1, :test_1}, entry(last_run_status: :passed, file: @existing_file_1)},
{{TestMod1, :test_2}, entry(last_run_status: :failed, file: @existing_file_1)}
]
end
end
end
@@ -51,10 +51,10 @@ defmodule ExUnit.RunnerStatsTest do
simulate_test(formatter, :test_2, :failed)
end)

assert read_manifest() == %{
{TestModule, :test_1} => entry(file: __ENV__.file, last_run_status: :passed),
{TestModule, :test_2} => entry(file: __ENV__.file, last_run_status: :failed)
}
assert read_and_sort_manifest() == [
{{TestModule, :test_1}, entry(file: __ENV__.file, last_run_status: :passed)},
{{TestModule, :test_2}, entry(file: __ENV__.file, last_run_status: :failed)}
]
end)
end

@@ -63,10 +63,10 @@ defmodule ExUnit.RunnerStatsTest do
simulate_suite(&simulate_test(&1, :test_1, :passed))
simulate_suite(&simulate_test(&1, :test_2, :failed))

assert read_manifest() == %{
{TestModule, :test_1} => entry(file: __ENV__.file, last_run_status: :passed),
{TestModule, :test_2} => entry(file: __ENV__.file, last_run_status: :failed)
}
assert read_and_sort_manifest() == [
{{TestModule, :test_1}, entry(file: __ENV__.file, last_run_status: :passed)},
{{TestModule, :test_2}, entry(file: __ENV__.file, last_run_status: :failed)}
]
end)
end
end
@@ -100,7 +100,7 @@ defmodule ExUnit.RunnerStatsTest do
defp state_for(:skipped), do: {:skipped, "reason"}
defp state_for(:excluded), do: {:excluded, "reason"}

defp read_manifest do
Manifest.read(@manifest_file)
defp read_and_sort_manifest do
@manifest_file |> Manifest.read() |> Enum.sort()
end
end