@@ -27,6 +27,7 @@ defmodule ExUnit.CLIFormatter do
2727 test_counter: % { } ,
2828 test_timings: [ ] ,
2929 failure_counter: 0 ,
30+ failure_type_counter: % { } ,
3031 skipped_counter: 0 ,
3132 excluded_counter: 0 ,
3233 invalid_counter: 0
@@ -139,7 +140,14 @@ defmodule ExUnit.CLIFormatter do
139140
140141 test_counter = update_test_counter ( config . test_counter , test )
141142 failure_counter = config . failure_counter + 1
142- config = % { config | test_counter: test_counter , failure_counter: failure_counter }
143+ failure_type_counter = update_test_counter ( config . failure_type_counter , test )
144+
145+ config = % {
146+ config
147+ | test_counter: test_counter ,
148+ failure_counter: failure_counter ,
149+ failure_type_counter: failure_type_counter
150+ }
143151
144152 { :noreply , update_test_timings ( config , test ) }
145153 end
@@ -176,8 +184,16 @@ defmodule ExUnit.CLIFormatter do
176184 # The failed tests have already contributed to the counter,
177185 # so we should only add the successful tests to the count
178186 config =
179- update_in ( config . failure_counter , fn counter ->
180- counter + Enum . count ( test_module . tests , & is_nil ( & 1 . state ) )
187+ Enum . reduce ( test_module . tests , config , fn
188+ % { state: nil } = test , acc ->
189+ % {
190+ acc
191+ | failure_counter: acc . failure_counter + 1 ,
192+ failure_type_counter: update_test_counter ( acc . failure_type_counter , test )
193+ }
194+
195+ _test , acc ->
196+ acc
181197 end )
182198
183199 formatted =
@@ -352,11 +368,28 @@ defmodule ExUnit.CLIFormatter do
352368 defp print_summary ( config , force_failures? ) do
353369 test_type_counts = collect_test_type_counts ( config )
354370 test_counter = test_counter_or_default ( config , test_type_counts )
355- formatted_test_type_counts = format_test_type_counts ( test_counter )
356- failure_pl = pluralize ( config . failure_counter , "failure" , "failures" )
371+
372+ passed_total =
373+ test_type_counts - config . failure_counter - config . skipped_counter - config . invalid_counter
374+
375+ # Passed line: "Passed: 447/455 (53/54 doctests, 393/403 tests)"
376+ passed_breakdown = format_passed_breakdown ( test_counter , config . failure_type_counter )
377+
378+ passed_line =
379+ "Passed: #{ passed_total } /#{ test_type_counts } "
380+ |> if_true ( passed_breakdown != "" , & ( & 1 <> " (#{ passed_breakdown } )" ) )
381+
382+ # Failed line: "Failed: 8 tests, 1 property"
383+ failed_line =
384+ if config . failure_counter > 0 do
385+ failed_breakdown = format_type_counts ( config . failure_type_counter )
386+ "\n " <> failure ( "Failed: #{ failed_breakdown } " , config )
387+ else
388+ ""
389+ end
357390
358391 message =
359- " #{ formatted_test_type_counts } #{ config . failure_counter } #{ failure_pl } "
392+ passed_line
360393 |> if_true (
361394 config . invalid_counter > 0 ,
362395 & ( & 1 <> ", #{ config . invalid_counter } invalid" )
@@ -372,7 +405,7 @@ defmodule ExUnit.CLIFormatter do
372405
373406 cond do
374407 config . failure_counter > 0 or force_failures? ->
375- IO . puts ( failure ( message , config ) )
408+ IO . puts ( message <> failed_line )
376409
377410 config . invalid_counter > 0 ->
378411 IO . puts ( invalid ( message , config ) )
@@ -404,14 +437,34 @@ defmodule ExUnit.CLIFormatter do
404437 IO . puts ( formatted )
405438 end
406439
407- defp format_test_type_counts ( test_counter ) do
408- test_counter
440+ defp format_type_counts ( type_counter ) do
441+ type_counter
409442 |> Enum . sort ( )
410443 |> Enum . map ( fn { test_type , count } ->
411- type_pluralized = pluralize ( count , test_type , ExUnit . plural_rule ( test_type |> to_string ( ) ) )
412-
413- "#{ count } #{ type_pluralized } , "
444+ "#{ count } #{ pluralize_type ( count , test_type ) } "
414445 end )
446+ |> Enum . join ( ", " )
447+ end
448+
449+ defp format_passed_breakdown ( test_counter , failure_type_counter ) do
450+ types = test_counter |> Map . keys ( ) |> Enum . sort ( )
451+
452+ if length ( types ) <= 1 do
453+ ""
454+ else
455+ types
456+ |> Enum . map ( fn type ->
457+ total = Map . get ( test_counter , type , 0 )
458+ failed = Map . get ( failure_type_counter , type , 0 )
459+ passed = total - failed
460+ "#{ passed } /#{ total } #{ pluralize_type ( total , type ) } "
461+ end )
462+ |> Enum . join ( ", " )
463+ end
464+ end
465+
466+ defp pluralize_type ( count , type ) do
467+ pluralize ( count , type , ExUnit . plural_rule ( to_string ( type ) ) )
415468 end
416469
417470 defp test_counter_or_default ( _config , 0 ) do
0 commit comments