Module: Coverage
Relationships & Source Files | |
Defined in: | ext/coverage/coverage.c, ext/coverage/lib/coverage.rb |
Overview
Coverage
provides coverage measurement feature for Ruby. This feature is experimental, so these APIs may be changed in future.
Usage
-
require “coverage”
-
do .start
-
require or load Ruby source file
-
.result will return a hash that contains filename as key and coverage array as value. A coverage array gives, for each line, the number of line execution by the interpreter. A
nil
value means coverage is disabled for this line (lines likeelse
andend
).
Example
[foo.rb]
s = 0
10.times do |x|
s += x
end
if s == 45
p :ok
else
p :ng
end
[EOF]
require "coverage"
Coverage.start
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
Class Attribute Summary
- .running? ⇒ Boolean readonly mod_func
Class Method Summary
- .line_stub(file)
-
.peek_result ⇒ Hash
mod_func
Returns a hash that contains filename as key and coverage array as value.
-
.result(stop: true, clear: true) ⇒ Hash
mod_func
Returns a hash that contains filename as key and coverage array as value.
-
.start ⇒ nil
mod_func
Enables coverage measurement.
Class Attribute Details
.running? ⇒ Boolean
(readonly, mod_func)
# File 'ext/coverage/coverage.c', line 292
static VALUE rb_coverage_running(VALUE klass) { VALUE coverages = rb_get_coverages(); return RTEST(coverages) ? Qtrue : Qfalse; }
Class Method Details
.line_stub(file)
[ GitHub ]# File 'ext/coverage/lib/coverage.rb', line 4
def self.line_stub(file) lines = File.foreach(file).map { nil } iseqs = [RubyVM::InstructionSequence.compile_file(file)] until iseqs.empty? iseq = iseqs.pop iseq.trace_points.each {|n, type| lines[n - 1] = 0 if type == :line } iseq.each_child {|child| iseqs << child } end lines end
.peek_result ⇒ Hash
(mod_func)
Returns a hash that contains filename as key and coverage array as value. This is the same as Coverage.result(stop: false, clear: false)
.
{
"file.rb" => [1, 2, nil],
#...
}
# File 'ext/coverage/coverage.c', line 219
static VALUE rb_coverage_peek_result(VALUE klass) { VALUE coverages = rb_get_coverages(); VALUE ncoverages = rb_hash_new(); if (!RTEST(coverages)) { rb_raise(rb_eRuntimeError, "coverage measurement is not enabled"); } st_foreach(RHASH_TBL(coverages), coverage_peek_result_i, ncoverages); if (current_mode & COVERAGE_TARGET_METHODS) { rb_objspace_each_objects(method_coverage_i, &ncoverages); } rb_hash_freeze(ncoverages); return ncoverages; }
.result(stop: true, clear: true) ⇒ Hash
(mod_func)
Returns a hash that contains filename as key and coverage array as value. If clear
is true, it clears the counters to zero. If stop
is true, it disables coverage measurement.
# File 'ext/coverage/coverage.c', line 253
static VALUE rb_coverage_result(int argc, VALUE *argv, VALUE klass) { VALUE ncoverages; VALUE opt; int stop = 1, clear = 1; rb_scan_args(argc, argv, "01", &opt); if (argc == 1) { opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash"); stop = RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("stop")))); clear = RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("clear")))); } ncoverages = rb_coverage_peek_result(klass); if (stop && !clear) { rb_warn("stop implies clear"); clear = 1; } if (clear) { rb_clear_coverages(); if (!NIL_P(me2counter)) rb_hash_foreach(me2counter, clear_me2counter_i, Qnil); } if (stop) { rb_reset_coverages(); me2counter = Qnil; } return ncoverages; }
.start ⇒ nil
(mod_func)
Enables coverage measurement.
# File 'ext/coverage/coverage.c', line 24
static VALUE rb_coverage_start(int argc, VALUE *argv, VALUE klass) { VALUE coverages, opt; int mode; rb_scan_args(argc, argv, "01", &opt); if (argc == 0) { mode = 0; /* compatible mode */ } else if (opt == ID2SYM(rb_intern("all"))) { mode = COVERAGE_TARGET_LINES | COVERAGE_TARGET_BRANCHES | COVERAGE_TARGET_METHODS; } else { mode = 0; opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash"); if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("lines"))))) mode |= COVERAGE_TARGET_LINES; if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("branches"))))) mode |= COVERAGE_TARGET_BRANCHES; if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("methods"))))) mode |= COVERAGE_TARGET_METHODS; if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("oneshot_lines"))))) { if (mode & COVERAGE_TARGET_LINES) rb_raise(rb_eRuntimeError, "cannot enable lines and oneshot_lines simultaneously"); mode |= COVERAGE_TARGET_LINES; mode |= COVERAGE_TARGET_ONESHOT_LINES; } } if (mode & COVERAGE_TARGET_METHODS) { me2counter = rb_hash_new_compare_by_id(); } else { me2counter = Qnil; } coverages = rb_get_coverages(); if (!RTEST(coverages)) { coverages = rb_hash_new(); rb_obj_hide(coverages); current_mode = mode; if (mode == 0) mode = COVERAGE_TARGET_LINES; rb_set_coverages(coverages, mode, me2counter); } else if (current_mode != mode) { rb_raise(rb_eRuntimeError, "cannot change the measuring target during coverage measurement"); } return Qnil; }