erlang的单元测试相信很多人都用过,体验不好,但是elixir出现后,似乎这个体验有机会赶超rspec,那就哈哈哈了。
初学elixir/mix,苦于没有用武之地,其实可以从测试用例开始,毕竟erlang和elixir编译出来的代码是可以完整互相调用的,那么混合在一起也什么困难的。
新建一个rebar工程
在erlang中我是这样尝试写用例的。
rebar create-app appid=rebar_mix_test ==> rebar_mix_test (create-app) Writing src/rebar_mix_test.app.src Writing src/rebar_mix_test_app.erl Writing src/rebar_mix_test_sup.erl |
现在这个简单的otp应用下面挂一个工作者进程,这个进程有一点简单的api函数。
mix_worker.erl 简单易懂,实现了add和double函数。
-module(mix_worker). -behaviour(gen_server). %% API -export([start_link/0]). -export([add/2]). -export([double/1]). -record(state, {}). -define(SERVER, MODULE). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). start_link() -> gen_server:start_link({local, SERVER}, MODULE, [], []). add(A, B) -> gen_server:call(MODULE, {add, A, B}). double(A) -> gen_server:call(MODULE, {double, A}). init([]) -> {ok, #state{}}. handle_call({add, X, Y}, _From, State) -> {reply, X+Y, State}; handle_call({double, X}, _From, State) -> {reply, X*2, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. |
接下来挂到监督者下面
init([]) ->
{ok, { {one_for_one, 5, 10}, [CHILD(mix_worker, worker)]} }.
编译测试:
rebar compile ==> rebar_mix_test (compile) Compiled src/rebar_mix_test_sup.erl Compiled src/mix_worker.erl erl -pa deps/*/ebin ebin/ zsh: no matches found: deps/*/ebin erl -pa ebin/ Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] Eshell V7.3 (abort with ^G) 1> application:start(rebar_mix_test). ok 2> observer:start(). ok 3> mix_worker:add(3,3). 6 4> mix_worker:double(232). 464 5> |
这个mix_worker如果想在eunit里面写单元测试用例是比较难的,我尝试写一个:
test/mix_worker_tests.erl
-module(mix_worker_tests).
-compile([export_all]).
-include_lib("eunit/include/eunit.hrl").
add_test() ->
3 = mix_worker:add(1,2),
ok.
执行测试:
rebar eunit ==> rebar_mix_test (eunit) Compiled test/mix_worker_tests.erl mix_worker_tests: add_test (module 'mix_worker_tests')...*failed* in function gen_server:call/2 (gen_server.erl, line 204) in call from mix_worker_tests:add_test/0 (test/mix_worker_tests.erl, line 7) **exit:{noproc,{gen_server,call,[mix_worker,{add,1,2}]}} output:<<"">> ======================================================= Failed: 1. Skipped: 0. Passed: 0. ERROR: One or more eunit tests failed. ERROR: eunit failed while processing /Users/zhuoyikang/source/services/rebar_mix_test: rebar_abort |
抓瞎了,mix_worker没有启动,那么怎么测呢?
尝试在测试用例中启动rebar_mix_test:
add_test() ->
ok = application:start(rebar_mix_test),
3 = mix_worker:add(1,2),
ok = application:stop(rebar_mix_test),
ok.