I'm write a test with EUnit, but not anything exception detail output in console.
exp_test() ->
?assertEqual(0, 1/0).
Run this module:exp_test() in the Erlang Shell output following
** exception error: bad argument in an arithmetic expression
in function exp_test:'-exp_test/0-fun-0-'/1 (src/test/eunit/xxx_test.erl, line 8)
But in EUnit output following
> eunit:test(xxx).
> xxx_test: exp_test...*failed*
::badarith
EUnit not output anything exception trace info
Im trying the verbose config in eunit, but no effect.
I want to output some exception detail in eunit test result.
Thanks~
The problem seems to be that the version of eunit shipped with R15 does not understand the new stack trace format in R15. This has been fixed in the development version of eunit: github.com/richcarl/eunit
For example:
Eshell V5.10 (abort with ^G)
1> eunit:test(fun() -> (fun() -> exit(foo), ok end)() end).
erl_eval: expr...*failed*
in function erl_eval:do_apply/6 (erl_eval.erl, line 576)
in call from erl_eval:exprs/5 (erl_eval.erl, line 118)
**exit:foo
I hope this will make it into the next release of OTP R15.
This is a known problem in eunit as released in R15B and R15B01. This has been fixed in release R15B02. If you're stuck with an earlier version, you can download and apply a patch:
A workaround for releases before R15B02
You can fix the problem in your local installation by recompiling the affected module:
Download and unpack the Erlang/OTP sources, if you don't have them already.
wget http://www.erlang.org/download/otp_src_R15B01.tar.gz
tar xzf otp_src_R15B01.tar.gz
cd otp_src_R15B01
Download and apply the patch.
wget -O eunit-stacktrace.patch https://github.com/erlang/otp/commit/73b94a990bb91fd263dace4ccbaef6ff727a9637.patch
patch -p1 < eunit-stacktrace.patch
Recompile eunit_lib.erl.
cd lib/eunit
erlc -o ebin -I include src/eunit_lib.erl
Copy the new eunit_lib.beam over the old one (usually somewhere below /usr/local).
ls /usr/local/lib/erlang/lib/eunit-2.2.2/ebin/
# check that eunit_lib.beam is actually there
sudo cp ebin/eunit_lib.beam /usr/local/lib/erlang/lib/eunit-2.2.2/ebin/
Eunit is quite old and while it is officially maintained by the OTP team at Ericsson, it is usually uncared for. Eunit currently has the bad habit of eating up stack traces, and hasn't been updated for R15's line numbers in exceptions.
I wouldn't argue that "that's how it's supposed to work". No sane test tool should hide exception details and line numbers for you.
A trick I like to use is ?debugVal(catch expr) where expr is either a begin end block
or a call to the failing function. For example, ?debugVal(catch begin 1 = 2 end) will output a stacktrace in your tests.
Related
I get an error like this when I execute the command. How do I fix this error?
Erlang Version: 22.3
Operating System: Centos OS 7
{"init terminating in do_boot",{{badmatch,{error,{1,erl_parse,["syntax error before: ","','"]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({{badmatch,{error,{1,erl_parse,[_]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
It is syntax error, not difficult to debug.
You should have source code and check the program and write some debug statement if necessary.
Mot likely the $1 and $option are not resolving to correct values...
As I try the following command, trying to simulate what might be executing as part of the shell script, I get the same error as you are...
$ erl -noshell -pa /tools_core/ebin -pa ./ebin -eval "make:all(),gen_data:gen(,)" -s c q
{"init terminating in do_boot",{{badmatch,{error,{1,erl_parse,["syntax error before: ","','"]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({{badmatch,{error,{1,erl_parse,[_]}}},[{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
So most likely, you should check what values they are resolving to. If they are resolving to an empty value, then erlang parse will fail. Since it says before ,, I suspect it's the resolution of $1 which is not happening properly.
can you echo these values and let us know what are they resolving to??
Most likely, $1 should take the command line argument which gets passed along while invoking this shell script. Since its your environment, can't say much. But please try and share what $1 is resolving to in your case.
I have running application and in the interactive console I try to run common test suites located in test/common directory:
ct:run("test/common").
But I get a bunch of errors:
Reason: undef
and all tests fail.
I tried to run them from linux shell
ct_run -dir test/common
or like this:
ct_run -boot start_sasl -spec test/common/app_ct.spec -erl_args -config env/dev.config
with the same result.
But when I run them using rebar (the second version, not rebar3)
rebar ct
Everything works, tests pass. But it takes too much time to compile the app and to start it.
In the rebar.config I have:
{ct_dir,"test/common"}.
{ct_log_dir,"test/logs"}.
{ct_extra_params,"-boot start_sasl -pa deps/*/ebin -pa ebin -spec test/common/app_ct.spec -erl_args -config env/dev.config"}.
and in the test/common/app_ct.spec I have:
{verbosity, 100}.
{init, {eval, [{application, ensure_all_started, [app]}, {timer, sleep, [30000]}]}}.
{alias, common, "./test/common/"}.
{suites, "", [app_srv_SUITE, app_client_SUITE]}.
What can I do to run tests from erl console using ct:run("test/common")?
My goal is to be able to recompile single test files individually and run tests from working application console without stopping and recompiling all application.
I recompile singular test module without problems like this:
c("test/common/new_mod_SUITE.erl", [{i, "include"}, {i, "deps"}, {outdir, "test/common"}]).
But I still can't run tests after that.
First of all, need to be sure that all tests is compiled and they are inside of folder what is put as argument into ct:run/1. If need to run only one test from specific folder, can be used ct:run/2. If need to run specific test case from specific folder, can be used specific folder ct:run/3. Examples:
1> ct:run("test/common").
2> ct:run("test/common", "some_SUITE").
However I would recommend using rebar3, in rebar3 was added option like --dir and tests from specific folder can be run like:
$ ./rebar3 ct --dir="test/common"
This probably won't help, but here is what happens for me using rebar3:
~/erlang_programs/myrebar/myapp$ ls
LICENSE _build rebar.lock test
README.md rebar.config src
~/erlang_programs/myrebar/myapp$ cd src
~/erlang_programs/myrebar/myapp/src$ ls
a.erl myapp_app.erl rebar.lock
myapp.app.src myapp_sup.erl
~/erlang_programs/myrebar/myapp/src$ cat a.erl
-module(a).
-compile(export_all).
%%-include("eunit.hrl").
hello() -> io:format("hello").
~/erlang_programs/myrebar/myapp/src$ cd ../test
~/erlang_programs/myrebar/myapp/test$ ls
a_SUITE.erl
~/erlang_programs/myrebar/myapp/test$ cat a_SUITE.erl
-module(a_SUITE).
-compile(export_all).
all() -> [go].
go(_Config) ->
1 = 1.
~/erlang_programs/myrebar/myapp/test$ cd ..
~/erlang_programs/myrebar/myapp$ rebar3 compile
===> Verifying dependencies...
===> Compiling myapp
~/erlang_programs/myrebar/myapp$ rebar3 shell
===> Verifying dependencies...
===> Compiling myapp
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> ===> The rebar3 shell is a development tool; to deploy applications in production, consider using releases (http://www.rebar3.org/docs/releases)
===> Booted myapp
1> ct:run("test").
Common Test: Running make in test directories...
Recompile: a_SUITE
a_SUITE.erl:2: Warning: export_all flag enabled - all functions will be exported
CWD set to: "/Users/7stud/erlang_programs/myrebar/myapp/ct_run.nonode#nohost.2021-02-14_14.26.08"
TEST INFO: 1 test(s), 1 case(s) in 1 suite(s)
Testing myrebar.myapp: Starting test, 1 test cases
Testing myrebar.myapp: TEST COMPLETE, 1 ok, 0 failed of 1 test cases
Updating /Users/7stud/erlang_programs/myrebar/myapp/index.html ... done
Updating /Users/7stud/erlang_programs/myrebar/myapp/all_runs.html ... done
{1,0,{0,0}}
2>
Then after exiting the shell:
~/erlang_programs/myrebar/myapp$
~/erlang_programs/myrebar/myapp$ rebar3 ct
===> Verifying dependencies...
===> Compiling myapp
test/a_SUITE.erl:2: Warning: export_all flag enabled - all functions will be exported
===> Running Common Test suites...
%%% a_SUITE: .
All 1 tests passed.
~/erlang_programs/myrebar/myapp$
I didn't touch rebar.config, it is the default produced by rebar3:
{erl_opts, [debug_info]}.
{deps, [{eleveldb, "2.2.20"}]
}.
{shell, [
% {config, "config/sys.config"},
{apps, [myapp]}
]}.
I would try printing your current working directory when you are in the shell:
2> pwd().
/Users/7stud/erlang_programs/myrebar/myapp
ok
Then try using either a full path or a relative path from that directory, e.g.:
"./test/common"
"Users/../../test/common"
Then, I would move all your *_SUITE.erl files except one into a directory outside your app, and just work with one test file. Then, I would get rid of all that config file stuff and try again.
My test project is structured this way:
./Emakefile:
{"source/*", [debug_info, {outdir, "binary"}]}.
./source/test.erl:
-module(test).
-behaviour(test_behaviour).
./source/test_behaviour.erl:
-module(test_behaviour).
-export([behaviour_info/1]).
behaviour_info(callbacks) -> [];
behaviour_info(_) -> undefined.
When I use the command erl -make in the project directory (.), I get the following output:
Recompile: source/test_behaviour
Recompile: source/test
source/test.erl:2: Warning: behaviour test_behaviour undefined
Why does erl print this warning ? It compiled test_behaviour.erl before test.erl, so I guess it should be able to find test_behaviour.beam in the binary folder.
Behaviors are resolved at the compile time. Hence the Erlang compiler should find the behavior beam file and call the behavior module's behaviour_info/1 function.
Here test_behaviour.beam is not in the code path of the compiler. You can run by calling
erl -pa ebin -make
This solved the problem for me. I tried specifying in Emakefile but with no luck. Could not find the documentation also.
Also found that oder of -pa ebin has to be before -make (not sure why though).
I wanted to run the following eunit test command from console
eunit:test([test_module, [verbose]).
I tried this, but seems not working
erl -noshell -pa ./ebin -s eunit test test_module verbose -init stop
~/uid_server$erl -noshell -pa ./ebin -s eunit test test_module verbose -init stop
undefined
*** test module not found ***
::test_module
=======================================================
Failed: 0. Skipped: 0. Passed: 0.
One or more tests were cancelled.
Do you know how to pass not a simple arguments properly from console?
Your parameters look wrong. This should work:
erl -noshell -pa ebin -eval "eunit:test(test_module, [verbose])" -s init stop
-s can only run functions without arguments by specifying the module and function name (for example init and stop to execute init:stop()).
You can also pass one list to a function of arity 1 like this:
-s foo bar a b c
would call
foo:bar([a,b,c])
All the parameters are passed as a list of atoms only (even when you try to use some other characters, such as numbers, they are converted to atoms).
So since you want to pass two params and not only atoms if you want to run eunit:test/2 you'd have to use -eval which takes a string containing Erlang code as an argument. All -eval and -s functions are executed sequentially in the order they are defined.
Also, make sure you have your test code in ./ebin as well (otherwise write -pa ebin test_ebin where test_ebin is where your test code is).
You can also use rebar...
Get rebar by cd'ing to your project directory and typing the following:
curl http://cloud.github.com/downloads/basho/rebar/rebar -o rebar
chmod u+x rebar
Add the following to your module under test, right after last export:
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
Next, add your tests at the bottom of your module, wrapped in an ifdef like so:
-ifdef(TEST).
simple_test() ->
?assertNot(true).
-endif.
Lastly, run rebar from your shell like so:
./rebar compile eunit
you can try quote parameters instead of listing.
erl -noshell -pa ./ebin -s eunit test "test_module verbose" -init stop
More than eight years passed since the question, but there's still a nice solution not mentioned in the previous answers.
Once you are using EUnit, you can leverage from some of it's "automagic" features. One of them is an automatic export of the test/0 function, containing all the tests for the module.
So, if you are writing your tests alongside with the source code in the same module, all you have to do is:
$ erl -noshell -run your_module test -run init stop
If you are writing the tests in a separated, dependent module (as you should), you have to point to that module:
$ erl -noshell -run your_module_tests test -run init stop
All this will work fine, but the test won't be run in verbose mode as the OP required, but this is simple to solve with the EUNIT environment variable set to verbose.
Final version:
$ EUNIT=verbose erl -noshell -run your_module_tests test -run init stop
Have fun with Erlang and EUnit!
I use this script: https://github.com/lafka/dotconfig/blob/master/bin/eunit-module to run eunit on specific modules.
Example:
eunit-module <module> src ebin -I deps
That will do a couple of things:
Arg #2 is the directory where .erl resides
Arg #3 is the directory to output the compiled .beam
Arg #4++ is all the additional paths to add to your code path
Using -I specifies additional code paths AND where to look for files referenced with -include_lib
Erlang was already installed:
$dpkg -l|grep erlang
ii erlang 1:13.b.3-dfsg-2ubuntu2 Concurrent, real-time, distributed function
ii erlang-appmon 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application monitor
ii erlang-asn1 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP modules for ASN.1 support
ii erlang-base 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP virtual machine and base applica
ii erlang-common-test 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application for automated testin
ii erlang-debugger 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP application for debugging and te
ii erlang-dev 1:13.b.3-dfsg-2ubuntu2 Erlang/OTP development libraries and header
[... many more]
Erlang seems to work:
$ erl
Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.4 (abort with ^G)
1>
I downloaded lfe from github and checked out 0.5.2:
git clone http://github.com/rvirding/lfe.git
cd lfe
git checkout -b local0.5.2 e207eb2cad
$ configure
configure: command not found
$ make
mkdir -p ebin
erlc -I include -o ebin -W0 -Ddebug +debug_info src/*.erl
#erl -I -pa ebin -noshell -eval -noshell -run edoc file src/leex.erl -run init stop
#erl -I -pa ebin -noshell -eval -noshell -run edoc_run application "'Leex'" '"."' '[no_packages]'
#mv src/*.html doc/
Must be something stupid i missed :o
$ sudo make install
make: *** No rule to make target `install'. Stop.
$ erl -noshell -noinput -s lfe_boot start
{"init terminating in do_boot",{undef,[{lfe_boot,start,[]},{init,start_it,1},{init,start_em,1}]}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
Is there an example how I would create a hello world source file and compile and run it?
No, there is nothing you missed. The Makefile in LFE is "less than perfect" and should be ignored, it will be improved upon in the next release. To compensate all the needed files have already compiled and the .beam files are in the ebin directory. As it is not part of OTP I don't think it should ever install there.
The easiest way to handle this to create a private erlang library directory and point the environment variable ERL_LIBS to it. Then just drop the whole LFE directory there. When erlang starts the code server will automatically add the lfe/ebin directories into the path and the .beam files there will automagically be found and loaded. This will work with any package that contains an ebin directory. This also works on Windows. So:
Make an libs directory, say ~/erlang/lib
Set the environment variable ERL_LIBS, export ERL_LIBS=~/erlang/lib
Put the whole LFE directory there
When you start erlang you will then see /Users/rv/erlang/lib/lfe/ebin (or wherever you have it) in the code path (code:get_path()). You will then also be able to start the LFE shell directly with
erl -noshell -noinput -s lfe_boot start
There will be an lfe and an lfe.bat which does this included as well in the future.
As with erlang any text editor will work to edit LFE. For emacs there is an LFE mode which is still rather basic but works. You cannot yet run LFE in a window. Soon. The best way to include this is to put the following in your .emacs file:
;; LFE mode.
(setq load-path (cons "/Users/rv/erlang/lib/lfe/emacs" load-path))
(require 'lfe-start)
There are some example files in lfe/examples, all should work. In lfe/test/visual there is a bunch of my test files which have been included as example files. To compile an LFE file from the normal erlang shell do
lfe_comp:file("foo").
l(foo). %No autloload here, do this to ensure loading
while from the LFE shell do:
(c '"foo") ;This will autoload
There is a bunch of documentation in lfe/docs which is quite accurate but the user_guide.txt needs to be extended. There is also a Google group for LFE at
http://groups.google.se/group/lisp-flavoured-erlang
which contains some interesting discussions and people have written quite a lot in the github LFE wiki.
That's about it I think. contact me if/when you have more questions.