diff --git a/lib/ex_unit/lib/ex_unit/cli_formatter.ex b/lib/ex_unit/lib/ex_unit/cli_formatter.ex index f4d2982c3d..06d63c0669 100644 --- a/lib/ex_unit/lib/ex_unit/cli_formatter.ex +++ b/lib/ex_unit/lib/ex_unit/cli_formatter.ex @@ -18,6 +18,7 @@ defmodule ExUnit.CLIFormatter do IO.puts("") config = %{ + dry_run: opts[:dry_run], trace: opts[:trace], colors: colors(opts), width: get_terminal_width(), @@ -154,7 +155,16 @@ defmodule ExUnit.CLIFormatter do {:noreply, config} end - def handle_cast({:module_finished, %ExUnit.TestModule{state: nil}}, config) do + def handle_cast({:module_finished, %ExUnit.TestModule{state: nil} = module}, config) do + if config.dry_run do + IO.puts("Test dry run:") + file_path = Path.relative_to_cwd(module.file) + + Enum.each(module.tests, fn test -> + IO.puts("#{file_path}:#{test.tags.line}") + end) + end + {:noreply, config} end @@ -356,7 +366,11 @@ defmodule ExUnit.CLIFormatter do ) |> if_true( config.excluded_counter > 0, - &(&1 <> " (#{config.excluded_counter} excluded)") + &(&1 <> ", (#{config.excluded_counter} excluded)") + ) + |> if_true( + config.dry_run == true, + &(&1 <> " (dry run)") ) cond do diff --git a/lib/ex_unit/lib/ex_unit/runner.ex b/lib/ex_unit/lib/ex_unit/runner.ex index ff4c3b218f..67fc19431d 100644 --- a/lib/ex_unit/lib/ex_unit/runner.ex +++ b/lib/ex_unit/lib/ex_unit/runner.ex @@ -88,7 +88,8 @@ defmodule ExUnit.Runner do seed: opts[:seed], stats_pid: stats_pid, timeout: opts[:timeout], - trace: opts[:trace] + trace: opts[:trace], + dry_run: opts[:dry_run] } end @@ -306,6 +307,10 @@ defmodule ExUnit.Runner do {test_module, [], []} end + defp run_module_tests(%{dry_run: true}, test_module, _async?, tests) do + {test_module, [], tests} + end + defp run_module_tests(config, test_module, async?, tests) do Process.put(@current_key, test_module) %ExUnit.TestModule{name: module, tags: tags, parameters: params} = test_module diff --git a/lib/mix/lib/mix/tasks/test.ex b/lib/mix/lib/mix/tasks/test.ex index ad32028f91..f6eb1a44d0 100644 --- a/lib/mix/lib/mix/tasks/test.ex +++ b/lib/mix/lib/mix/tasks/test.ex @@ -121,6 +121,10 @@ defmodule Mix.Tasks.Test do * `--cover` - runs coverage tool. See "Coverage" section below + * `--dry-run` *(since v1.19.0)* - prints which tests would be run based on current options, + but does not actually run any tests. This combines with all other options + like `--stale`, `--only`, `--exclude`, and so on. + * `--exclude` - excludes tests that match the filter. This option may be given several times to apply different filters, such as `--exclude ci --exclude slow` @@ -494,7 +498,8 @@ defmodule Mix.Tasks.Test do warnings_as_errors: :boolean, profile_require: :string, exit_status: :integer, - repeat_until_failure: :integer + repeat_until_failure: :integer, + dry_run: :boolean ] @cover [output: "cover", tool: Mix.Tasks.Test.Coverage] @@ -847,7 +852,8 @@ defmodule Mix.Tasks.Test do :only_test_ids, :test_location_relative_path, :exit_status, - :repeat_until_failure + :repeat_until_failure, + :dry_run ] @doc false diff --git a/lib/mix/test/mix/tasks/test_test.exs b/lib/mix/test/mix/tasks/test_test.exs index f5d792ce47..24037a63d5 100644 --- a/lib/mix/test/mix/tasks/test_test.exs +++ b/lib/mix/test/mix/tasks/test_test.exs @@ -716,6 +716,39 @@ defmodule Mix.Tasks.TestTest do end end + describe "--dry-run" do + test "works with --stale" do + in_fixture("test_stale", fn -> + File.write!("test/dry_run_test_stale.exs", """ + defmodule DryRunTest do + use ExUnit.Case + + test "new test" do + assert true + end + end + """) + + output = mix(["test", "--dry-run", "--stale"]) + + assert output =~ "Test dry run:" + assert output =~ "test/dry_run_test_stale.exs:4" + assert output =~ "0 tests, 0 failures (dry run)" + end) + end + + test "works with --failed" do + in_fixture("test_failed", fn -> + _initial_run = mix(["test"]) + output = mix(["test", "--dry-run", "--failed"]) + + assert output =~ "Test dry run:" + assert output =~ "test/passing_and_failing_test_failed.exs:5" + assert output =~ "0 tests, 0 failures (dry run)" + end) + end + end + defp receive_until_match(port, expected, acc) do receive do {^port, {:data, output}} ->