@@ -121,6 +121,10 @@ defmodule Mix.Tasks.Test do
121121
122122 * `--cover` - runs coverage tool. See "Coverage" section below
123123
124+ * `--dry-run` - prints which tests would be run based on current options,
125+ but does not actually run any tests. This combines with all other options
126+ like `--stale`, `--only`, `--exclude`, etc.
127+
124128 * `--exclude` - excludes tests that match the filter. This option may be given
125129 several times to apply different filters, such as `--exclude ci --exclude slow`
126130
@@ -494,7 +498,8 @@ defmodule Mix.Tasks.Test do
494498 warnings_as_errors: :boolean ,
495499 profile_require: :string ,
496500 exit_status: :integer ,
497- repeat_until_failure: :integer
501+ repeat_until_failure: :integer ,
502+ dry_run: :boolean
498503 ]
499504
500505 @ cover [ output: "cover" , tool: Mix.Tasks.Test.Coverage ]
@@ -623,6 +628,7 @@ defmodule Mix.Tasks.Test do
623628
624629 warnings_as_errors? = Keyword . get ( opts , :warnings_as_errors , false )
625630 exit_status = Keyword . fetch! ( ex_unit_opts , :exit_status )
631+ dry_run? = Keyword . get ( opts , :dry_run , false )
626632
627633 # Prepare and extract all files to require and run
628634 test_paths = project [ :test_paths ] || default_test_paths ( )
@@ -659,69 +665,115 @@ defmodule Mix.Tasks.Test do
659665
660666 warn_files != [ ] && warn_misnamed_test_files ( warn_files )
661667
662- try do
663- Enum . each ( test_paths , & require_test_helper ( shell , & 1 ) )
664- # test_opts always wins because those are given via args
665- ExUnit . configure ( ex_unit_opts |> merge_helper_opts ( ) |> Keyword . merge ( test_opts ) )
666- CT . require_and_run ( matched_test_files , test_paths , test_elixirc_options , opts )
667- catch
668- kind , reason ->
669- # Also mark the whole suite as failed
670- file = Keyword . fetch! ( opts , :failures_manifest_path )
671- ExUnit.Filters . fail_all! ( file )
672- :erlang . raise ( kind , reason , __STACKTRACE__ )
668+ if dry_run? do
669+ do_dry_run ( matched_test_files )
670+ else
671+ do_wet_run (
672+ shell ,
673+ cover ,
674+ test_paths ,
675+ files ,
676+ matched_test_files ,
677+ test_opts ,
678+ test_elixirc_options ,
679+ ex_unit_opts ,
680+ warnings_as_errors? ,
681+ exit_status ,
682+ opts
683+ )
684+ end
685+ end
686+
687+ defp do_dry_run ( matched_test_files ) do
688+ if matched_test_files == [ ] do
689+ Mix . shell ( ) . info ( """
690+ -- DRY RUN --
691+ No tests would run
692+ """ )
673693 else
674- { :ok , % { excluded: excluded , failures: failures , warnings?: warnings? , total: total } } ->
675- Mix . shell ( shell )
676- cover && cover . ( )
694+ Mix . shell ( ) . info ( """
695+ -- DRY RUN --
696+ The following test files would be run:
697+
698+ #{ Enum . join ( matched_test_files , "\n " ) }
699+ """ )
700+ end
701+ end
677702
678- cond do
679- warnings_as_errors? and warnings? and failures == 0 ->
680- message =
681- "\n ERROR! Test suite aborted after successful execution due to warnings while using the --warnings-as-errors option"
703+ defp do_wet_run (
704+ shell ,
705+ cover ,
706+ test_paths ,
707+ files ,
708+ matched_test_files ,
709+ test_opts ,
710+ test_elixirc_options ,
711+ ex_unit_opts ,
712+ warnings_as_errors? ,
713+ exit_status ,
714+ opts
715+ ) do
716+ Enum . each ( test_paths , & require_test_helper ( shell , & 1 ) )
717+ # test_opts always wins because those are given via args
718+ ExUnit . configure ( ex_unit_opts |> merge_helper_opts ( ) |> Keyword . merge ( test_opts ) )
719+ CT . require_and_run ( matched_test_files , test_paths , test_elixirc_options , opts )
720+ catch
721+ kind , reason ->
722+ # Also mark the whole suite as failed
723+ file = Keyword . fetch! ( opts , :failures_manifest_path )
724+ ExUnit.Filters . fail_all! ( file )
725+ :erlang . raise ( kind , reason , __STACKTRACE__ )
726+ else
727+ { :ok , % { excluded: excluded , failures: failures , warnings?: warnings? , total: total } } ->
728+ Mix . shell ( shell )
729+ cover && cover . ( )
682730
683- IO . puts ( :stderr , IO.ANSI . format ( [ :red , message ] ) )
731+ cond do
732+ warnings_as_errors? and warnings? and failures == 0 ->
733+ message =
734+ "\n ERROR! Test suite aborted after successful execution due to warnings while using the --warnings-as-errors option"
735+
736+ IO . puts ( :stderr , IO.ANSI . format ( [ :red , message ] ) )
684737
685- System . at_exit ( fn _ ->
686- exit ( { :shutdown , 1 } )
687- end )
738+ System . at_exit ( fn _ ->
739+ exit ( { :shutdown , 1 } )
740+ end )
688741
689- failures > 0 and opts [ :raise ] ->
690- raise_with_shell ( shell , "\" mix test\" failed" )
742+ failures > 0 and opts [ :raise ] ->
743+ raise_with_shell ( shell , "\" mix test\" failed" )
691744
692- warnings_as_errors? and warnings? and failures > 0 ->
693- System . at_exit ( fn _ ->
694- exit ( { :shutdown , exit_status + 1 } )
695- end )
745+ warnings_as_errors? and warnings? and failures > 0 ->
746+ System . at_exit ( fn _ ->
747+ exit ( { :shutdown , exit_status + 1 } )
748+ end )
696749
697- failures > 0 ->
698- System . at_exit ( fn _ ->
699- exit ( { :shutdown , exit_status } )
700- end )
750+ failures > 0 ->
751+ System . at_exit ( fn _ ->
752+ exit ( { :shutdown , exit_status } )
753+ end )
701754
702- excluded == total and Keyword . has_key? ( opts , :only ) ->
703- message = "The --only option was given to \" mix test\" but no test was executed"
704- raise_or_error_at_exit ( shell , message , opts )
755+ excluded == total and Keyword . has_key? ( opts , :only ) ->
756+ message = "The --only option was given to \" mix test\" but no test was executed"
757+ raise_or_error_at_exit ( shell , message , opts )
705758
706- true ->
707- :ok
708- end
759+ true ->
760+ :ok
761+ end
709762
710- :noop ->
711- cond do
712- opts [ :stale ] ->
713- Mix . shell ( ) . info ( "No stale tests" )
763+ :noop ->
764+ cond do
765+ opts [ :stale ] ->
766+ Mix . shell ( ) . info ( "No stale tests" )
714767
715- opts [ :failed ] || files == [ ] ->
716- Mix . shell ( ) . info ( "There are no tests to run" )
768+ opts [ :failed ] || files == [ ] ->
769+ Mix . shell ( ) . info ( "There are no tests to run" )
717770
718- true ->
719- message = "Paths given to \" mix test\" did not match any directory/file: "
720- raise_or_error_at_exit ( shell , message <> Enum . join ( files , ", " ) , opts )
721- end
771+ true ->
772+ message = "Paths given to \" mix test\" did not match any directory/file: "
773+ raise_or_error_at_exit ( shell , message <> Enum . join ( files , ", " ) , opts )
774+ end
722775
723- :ok
724- end
776+ :ok
725777 end
726778
727779 # similar to Mix.Utils.extract_files/2, but returns a list of directly included test files,
@@ -847,7 +899,8 @@ defmodule Mix.Tasks.Test do
847899 :only_test_ids ,
848900 :test_location_relative_path ,
849901 :exit_status ,
850- :repeat_until_failure
902+ :repeat_until_failure ,
903+ :dry_run
851904 ]
852905
853906 @ doc false
0 commit comments