Copyright © Quviq AB, 2014-2023
Version: 1.46.3
This module provides a tool for measuring code coverage for Erlang code.
The coverage tool works on code that has been compiled with theeqc_cover
parse transform.
17> c(test, [{parse_transform, eqc_cover}]). {ok,test}Or using an attribute in the module:
-compile({parse_transform, eqc_cover}).To start collecting coverage data
start/0
is called. After exercising the
covered code, stop/0
stops data collection and returns the collected data.
The common usage of collected data is to visualize it in HTML-format, using
write_html/2
:
2> eqc_cover:start(). true 3> test:a(7). X: 1 X: 2 X: 3 X: 4 X: 5 X: 6 X: 7 [ok,ok,ok,ok,ok,ok,ok] 4> test:b(5, 9). 4 5> Data = eqc_cover:stop(). ... 6> eqc_cover:write_html(Data, []). Coverage of /Users/hans/Quviq/tmp/test.erl: 67.2% ok
The resulting HTML-output can be seen here.
Alternatively a single computation can be measured usingapply/1
:
12> eqc_cover:apply(fun() -> test:a(0), test:b(2, 7) end). Coverage of /Users/hans/Quviq/tmp/test.erl: 51.6% 5
The resulting HTML-output can be seen here.
Usingstop/1
and merge_ticks/2
it is possible to tag and
combine separate runs and get the aggregated coverage data with a
break-down per tag. For example,
13> eqc_cover:start(). true 14> [ begin test:a(X), test:b(X, 2 * X) end || X <- lists:seq(1, 100) ], ok. ... 15> Run1 = eqc_cover:stop("Run 1"). ... 16> eqc_cover:start(). true 17> [ begin test:a(X), test:b(2 * X, X) end || X <- lists:seq(1, 10) ], ok. ... 18> Run2 = eqc_cover:stop("Run 2"). ... 19> eqc_cover:write_html(eqc_cover:merge_ticks(Run1, Run2), []). Coverage of /Users/ulfn/work/scratch/test.erl: 95.3% ok
The result can be seen here.
Special care is needed for modules using the -on_load
attribute (the
most common usage is for Erlang NIFs). Due to limitations in the Erlang VM
it is not possible to call the module currently being loaded using a
qualified function call--this hangs the Erlang VM. This means that
eqc_cover
cannot collect coverage data during module loading, and thus,
by default, the parse transform skips any modules using -on_load
.
-on_load
that one would like to
measure coverage for, it is possible to use the eqc_cover
attribute to
specificy precisely which functions should be cover compiled:
-eqc_cover({cover, [a/1, b/3, g/0]}).or to specify which functions should not be cover compiled:
-eqc_cover({skip, [d/2, f/1]}).
Note: the parse transform checks that the function in the -on_load
attribute is not among the covered functions (but it will not compute the
complete call graph for this function!).
html_opt() = {out_dir, string()} | {css_dir, string()} | {js_dir, string()}
Specify options for HTML generation. Where the HTML files should be written, and where the necessary css-files and js-files should be written.
html_opts() = [html_opt()]
abstract datatype: tick()
The abstract data type for a tick
, used to count how many times a
particular piece of code has been evaluated.
ticks() = [tick()]
A list of ticks.
apply/1 | Equivalent to apply(F, []). |
apply/2 | Measure coverage (and generate HTML output) for single computation. |
apply/3 | Equivalent to apply(M, F, A, []). |
apply/4 | Equivalent to apply(fun () -> erlang:apply(M, F, A) end, Options). |
compile/1 | Equivalent to compile(File, []). |
compile/2 |
Compile a module using the eqc_cover parse transform. |
merge_ticks/1 | Equivalent to lists:foldr(fun merge_ticks/2, [], Tickss). |
merge_ticks/2 | Merge two sets of collected coverage ticks. |
no_ticks/1 | Compute an empty set of ticks for a given (list of) module(s). |
start/0 | Start coverage data collection (will implicity stop any ongoing data collection!). |
stop/0 | Equivalent to stop(""). |
stop/1 | Stop coverage data collection. |
strip_tags/1 | Strip (replace with "") tags from a collection of ticks. |
write_html/2 | Prepare and write HTML output for collected coverage data. |
apply(F::function()) -> any()
Equivalent to apply(F, []).
apply(F::function(), Options::html_opts()) -> any()
Measure coverage (and generate HTML output) for single computation.
Starts coverage data collection. EvaluatesF
, stops data
collection, and generates HTML output.
apply(M::module(), F::atom(), A::[term()]) -> any()
Equivalent to apply(M, F, A, []).
apply(M::module(), F::atom(), A::[term()], Options::html_opts()) -> any()
Equivalent to apply(fun () -> erlang:apply(M, F, A) end, Options).
compile(File) -> any()
Equivalent to compile(File, []).
compile(Mod, Options) -> term()
Compile a module using the eqc_cover
parse transform.
More or less equivalent to:
compile:file(File, [binary, {parse_transform, eqc_cover}] ++ Options)
compile:file/2
for more information on possible Options
, and
code:load_binary/3
for possible return values.
Equivalent to lists:foldr(fun merge_ticks/2, [], Tickss).
Merge two sets of collected coverage ticks.
no_ticks(Mods::module() | [module()]) -> ticks()
Compute an empty set of ticks for a given (list of) module(s).
Returns coverage data where the measured number of ticks is 0 everywhere.start() -> true
Start coverage data collection (will implicity stop any ongoing data collection!).
stop() -> ticks()
Equivalent to stop("").
stop(Tag::string()) -> ticks()
Stop coverage data collection. Returns the collected coverage data tagged
with Tag
. When generating HTML for merged coverage data (merge_ticks/2
) containing multiple tags, a break-down of the number of
calls per tag will be shown.
Strip (replace with "") tags from a collection of ticks.
write_html(Ticks::ticks(), Options::html_opts()) -> ok | {error, atom()}
Prepare and write HTML output for collected coverage data.
If no options are given, HTML output is written to the current directory and the css-files and js-files are also copied to the current directory. Configuration options are:Generated by EDoc