Io:fwrite does not display anything inside eunit code

My eunit code xyz_test_() has many lines of code. For example, it calls a function to find out the expected reply, before comparing it with the actual reply using the ?assertEqual macro.

I have tried to add io:fwrite inside the eunit code for debugging. But I do not see any output written by io:fwrite. What could be the reason?

I have put an example code below.

-module(my_sort).
-export([sort/1]).
-include_lib("eunit/include/eunit.hrl").

-spec sort([T]) -> [T].
sort([]) -> [];
sort([P|Xs]) ->
  sort([X || X <- Xs, X < P]) ++ [P] ++ sort([X || X <- Xs, P < X]).

sort2_test_() ->
  [ {"testcase with 4 paras", fun test_four/0},
    {"testcase with 5 paras", fun test_five/0}].

test_four() ->
  io:fwrite("Started test_4\n"),
  [?_assertEqual([1,2,3,4], sort([3,1,4,2]))].
test_five() ->
  io:fwrite("Started test_5\n"),
  [?_assertEqual([1,2,3,4,5], sort([3,1,4,2,5]))].
1 Like

this is explained in the eunit user-guide:

EUnit captures standard output

If your test code writes to the standard output, you may be surprised to see that the text does not appear on the console when the tests are running. This is because EUnit captures all standard output from test functions (this also includes setup and cleanup functions, but not generator functions), so that it can be included in the test report if errors occur. To bypass EUnit and print text directly to the console while testing, you can write to the user output stream, as in io:format(user, “~w”, [Term]). The recommended way of doing this is to use the EUnit Debugging macros, which make it much simpler.

changing your code to use ?debugMsg:

-module(my_sort).
-export([sort/1]).
-include_lib("eunit/include/eunit.hrl").

-spec sort([T]) -> [T].
sort([]) -> [];
sort([P|Xs]) ->
  sort([X || X <- Xs, X < P]) ++ [P] ++ sort([X || X <- Xs, P < X]).

sort2_test_() ->
  [ {"testcase with 4 paras", fun test_four/0},
    {"testcase with 5 paras", fun test_five/0}].

test_four() ->
  ?debugMsg("Started test_4\n"),
  [?_assertEqual([1,2,3,4], sort([3,1,4,2]))].
test_five() ->
  ?debugMsg("Started test_5\n"),  
  [?_assertEqual([1,2,3,4,5], sort([3,1,4,2,5]))].

shows the following output:

% rebar3 eunit                                                                       
===> Verifying dependencies...                                                                            
===> Analyzing applications...                                                                            
===> Compiling mylib                                                                                      
===> Performing EUnit tests...                                                                            
/private/tmp/mylib/test/my_sort.erl:15:<0.173.0>: Started test_4                                          
                                                                                                          
/private/tmp/mylib/test/my_sort.erl:18:<0.173.0>: Started test_5                                          
                                                                                                          
..                                                                                                        
Finished in 0.020 seconds                                                                                 
2 tests, 0 failures        
5 Likes

Thanks, Felix. It worked.

Another query. What about the text specified in sort2_test_()>

sort2_test_() ->
  [ {"testcase with 4 paras", fun test_four/0},
    {"testcase with 5 paras", fun test_five/0}].
2 Likes

thats the “title”, see Erlang -- EUnit - a Lightweight Unit Testing Framework for Erlang

Since this is tagged with rebar3, for example if you use verbose flag you see it (or if something fails):

% rebar3 eunit -v                                                         
===> Verifying dependencies...                                                                            
===> Analyzing applications...                                                                            
===> Compiling mylib                                                                                      
===> Performing EUnit tests...                                                                            
======================== EUnit ========================                                                   
file "mylib.app"                                                                                          
  application 'mylib'                                                                                     
    module 'mylib'                                                                                        
    [done in 0.001 s]                                                                                     
  [done in 0.002 s]                                                                                       
module 'my_sort'                                                                                          
  my_sort: fun.test_four (testcase with 4 paras)...ok                                                     
  my_sort: fun.test_five (testcase with 5 paras)...ok                                                     
                          ^^^^^^^^^^^^^^^^^^^^^
  [done in 0.006 s]                                                                                       
=======================================================                                                   
  2 tests passed.                                                 

(highlighed with ^^^^… :slight_smile: )

3 Likes

Thanks, Felix. It worked.

1 Like

Another useful trick is to prefix the io functions with the special IO device user which goes to the top group leader IO device:

io:format(user, "Started test_4\n", [])

That bypasses most (all?) of such IO-redirecting magic.

2 Likes