Thursday, July 5, 2012

eunit truncates terms when outputting diff

Apparently this is not eunit's fault, but rather something to do with the shell. There is a workaround which is to output to file instead of the shell:

Use eunit with surefire:
eunit:test(my_module, [{report,{eunit_surefire,[{dir,"."}]}}]).

this will create a file called TEST-something.xml which will print out the full terms if a test fails

If you are running eunit via dialyzer like this:


$> rebar eunit

Then you can create the xml files by adding this line to your rebar.config:

{eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}.

This will make the tests more verbose (remove the verbose option if you do not want that).
It will also create the xml files in the same directory as the beam files created for the test which is called .eunit.

For example if you have the following structure for your app:
| my_app
|-- src
|-- ebin
| -- .eunt

Compiling Erlang modules for Unit Test

%% When compiling erlang modules for testing, some of the common options are
  debug_info
and
  export_all
e.g. from the shell:
compile:file(my_module, [debug_info, export_all]).

%% or you can use
c(my_module, [debug_info, export_all]).

%% If my_module is not in the current path, you can specify the full path as a string:
c("apps/my_app/src/my_module.erl", [export_all, {outdir, "apps/my_module/ebin"}, {d, 'TEST'}]).

%% OR
c("src/bid_processor", [export_all, {outdir, "ebin"}, {d, 'TEST'}]).

%% If you suspect that your module under test does not behave according to the most recent code changes you can check that the shell has not loaded some stray beam file from another directory:
code:which(my_module).
%% This will return the full path to the module

%% And if you really want to you can unload the module with
code:purge(my_module).
code:delete(my_module).

%% When running eunit test cases it often happens that the diff of 2 terms is truncated. e.g. when you compare 2 large tuples.  You can output the test log to a file and in the file the terms are not truncated.

You can use
code:get_path().
to get a list of paths used in the erlang shell, most likely you will have to wrap that method in the shell command rp, otherwise the shell will truncate the output e.g.
rp(code:get_path()).


It is very useful if you have a directory called e.g. apps and which contains a collection of erlang applications to set the ERL_LIBS environment variable e.g.
export ERL_LIBS=/home/philip/erlang/apps
When you start up the erlang shell, and do code:get_path(), you will see that for each application, erlang has automatically set a path to the ebin directory.

Tuesday, July 3, 2012

erlang registering and monitoring global processes

Please note, the shell command numbers may not be in order as I put this together in a hurry.

% start up an erlang node
 erl -sname a -setcookie qwerty




%% create a new process which echos back anything it receives
(a@philipclarkeirl-desktop)1> Pid = spawn(fun() -> receive {Sender, Msg} -> Sender ! Msg end end).
<0.40.0>



%% test it out
(a@philipclarkeirl-desktop)2> Pid ! {self(), "Hello"}.
{<0.38.0>,"Hello"}


%% globally register the process
 (a@philipclarkeirl-desktop)3> global:register_name(myprocess, Pid).
yes


%% check it is registered
(a@philipclarkeirl-desktop)4> global:registered_names().
[myprocess]



(a@philipclarkeirl-desktop)6> global:whereis_name(myprocess) =:= Pid.
true
 

%% send to myprocess a message
(a@philipclarkeirl-desktop)7> global:send(myprocess, {self(), "Hello from shell"}).
<0.40.0>


%% note the return value is the pid found for myprocess
 

%% check in the shell that we received a response
(a@philipclarkeirl-desktop)8> flush().
Shell got "Hello from shell"
ok



%% start up another node
erl -sname b -setcookie qwerty

%% check that the process is globally registered
(b@philipclarkeirl-desktop)3> global:registered_names().
[myprocess]


%% monitor the process started in node a
(b@philipclarkeirl-desktop)11> MRef = erlang:monitor(process, global:whereis_name(myprocess)).
#Ref<0.0.0.83>



%% in node a, kill the process
(a@philipclarkeirl-desktop)33> exit(Pid, kill).
true


%% in node b
(b@philipclarkeirl-desktop)12> flush().
Shell got {'DOWN',#Ref<0.0.0.83>,process,<5799.85.0>,killed}
ok