ruby/ruby — pull request #511 by srawlins (2014-01-22 01:13:53+00:00)
Title: Add method coverage and branch coverage metrics

This is a working proof-of-concept for tracking more advanced code coverage metrics in the Coverage module. Namely, method coverage branch coverage. I'd love feedback!

Currently the format of a Coverage report looks like:

```ruby
{"foo.rb" => [1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
```

(from the [rdoc](http://ruby-doc.org/stdlib-2.1.0/libdoc/coverage/rdoc/Coverage.html)) which says that, within "foo.rb":

* lines 1 and 2 were executed once,
* line 3 was executed 10 times,
* lines 4 and 5 were "disabled" as far as Coverage is concerned,
* etc.

This pull request changes the format to be more complicated. For the following ruby file:

```ruby
def sum
s = 0
10.times do |x|
s += x
end

if s == 45
p :okay
p :ok
else
p :ng
end
end

def never_executed
"badwrong"
end

def hello(name)
puts "Hello #{name}"
end

sum; sum; hello("Sam")
```

Coverage.result would yield the following:

```ruby
{"/Users/sam/code/ruby/cov_method.rb" => {
lines: [1, 2, 2, 20, nil, nil, 2, 2, 2, nil, 0, nil, nil, nil, 1, 0, nil, nil, 1, 1, nil, nil, 1],
methods: {1=>2, 15=>0, 19=>1},
branches: {8=>2, 11=>0}
}}
```

So the following things change about the coverage report:

1. The coverage report for a given file is a _Hash_, changed from an _Array_.
2. The execution count for each _line_ is in `Coverage.result[file][:lines]`, changed from `Coverage.result[file]`.
3. The coverage report includes execution counts for each _method_ in `Coverage.result[file][:methods]`. This object is a hash, with line number keys (where each method was defined), and execution count values ("calls"). This could be changed to be the same format as `[:lines]`, but a Hash presumably saves space and time.
4. The coverage report includes execution counts for each _"branch"_ in `Coverage.result[file][:branches]`. This object is a Hash, with line number keys (the first line of the body of a branch), and execution count values. This can also be changed to be the same format as `[:lines]` if that is desirable.

### Branches

I'm defining branches as all bodies of conditional code. This should include the bodies of `if`, `elsif`, `else`, `unless`, `while`, `until`, and `when` statements. Right now, this proof-of-concept will only trace the bodies of `if`, `elsif`, and `else` (paired with an `if` or `unless`). I'd love feedback before moving on to `while`, `until`, and `when`.