The module cover provides a set of functions for coverage
analysis of Erlang programs, counting how many times each
executable line of code is executed when a program is run.
An executable line contains an Erlang expression such as a matching
or a function call. A blank line or a line containing a comment,
function head or pattern in a case- or receive statement
is not executable.
Coverage analysis can be used to verify test cases, making sure all relevant code is covered, and may also be helpful when looking for bottlenecks in the code.
Before any analysis can take place, the involved modules must be
Cover compiled. This means that some extra information is
added to the module before it is compiled into a binary which then
is loaded. The source file of the module is not affected and no
.beam file is created.
Each time a function in a Cover compiled module is called,
information about the call is added to an internal database of Cover.
The coverage analysis is performed by examining the contents of
the Cover database. The output Answer is determined by two
parameters, Level and Analysis.
Level = moduleAnswer = {Module,Value}, where Module is the module
name.Level = functionAnswer = [{Function,Value}], one tuple for each function in
the module. A function is specified by its module name M,
function name F and arity A as a tuple
{M,F,A}.Level = clauseAnswer = [{Clause,Value}], one tuple for each clause in
the module. A clause is specified by its module name M,
function name F, arity A and position in the function
definition C as a tuple {M,F,A,C}.Level = lineAnswer = [{Line,Value}], one tuple for each executable
line in the module. A line is specified by its module name M
and line number in the source file N as a tuple
{M,N}.Analysis = coverageValue = {Cov,NotCov} where Cov is the number of
executable lines in the module, function, clause or line that have
been executed at least once and NotCov is the number of
executable lines that have not been executed.Analysis = callsValue = Calls which is the number of times the module,
function, or clause has been called. In the case of line level
analysis, Calls is the number of times the line has been
executed.Distribution
Cover can be used in a distributed Erlang system. One of the nodes in the system must then be selected as the main node, and all Cover commands must be executed from this node.
Use cover:start/1 and cover:stop/1 to add or
remove nodes. The same Cover compiled code will be loaded on each
node, and analysis will collect and sum up coverage data results
from all nodes.
start() -> {ok,Pid} | {error,Reason}
Types:
Pid = pid()
Reason = {already_started,Pid}
Starts the Cover server which owns the Cover internal database. This function is called automatically by the other functions in the module.
start(Nodes) -> {ok,StartedNodes}
Types:
Nodes = StartedNodes = [atom()]
Starts a Cover server on the each of given nodes, and loads all cover compiled modules.
compile(ModFile) -> Result
compile(ModFile, Options) -> Result
compile_module(ModFile) -> Result
compile_module(ModFile, Options) -> Result
Types:
ModFile = Module | File
Module = atom()
File = string()
Options = [Option]
Option = {i,Dir} | {d,Macro} | {d,Macro,Value}
compile:file/2.
Result = {ok,Module} | {error,File}Compiles a module for Cover analysis. The module is given by its
module name Module or by its file name File.
The .erl extension may be omitted. If the module is
located in another directory, the path has to be specified.
Options is a list of compiler options which defaults to
[]. Only options defining include file directories and
macros are passed to compile:file/2, everything else is
ignored.
If the module is successfully Cover compiled, the function
returns {ok,Module}. Otherwise the function returns
{error,File}. Errors and warnings are printed as they
occur.
Note that the internal database is (re-)initiated during the compilation, meaning any previously collected coverage data for the module will be lost.
compile_directory() -> [Result] | {error,Reason}
compile_directory(Dir) -> [Result] | {error,Reason}
compile_directory(Dir, Options) -> [Result] | {error,Reason}
Types:
Dir = string()
Options = [Option]
compile_module/1,2
Result = {ok,Module} | {error,File}compile_module/1,2
Reason = eacces | enoentCompiles all modules (.erl files) in a directory
Dir for Cover analysis the same way as
compile_module/1,2 and returns a list with the return
values.
Dir defaults to the current working directory.
The function returns {error,eacces} if the directory is not
readable or {error,enoent} if the directory does not exist.
compile_beam(ModFile) -> Result
Types:
ModFile = Module | BeamFile
Module = atom()
BeamFile = string()
Result = {ok,Module} | {error,BeamFile} | {error,Reason}
Reason = non_existing | {no_abstract_code,BeamFile} |
{already_cover_compiled,no_beam_found,Module}
Does the same as compile/1,2, but uses an existing
.beam file as base, i.e. the module is not compiled
from source. Thus compile_beam/1 is faster than
compile/1,2.
Note that he existing .beam file must contain
abstract code, i.e. it must have been compiled with
the debug_info option. If not, the error reason
no_abstract_code is returned.
If only the module name (i.e. not the full name of the
.beam file) is given to this function, the
.beam file is found by calling
code:which(Module). If no .beam file is found,
the error reason non_existing is returned. If the
module is already cover compiled with compile_beam/1,
the .beam file will be picked from the same location
as the first time it was compiled. If the module is already
cover compiled with compile/1,2, there is no way to
find the correct .beam file, so the error reason
{already_cover_compiled,no_beam_found,Module} is
returned.
{error,Beamfile} is returned if the compiled code
can not be loaded on the node.
compile_beam_directory() -> [Result] | {error,Reason}
compile_beam_directory(Dir) -> [Result] | {error,Reason}
Types:
Dir = string()
Result = See compile_beam/1
Reason = eacces | enoent
Compiles all modules (.beam files) in a directory
Dir for Cover analysis the same way as
compile_beam/1 and returns a list with the return
values.
Dir defaults to the current working directory.
The function returns {error,eacces} if the directory is not
readable or {error,enoent} if the directory does not exist.
analyse(Module) -> {ok,Answer} | {error,Error}
analyse(Module, Analysis) -> {ok,Answer} | {error,Error}
analyse(Module, Level) -> {ok,Answer} | {error,Error}
analyse(Module, Analysis, Level) -> {ok,Answer} | {error,Error}
Types:
Module = atom()
Analysis = coverage | calls
Level = line | clause | function | module
Answer = {Module,Value} | [{Item,Value}]
Item = Line | Clause | Function
Line = {M,N}
Clause = {M,F,A,C}
Function = {M,F,A}
M = F = atom()
N = A = C = integer()
Value = {Cov,NotCov} | Calls
Cov = NotCov = Calls = integer()
Error = {not_cover_compiled,Module}
Performs analysis of a Cover compiled module Module, as
specified by Analysis and Level (see above), by
examining the contents of the internal database.
Analysis defaults to coverage and Level
defaults to function.
If Module is not Cover compiled, the function returns
{error,{not_cover_compiled,Module}}.
analyse_to_file(Module) ->
analyse_to_file(Module,Options) ->
analyse_to_file(Module, OutFile) ->
analyse_to_file(Module, OutFile, Options) ->
{ok,OutFile} | {error,Error}
Types:
Module = atom()
OutFile = string()
Options = [Option]
Option = html
Error = {not_cover_compiled,Module} | {file,File,Reason} |
no_source_code_found
File = string()
Reason = term()
Makes a copy OutFile of the source file for a module
Module, where it for each executable line is specified
how many times it has been executed.
The output file OutFile defaults to
Module.COVER.out, or Module.COVER.html if the
option html was used.
If Module is not Cover compiled, the function returns
{error,{not_cover_compiled,Module}}.
If the source file and/or the output file cannot be opened using
file:open/2, the function returns
{error,{file,File,Reason}} where File is the file
name and Reason is the error reason.
If the module was cover compiled from the .beam
file, i.e. using compile_beam/1 or
compile_beam_directory/0,1, it is assumed that the
source code can be found in the same directory as the
.beam file, or in ../src relative to that
directory. If no source code is found,
,{error,no_source_code_found} is returned.
Types:
Module = atom()
Returns a list with all modules that are currently Cover compiled.
imported_modules() -> [Module]
Types:
Module = atom()
Returns a list with all modules for which there are imported data.
Types:
File = string()
Returns a list with all imported files.
Types:
Node = atom()
Returns a list with all nodes that are part of the coverage analysis. Note that the current node is not returned. This node is always part of the analysis.
is_compiled(Module) -> {file,File} | false
Types:
Module = atom()
Beam = string()
Returns {file,File} if the module Module is
Cover compiled, or false otherwise. File is
the .erl file used by cover:compile_module/1,2
or the .beam file used by compile_beam/1.
reset(Module) -> ok
reset() -> ok
Types:
Module = atom()
Resets all coverage data for a Cover compiled module
Module in the Cover database on all nodes. If the
argument is omitted, the coverage data will be reset for all
modules known by Cover.
If Module is not Cover compiled, the function returns
{error,{not_cover_compiled,Module}}.
export(ExportFile)
export(ExportFile,Module) -> ok | {error,Reason}
Types:
ExportFile = string()
Module = atom()
Reason = {not_cover_compiled,Module} |
{cant_open_file,ExportFile,Reason}
Exports the current coverage data for Module to the
file ExportFile. It is recommended to name the
ExportFile with the extension .coverdata, since
other filenames can not be read by the web based interface to
cover.
If Module is not given, data for all Cover compiled
or earlier imported modules is exported.
This function is useful if coverage data from different systems is to be merged.
See also cover:import/1
import(ExportFile) -> ok | {error,Reason}
Types:
ExportFile = string()
Reason = {cant_open_file,ExportFile,Reason}
Imports coverage data from the file ExportFile
created with cover:export/1,2. Any analysis performed
after this will include the imported data.
Note that when compiling a module all existing coverage data is removed, including imported data. If a module is already compiled when data is imported, the imported data is added to the existing coverage data.
Coverage data from several export files can be imported into one system. The coverage data is then added up when analysing.
Coverage data for a module can not be imported from the same file twice unless the module is first reset or compiled. The check is based on the filename, so you can easily fool the system by renaming your export file.
See also cover:export/1,2
Stops the Cover server and unloads all Cover compiled code.
Types:
Nodes = [atom()]
Stops the Cover server and unloads all Cover compiled code on the given nodes. Data stored in the Cover database on the remote nodes is fetched and stored on the main node.
code(3), compile(3)