diff options
author | Loïc Hoguin <[email protected]> | 2015-05-09 16:32:32 +0300 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2015-05-09 16:32:49 +0300 |
commit | 7d28bd8d9eb449c360eb9582e282bd4756f76be9 (patch) | |
tree | 97791a7cc0319328bf33db2c46abeaa9e831354a /plugins | |
parent | afff9a6d94964f7733badd7e1a9fb404ab8b09a8 (diff) | |
parent | 8f39bed18723b0b60b17ea1aeecde4c6c371e3f0 (diff) | |
download | erlang.mk-7d28bd8d9eb449c360eb9582e282bd4756f76be9.tar.gz erlang.mk-7d28bd8d9eb449c360eb9582e282bd4756f76be9.tar.bz2 erlang.mk-7d28bd8d9eb449c360eb9582e282bd4756f76be9.zip |
Merge branch 'cover' of https://github.com/zuiderkwast/erlang.mk
Rebased and moved ct.cover.spec into the test/ directory.
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/cover.mk | 136 | ||||
-rw-r--r-- | plugins/eunit.mk | 21 |
2 files changed, 148 insertions, 9 deletions
diff --git a/plugins/cover.mk b/plugins/cover.mk new file mode 100644 index 0000000..3397dca --- /dev/null +++ b/plugins/cover.mk @@ -0,0 +1,136 @@ +# Copyright 2015, Viktor Söderqvist <[email protected]> +# This file is part of erlang.mk and subject to the terms of the ISC License. + +COVER_REPORT_DIR = cover + +# utility variables for representing special symbols +empty := +space := $(empty) $(empty) +comma := , + +# Hook in coverage to eunit + +ifdef COVER +ifdef EUNIT_RUN +EUNIT_RUN_BEFORE += -eval \ + 'case cover:compile_beam_directory("ebin") of \ + {error, _} -> halt(1); \ + _ -> ok \ + end.' +EUNIT_RUN_AFTER += -eval 'cover:export("eunit.coverdata").' +endif +endif + +# Hook in coverage to ct + +ifdef COVER +ifdef CT_RUN + +# All modules in 'ebin' +COVER_MODS = $(notdir $(basename $(shell echo ebin/*.beam))) + +test-build:: $(TEST_DIR)/ct.cover.spec + +$(TEST_DIR)/ct.cover.spec: + @echo Cover mods: $(COVER_MODS) + $(gen_verbose) printf "%s\n" \ + '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ + '{export,"$(CURDIR)/ct.coverdata"}.' > $@ + +CT_RUN += -cover $(TEST_DIR)/ct.cover.spec +endif +endif + +# Core targets + +ifdef COVER +ifneq ($(COVER_REPORT_DIR),) +tests:: + @$(MAKE) make --no-print-directory cover-report +endif +endif + +clean:: coverdata-clean + +ifneq ($(COVER_REPORT_DIR),) +distclean:: cover-report-clean +endif + +help:: + @printf "%s\n" "" \ + "Cover targets:" \ + " cover-report Generate a HTML coverage report from previously collected" \ + " cover data." \ + " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \ + "" \ + "If COVER=1 is set, coverage data is generated by the targets eunit and ct. The" \ + "target tests additionally generates a HTML coverage report from the combined" \ + "coverdata files from each of these testing tools. HTML reports can be disabled" \ + "by setting COVER_REPORT_DIR to empty." + +# Plugin specific targets + +COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) + +.PHONY: coverdata-clean +coverdata-clean: + $(gen_verbose) rm -f *.coverdata ct.cover.spec + +# Merge all coverdata files into one. +all.coverdata: $(COVERDATA) + $(gen_verbose) $(ERL) -eval ' \ + $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ + cover:export("$@"), halt(0).' + +# These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to +# empty if you want the coverdata files but not the HTML report. +ifneq ($(COVER_REPORT_DIR),) + +.PHONY: cover-report-clean cover-report + +cover-report-clean: + $(gen_verbose) rm -rf $(COVER_REPORT_DIR) + +ifeq ($(COVERDATA),) +cover-report: +else + +# Modules which include eunit.hrl always contain one line without coverage +# because eunit defines test/0 which is never called. We compensate for this. +EUNIT_HRL_MODS = $(subst $(space),$(comma),$(shell \ + grep -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ + | sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq)) + +cover-report: + $(gen_verbose) mkdir -p $(COVER_REPORT_DIR) + $(gen_verbose) $(ERL) -eval ' \ + $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ + Ms = cover:imported_modules(), \ + [cover:analyse_to_file(M, "$(COVER_REPORT_DIR)/" ++ atom_to_list(M) \ + ++ ".COVER.html", [html]) || M <- Ms], \ + Report = [begin {ok, R} = cover:analyse(M, module), R end || M <- Ms], \ + EunitHrlMods = [$(EUNIT_HRL_MODS)], \ + Report1 = [{M, {Y, case lists:member(M, EunitHrlMods) of \ + true -> N - 1; false -> N end}} || {M, {Y, N}} <- Report], \ + TotalY = lists:sum([Y || {_, {Y, _}} <- Report1]), \ + TotalN = lists:sum([N || {_, {_, N}} <- Report1]), \ + TotalPerc = round(100 * TotalY / (TotalY + TotalN)), \ + {ok, F} = file:open("$(COVER_REPORT_DIR)/index.html", [write]), \ + io:format(F, "<!DOCTYPE html><html>~n" \ + "<head><meta charset=\"UTF-8\">~n" \ + "<title>Coverage report</title></head>~n" \ + "<body>~n", []), \ + io:format(F, "<h1>Coverage</h1>~n<p>Total: ~p%</p>~n", [TotalPerc]),\ + io:format(F, "<table><tr><th>Module</th><th>Coverage</th></tr>~n", []), \ + [io:format(F, "<tr><td><a href=\"~p.COVER.html\">~p</a></td>" \ + "<td>~p%</td></tr>~n", \ + [M, M, round(100 * Y / (Y + N))]) || {M, {Y, N}} <- Report1], \ + How = "$(subst $(space),$(comma)$(space),$(basename $(COVERDATA)))", \ + Date = "$(shell date -u "+%Y-%m-%dT%H:%M:%SZ")", \ + io:format(F, "</table>~n" \ + "<p>Generated using ~s and erlang.mk on ~s.</p>~n" \ + "</body></html>", [How, Date]), \ + halt().' + +endif +endif # ifneq ($(COVER_REPORT_DIR),) diff --git a/plugins/eunit.mk b/plugins/eunit.mk index ec3228e..b9f2856 100644 --- a/plugins/eunit.mk +++ b/plugins/eunit.mk @@ -6,22 +6,19 @@ # Configuration +# All modules in TEST_DIR ifeq ($(strip $(TEST_DIR)),) -TAGGED_EUNIT_TESTS = {dir,"ebin"} -else -ifeq ($(wildcard $(TEST_DIR)),) -TAGGED_EUNIT_TESTS = {dir,"ebin"} +TEST_DIR_MODS = else -# All modules in TEST_DIR TEST_DIR_MODS = $(notdir $(basename $(shell find $(TEST_DIR) -type f -name *.beam))) +endif + # All modules in 'ebin' EUNIT_EBIN_MODS = $(notdir $(basename $(shell find ebin -type f -name *.beam))) # Only those modules in TEST_DIR with no matching module in 'ebin'. # This is done to avoid some tests being executed twice. EUNIT_MODS = $(filter-out $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(TEST_DIR_MODS)) -TAGGED_EUNIT_TESTS = {dir,"ebin"} $(foreach mod,$(EUNIT_MODS),$(shell echo $(mod) | sed -e 's/\(.*\)/{module,\1}/g')) -endif -endif +TAGGED_EUNIT_TESTS = $(foreach mod,$(EUNIT_EBIN_MODS) $(EUNIT_MODS),{module,$(mod)}) EUNIT_OPTS ?= @@ -42,10 +39,16 @@ help:: # Plugin-specific targets. +EUNIT_RUN_BEFORE ?= +EUNIT_RUN_AFTER ?= EUNIT_RUN = $(ERL) \ -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin \ -pz ebin \ - -eval 'case eunit:test([$(call str-join,$(TAGGED_EUNIT_TESTS))], [$(EUNIT_OPTS)]) of ok -> halt(0); error -> halt(1) end.' + $(EUNIT_RUN_BEFORE) \ + -eval 'case eunit:test([$(call str-join,$(TAGGED_EUNIT_TESTS))],\ + [$(EUNIT_OPTS)]) of ok -> ok; error -> halt(1) end.' \ + $(EUNIT_RUN_AFTER) \ + -eval 'halt(0).' eunit: test-build $(gen_verbose) $(EUNIT_RUN) |