如何在Erlang中进行单元测试覆盖

时间:2013-07-10 09:08:17

标签: testing erlang code-coverage eunit

使用Python时,我使用python-coverage等工具测试代码覆盖率,特别是django包djaango-nose,我正在寻找Erlang中的等价物。我已经使用eunit进行测试并使用surefire生成报告,但我没有找到代码覆盖的方法,是否有人知道这样做的工具或方法?

2 个答案:

答案 0 :(得分:10)

如果你是rebar,只需添加:

{cover_enabled, true}.

rebar.config

答案 1 :(得分:10)

我使用常用​​测试来控制测试套件,然后在测试规范中,您可以使用元组{cover,“coverspec path”}声明封面规范:

{include, ["../include"]}.
{suites,"../test", all}.
{logdir,"../results"}.
{cover,"../test/reduce.coverspec"}.

封面规范主要定义详细程度和要分析的模块列表:

{level, details}.
{incl_mods, [calc,calc_store]}.

然后当您运行测试时,您将获得一个增量网页,其中包含已完成的所有测试迭代,以及每个结果和一个指向覆盖总结的链接,然后您的源代码注释时间为评估了一条线。

incremental web page result summary coverage summary

和带注释的来源:

File generated from d:/documents and Settings/xxxxxxx/My Documents/git/calc/ebin/../src/calc_store.erl by COVER 2012-06-01 at 10:23:45

****************************************************************************

        |  -module(calc_store).
        |  
        |  -behaviour(gen_server).
        |  
        |  -record(state,{var,func}).
        |  -define(SERVER,?MODULE).
        |  
        |  %% gen_server call back
        |  -export([code_change/3,handle_call/3,handle_cast/2,handle_info/2,init/1,terminate/2]).
        |  
        |  %% api
        |  -export([start_link/0,storevar/2,storefunc/4,getvalue/1,getfunc/1,stop/0]).
        |  
        |  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        |  
        |  storevar(Name,Value) ->
     1..|      gen_server:cast(?MODULE,{storevar,Name,Value}).
        |  
        |  storefunc(Name,Par,Desc,Text) ->
     3..|      gen_server:cast(?MODULE,{storefunc,Name,Par,Desc,Text}).
        |  
        |  getvalue(Name) ->
    67..|      gen_server:call(?MODULE,{readvar,Name}).
        |  
        |  getfunc(Name) ->
    10..|      gen_server:call(?MODULE,{readfunc,Name}).
        |  
        |  stop() ->
     0..|   gen_server:cast(?MODULE,stop).
        |  
        |  start_link() -> 
     1..|      gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
        |  
        |  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        |  
        |  init([]) -> 
        |      %% register(?MODULE,self()),
     1..|      {ok,#state{var=dict:new(),func=dict:new()}}.
        |  
        |  handle_call({readvar,Name}, _From, State = #state{var=D}) -> 
    67..|      Reply = dict:find(Name,D), 
    67..|      {reply, Reply, State};
        |  handle_call({readfunc,Name}, _From, State = #state{func=F}) -> 
    10..|      Reply = dict:find(Name,F) , 
    10..|      {reply, Reply, State};
        |  handle_call(Request, From, State) -> 
     0..|      io:format("calc_store received call: ~p from ~p~n",[Request,From]),
     0..|      Reply = ok, 
     0..|      {reply, Reply, State}.
        |  
        |  handle_cast(stop,State) ->
     0..|   {stop,State};
        |  handle_cast({storevar,Name,Value}, State = #state{var=D}) -> 
     1..|      NewD= dict:store(Name,Value,D),
     1..|      {noreply, State#state{var=NewD}};
        |  handle_cast({storefunc,Name,Par,Desc,Text}, State = #state{func=F}) -> 
     3..|      NewF= dict:store(Name,{Par,Desc,Text},F),
     3..|      {noreply, State#state{func=NewF}};
        |  handle_cast(Msg, State) -> 
     0..|      io:format("calc_store received cast: ~p~n",[Msg]),
     0..|      {noreply, State}.
        |  
        |  handle_info({'EXIT',_P,shutdown},State) -> 
     0..|      {stop,State};
        |  handle_info(Msg,State) -> 
     0..|      io:format("calc_state received info: ~p~n",[Msg]),
     0..|      {noreply,State}.
        |  
        |  terminate(_Reason, _State) -> 
     0..|      ok.
        |  
        |  code_change(_OldVsn, State, _Extra) -> 
     0..|      {ok, State}.