diff --git a/lib/mix_test_interactive/interactive_mode.ex b/lib/mix_test_interactive/interactive_mode.ex index cede069..08ebf0a 100644 --- a/lib/mix_test_interactive/interactive_mode.ex +++ b/lib/mix_test_interactive/interactive_mode.ex @@ -14,6 +14,7 @@ defmodule MixTestInteractive.InteractiveMode do alias MixTestInteractive.CommandProcessor alias MixTestInteractive.Config alias MixTestInteractive.Runner + alias MixTestInteractive.RunSummary alias MixTestInteractive.Settings @type option :: {:config, Config.t()} | {:name | String.t()} @@ -116,7 +117,7 @@ defmodule MixTestInteractive.InteractiveMode do IO.puts("") settings - |> Settings.summary() + |> RunSummary.from_settings() |> IO.puts() end diff --git a/lib/mix_test_interactive/run_summary.ex b/lib/mix_test_interactive/run_summary.ex new file mode 100644 index 0000000..7714334 --- /dev/null +++ b/lib/mix_test_interactive/run_summary.ex @@ -0,0 +1,71 @@ +defmodule MixTestInteractive.RunSummary do + @moduledoc false + alias MixTestInteractive.Settings + + @doc """ + Return a text summary of the current interactive mode settings. + """ + @spec from_settings(Settings.t()) :: String.t() + def from_settings(%Settings{} = settings) do + [&base_summary/1, &all_tag_filters/1, &max_failures/1, &repeat_count/1, &seed/1, &tracing/1] + |> Enum.flat_map(fn fun -> List.wrap(fun.(settings)) end) + |> Enum.join("\n") + end + + defp all_tag_filters(%Settings{} = settings) do + Enum.reject( + [ + tag_filters("Excluding tags", settings.excludes), + tag_filters("Including tags", settings.includes), + tag_filters("Only tags", settings.only) + ], + &is_nil/1 + ) + end + + defp base_summary(%Settings{} = settings) do + cond do + settings.failed? -> + "Ran only failed tests" + + settings.stale? -> + "Ran only stale tests" + + !Enum.empty?(settings.patterns) -> + "Ran all test files matching #{Enum.join(settings.patterns, ", ")}" + + true -> + "Ran all tests" + end + end + + defp max_failures(%Settings{max_failures: nil}), do: nil + + defp max_failures(%Settings{} = settings) do + "Max failures: #{settings.max_failures}" + end + + defp repeat_count(%Settings{repeat_count: nil}), do: nil + + defp repeat_count(%Settings{} = settings) do + "Repeat until failure: #{settings.repeat_count}" + end + + def seed(%Settings{seed: nil}), do: nil + + def seed(%Settings{} = settings) do + "Seed: #{settings.seed}" + end + + defp tracing(%Settings{tracing?: false}), do: nil + + defp tracing(%Settings{}) do + "Tracing: ON" + end + + defp tag_filters(_label, []), do: nil + + defp tag_filters(label, tags) do + label <> ": " <> inspect(tags) + end +end diff --git a/test/mix_test_interactive/run_summary_test.exs b/test/mix_test_interactive/run_summary_test.exs new file mode 100644 index 0000000..aab30e7 --- /dev/null +++ b/test/mix_test_interactive/run_summary_test.exs @@ -0,0 +1,89 @@ +defmodule MixTestInteractive.RunSummaryTest do + use ExUnit.Case, async: true + + alias MixTestInteractive.RunSummary + alias MixTestInteractive.Settings + + describe "summarizing a test run" do + test "ran all tests" do + settings = %Settings{} + + assert RunSummary.from_settings(settings) == "Ran all tests" + end + + test "ran failed tests" do + settings = Settings.only_failed(%Settings{}) + + assert RunSummary.from_settings(settings) == "Ran only failed tests" + end + + test "ran stale tests" do + settings = Settings.only_stale(%Settings{}) + + assert RunSummary.from_settings(settings) == "Ran only stale tests" + end + + test "ran specific patterns" do + settings = + Settings.only_patterns(%Settings{}, ["p1", "p2"]) + + assert RunSummary.from_settings(settings) == "Ran all test files matching p1, p2" + end + + test "appends max failures" do + settings = Settings.with_max_failures(%Settings{}, "6") + + assert RunSummary.from_settings(settings) =~ "Max failures: 6" + end + + test "appends repeat count" do + settings = Settings.with_repeat_count(%Settings{}, "150") + + assert RunSummary.from_settings(settings) =~ "Repeat until failure: 150" + end + + test "appends seed" do + settings = Settings.with_seed(%Settings{}, "4242") + + assert RunSummary.from_settings(settings) =~ "Seed: 4242" + end + + test "appends tag filters" do + settings = + %Settings{} + |> Settings.with_excludes(["tag1", "tag2"]) + |> Settings.with_includes(["tag3", "tag4"]) + |> Settings.with_only(["tag5", "tag6"]) + + summary = RunSummary.from_settings(settings) + + assert summary =~ ~s(Excluding tags: ["tag1", "tag2"]) + assert summary =~ ~s(Including tags: ["tag3", "tag4"]) + assert summary =~ ~s(Only tags: ["tag5", "tag6"]) + end + + test "appends tracing" do + settings = Settings.toggle_tracing(%Settings{}) + + assert RunSummary.from_settings(settings) =~ "Tracing: ON" + end + + test "includes only relevant information with no extra blank lines" do + settings = + %Settings{} + |> Settings.only_stale() + |> Settings.toggle_tracing() + |> Settings.with_only(["tag1", "tag2"]) + |> Settings.with_seed("4258") + + expected = """ + Ran only stale tests + Only tags: ["tag1", "tag2"] + Seed: 4258 + Tracing: ON + """ + + assert RunSummary.from_settings(settings) == String.trim(expected) + end + end +end diff --git a/test/mix_test_interactive/settings_test.exs b/test/mix_test_interactive/settings_test.exs index 5bc419d..9d55542 100644 --- a/test/mix_test_interactive/settings_test.exs +++ b/test/mix_test_interactive/settings_test.exs @@ -272,96 +272,4 @@ defmodule MixTestInteractive.SettingsTest do assert args == [] end end - - describe "summary" do - test "ran all tests" do - settings = %Settings{} - - assert Settings.summary(settings) == "Ran all tests" - end - - test "ran all tests with seed" do - seed = "4242" - settings = Settings.with_seed(%Settings{}, seed) - - assert Settings.summary(settings) == "Ran all tests with seed: #{seed}" - end - - test "ran failed tests" do - settings = Settings.only_failed(%Settings{}) - - assert Settings.summary(settings) == "Ran only failed tests" - end - - test "ran failed tests with seed" do - seed = "4242" - - settings = - %Settings{} - |> Settings.only_failed() - |> Settings.with_seed(seed) - - assert Settings.summary(settings) == "Ran only failed tests with seed: #{seed}" - end - - test "ran stale tests" do - settings = Settings.only_stale(%Settings{}) - - assert Settings.summary(settings) == "Ran only stale tests" - end - - test "ran stale tests with seed" do - seed = "4242" - - settings = - %Settings{} - |> Settings.only_stale() - |> Settings.with_seed(seed) - - assert Settings.summary(settings) == "Ran only stale tests with seed: #{seed}" - end - - test "ran specific patterns with seed" do - seed = "4242" - - settings = - %Settings{} - |> Settings.only_patterns(["p1", "p2"]) - |> Settings.with_seed(seed) - - assert Settings.summary(settings) == "Ran all test files matching p1, p2 with seed: #{seed}" - end - - test "appends max failures" do - settings = Settings.with_max_failures(%Settings{}, "6") - - assert Settings.summary(settings) =~ "Max failures: 6" - end - - test "appends repeat count" do - settings = Settings.with_repeat_count(%Settings{}, "150") - - assert Settings.summary(settings) =~ "Repeat until failure: 150" - end - - test "appends tag filters" do - settings = - %Settings{} - |> Settings.with_excludes(["tag1", "tag2"]) - |> Settings.with_includes(["tag3", "tag4"]) - |> Settings.with_only(["tag5", "tag6"]) - - summary = Settings.summary(settings) - - assert summary =~ ~s(Excluding tags: ["tag1", "tag2"]) - assert summary =~ ~s(Including tags: ["tag3", "tag4"]) - assert summary =~ ~s(Only tags: ["tag5", "tag6"]) - end - - test "appends tracing" do - settings = Settings.toggle_tracing(%Settings{}) - - assert Settings.summary(settings) =~ "Tracing: ON" - end - end end