yesterday i found about code coverage under erlang on this nice blog. i wanted to integrate it with my unit testing, so i would be able to see what code of mine is not tested. this can be used to add new tests to cover it, or even remove of unnecessary code.

it took me some time to play with it and come up with a good method of doing that. eventually i have replaced the unit testing makefile line with:

check:
	@for f in $(MODULES); do \
	echo $$f; \
	erl $(FLAGS) -noshell -eval "
	cover:compile($$f, [{i,\"$(INCLUDE)\"}]),\
	$$f:test(),
	cover:analyse_to_file($$f, \"$(DOC)/$${f}_coverage.html\", [html])."\
	-s init stop; \

This actually do 3 things in a raw:

  1. compile each module using cover:compile.
  2. run the test, using the eunit test() function.
  3. dump analysis into html files on doc directory

enjoy!

edit: i found out, that you compile the whole directory for covearge, so the result you get is thecombined  coverage for all the specified modules and tests.

OBJECTS := $(patsubst %.erl,$(BIN)/%.$(EMULATOR),$(wildcard *.erl))
MODULES := $(patsubst %.erl,%,$(wildcard *.erl))
SKIP_FILES := $(patsubst %.erl,%,$(wildcard *_tests.erl))
MODULES := $(filter-out $(SKIP_FILES), $(MODULES))
MODULES := [$(subst $(space),$(comma),$(MODULES))]
 
check:
	@echo Testing units...
	@$(TIME) erl $(ERL_LIB_FLAGS) \
	-mnesia dir '"$(DATA_DIR)"' -mnesia debug $(MNESIA) -noshell \
	-eval "\
	cover:compile_directory(\".\", [{i,\"$(INCLUDE)\"},{d,'NODEBUG'}]), \
	T = fun(X) -> io:format(user, \"~-20.s\", [X]), X:test() end, \
	[T(X) || X <- "$(MODULES)"], \
	F = fun(X) -> cover:analyse_to_file(X, \"$(LOG)/\" ++ \
	    atom_to_list(X) ++ \"_coverage.html\", [html]) end, \
	[F(X) || X <- "$(MODULES)"]. \
	" -s init stop;