Skip to content

Commit 32571b4

Browse files
authored
Return --exit-status + 1 when warnings as errors and test failures (#14405)
1 parent c0ba8a1 commit 32571b4

File tree

3 files changed

+63
-18
lines changed

3 files changed

+63
-18
lines changed

lib/mix/lib/mix/compilers/test.ex

+3-12
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,17 @@ defmodule Mix.Compilers.Test do
7777

7878
true ->
7979
task = ExUnit.async_run()
80-
warnings_as_errors? = Keyword.get(opts, :warnings_as_errors, false)
8180
seed = Application.fetch_env!(:ex_unit, :seed)
8281
rand_algorithm = Application.fetch_env!(:ex_unit, :rand_algorithm)
8382
test_files = shuffle(seed, rand_algorithm, test_files)
8483

8584
try do
8685
parallel_require_options = shared_require_options ++ parallel_require_callbacks
8786

88-
failed? =
87+
warnings? =
8988
case Kernel.ParallelCompiler.require(test_files, parallel_require_options) do
9089
{:ok, _, %{compile_warnings: c, runtime_warnings: r}}
91-
when (c != [] or r != []) and warnings_as_errors? ->
90+
when c != [] or r != [] ->
9291
true
9392

9493
{:ok, _, _} ->
@@ -101,18 +100,10 @@ defmodule Mix.Compilers.Test do
101100
%{failures: failures} = results = ExUnit.await_run(task)
102101

103102
if failures == 0 do
104-
if failed? do
105-
message =
106-
"\nERROR! Test suite aborted after successful execution due to warnings while using the --warnings-as-errors option"
107-
108-
IO.puts(:stderr, IO.ANSI.format([:red, message]))
109-
exit({:shutdown, 1})
110-
end
111-
112103
agent_write_manifest(stale_manifest_pid)
113104
end
114105

115-
{:ok, results}
106+
{:ok, Map.put(results, :warnings?, warnings?)}
116107
catch
117108
kind, reason ->
118109
# In case there is an error, shut down the runner task

lib/mix/lib/mix/tasks/test.ex

+26-4
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,12 @@ defmodule Mix.Tasks.Test do
209209
Note that in trace mode test timeouts will be ignored as timeout is set to `:infinity`
210210
211211
* `--warnings-as-errors` *(since v1.12.0)* - treats compilation warnings (from loading the
212-
test suite) as errors and returns a non-zero exit status if the test suite would otherwise
213-
pass. Note that failures reported by `--warnings-as-errors` cannot be retried with the
212+
test suite) as errors and returns an exit status of 1 if the test suite would otherwise
213+
pass. If the test suite fails and also include warnings as errors, the exit
214+
status returned will be the value of the `--exit-status` option, which
215+
defaults to 2, plus one. Therefore in the default case, this will be exit status 3.
216+
217+
Note that failures reported by `--warnings-as-errors` cannot be retried with the
214218
`--failed` flag.
215219
216220
This option only applies to test files. To treat warnings as errors during compilation and
@@ -617,6 +621,9 @@ defmodule Mix.Tasks.Test do
617621
{ex_unit_opts, allowed_files} = process_ex_unit_opts(opts)
618622
ExUnit.configure(ex_unit_opts)
619623

624+
warnings_as_errors? = Keyword.get(opts, :warnings_as_errors, false)
625+
exit_status = Keyword.fetch!(ex_unit_opts, :exit_status)
626+
620627
# Prepare and extract all files to require and run
621628
test_paths = project[:test_paths] || default_test_paths()
622629
test_pattern = project[:test_pattern] || "*.{ex,exs}"
@@ -664,17 +671,32 @@ defmodule Mix.Tasks.Test do
664671
ExUnit.Filters.fail_all!(file)
665672
:erlang.raise(kind, reason, __STACKTRACE__)
666673
else
667-
{:ok, %{excluded: excluded, failures: failures, total: total}} ->
674+
{:ok, %{excluded: excluded, failures: failures, warnings?: warnings?, total: total}} ->
668675
Mix.shell(shell)
669676
cover && cover.()
670677

671678
cond do
679+
warnings_as_errors? and warnings? and failures == 0 ->
680+
message =
681+
"\nERROR! Test suite aborted after successful execution due to warnings while using the --warnings-as-errors option"
682+
683+
IO.puts(:stderr, IO.ANSI.format([:red, message]))
684+
685+
System.at_exit(fn _ ->
686+
exit({:shutdown, 1})
687+
end)
688+
672689
failures > 0 and opts[:raise] ->
673690
raise_with_shell(shell, "\"mix test\" failed")
674691

692+
warnings_as_errors? and warnings? and failures > 0 ->
693+
System.at_exit(fn _ ->
694+
exit({:shutdown, exit_status + 1})
695+
end)
696+
675697
failures > 0 ->
676698
System.at_exit(fn _ ->
677-
exit({:shutdown, Keyword.fetch!(ex_unit_opts, :exit_status)})
699+
exit({:shutdown, exit_status})
678700
end)
679701

680702
excluded == total and Keyword.has_key?(opts, :only) ->

lib/mix/test/mix/tasks/test_test.exs

+34-2
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ defmodule Mix.Tasks.TestTest do
558558
end
559559

560560
describe "--warnings-as-errors" do
561-
test "fail on warning in tests" do
561+
test "fail with exit status 1 if warning in tests but tests pass" do
562562
in_fixture("test_stale", fn ->
563563
msg =
564564
"Test suite aborted after successful execution due to warnings while using the --warnings-as-errors option"
@@ -579,10 +579,42 @@ defmodule Mix.Tasks.TestTest do
579579
end
580580
""")
581581

582-
output = mix(["test", "--warnings-as-errors", "test/warning_test_stale.exs"])
582+
{output, exit_status} =
583+
mix_code(["test", "--warnings-as-errors", "test/warning_test_stale.exs"])
584+
583585
assert output =~ "variable \"unused_compile_var\" is unused"
584586
assert output =~ "variable \"unused_test_var\" is unused"
585587
assert output =~ msg
588+
assert exit_status == 1
589+
end)
590+
end
591+
592+
test "fail with --exit-status + 1 if warning in tests and tests fail" do
593+
in_fixture("test_stale", fn ->
594+
File.write!("test/warning_test_warnings_as_errors_and_failures.exs", """
595+
defmodule WarningsAsErrorsAndFailuresTest do
596+
use ExUnit.Case
597+
598+
test "warning and failure" do
599+
unused_test_var = 1
600+
assert false
601+
end
602+
end
603+
""")
604+
605+
{output, exit_status} =
606+
mix_code([
607+
"test",
608+
"--warnings-as-errors",
609+
"--exit-status",
610+
"42",
611+
"test/warning_test_warnings_as_errors_and_failures.exs"
612+
])
613+
614+
assert output =~ "variable \"unused_test_var\" is unused"
615+
assert output =~ "1 failure"
616+
617+
assert exit_status == 43
586618
end)
587619
end
588620

0 commit comments

Comments
 (0)