Skip to content

Commit aeaacfb

Browse files
Update usage documentation.
1 parent dc1212e commit aeaacfb

3 files changed

Lines changed: 105 additions & 87 deletions

File tree

context/getting-started.md

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ Add the gem to your project:
1010
$ bundle add ruby-coverage
1111
~~~
1212

13-
If you are using `covered`, add that too:
14-
15-
~~~ bash
16-
$ bundle add covered
17-
~~~
18-
1913
## Motivation
2014

2115
Ruby's built-in `Coverage` module stores counters on the compiled instruction sequence (`ISeq`). That works well for ordinary files loaded once, but it breaks down when the same logical file is compiled more than once under the same path.
@@ -39,7 +33,7 @@ In both cases, the key design choice is that counters are associated with a file
3933

4034
## Basic Usage
4135

42-
If you want a drop-in API that behaves like the built-in coverage module, start here:
36+
If you want a familiar API that behaves like the built-in coverage module, start here:
4337

4438
~~~ ruby
4539
require "ruby/coverage"
@@ -55,8 +49,41 @@ pp result[path]
5549
# => {:lines=>[nil, 2]}
5650
~~~
5751

52+
`Ruby::Coverage.result` returns a hash keyed by path. Each value is a hash with a `:lines` array where executable lines contain hit counts, executable-but-unexecuted lines contain `0`, and non-executable lines contain `nil`.
53+
5854
This is the simplest way to get path-based accumulation across repeated evaluation of the same file.
5955

56+
Use `Ruby::Coverage.peek_result` to read counts without stopping coverage:
57+
58+
~~~ ruby
59+
Ruby::Coverage.start
60+
61+
path = "/tmp/example.rb"
62+
Module.new.module_eval("x = 1", path)
63+
64+
result = Ruby::Coverage.peek_result
65+
pp result[path]
66+
# => {:lines=>[nil, 1]}
67+
68+
Ruby::Coverage.result
69+
~~~
70+
71+
Use `Ruby::Coverage.result(stop: false, clear: true)` to clear accumulated counts while keeping coverage active:
72+
73+
~~~ ruby
74+
Ruby::Coverage.start
75+
76+
path = "/tmp/example.rb"
77+
Module.new.module_eval("x = 1", path)
78+
79+
Ruby::Coverage.result(stop: false, clear: true)
80+
81+
pp Ruby::Coverage.peek_result[path]
82+
# => nil
83+
84+
Ruby::Coverage.result
85+
~~~
86+
6087
## Using a Custom Tracer
6188

6289
If you need more control over how counters are allocated or cached, use `{Ruby::Coverage::Tracer}` directly.
@@ -68,8 +95,7 @@ This is useful when you need:
6895
- **Integration with other tooling**: Control exactly when and how coverage data is initialized.
6996

7097
~~~ ruby
71-
require_relative "config/environment"
72-
require_relative "lib/ruby/coverage"
98+
require "ruby/coverage"
7399

74100
files = {}
75101

@@ -108,15 +134,3 @@ The callback receives the file path and the active `RubyVM::InstructionSequence`
108134
- Do not expect stdlib `Coverage` semantics from this library. It intentionally changes the ownership model from `ISeq` to path.
109135
- If you evaluate code under different paths, you will get separate counters even if the source text is identical.
110136
- If you start coverage after code has already been defined, only code executed after startup will be tracked.
111-
112-
## Integration with `covered`
113-
114-
The `covered` gem can use `ruby-coverage` automatically when it is available.
115-
116-
~~~ ruby
117-
# gems.rb / Gemfile
118-
gem "ruby-coverage"
119-
gem "covered"
120-
~~~
121-
122-
This is a good fit when your test environment re-evaluates files and you want the final report to reflect cumulative path-based execution rather than per-compile counters.

guides/getting-started/readme.md

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ Add the gem to your project:
1010
$ bundle add ruby-coverage
1111
~~~
1212

13-
If you are using `covered`, add that too:
14-
15-
~~~ bash
16-
$ bundle add covered
17-
~~~
18-
1913
## Motivation
2014

2115
Ruby's built-in `Coverage` module stores counters on the compiled instruction sequence (`ISeq`). That works well for ordinary files loaded once, but it breaks down when the same logical file is compiled more than once under the same path.
@@ -39,7 +33,7 @@ In both cases, the key design choice is that counters are associated with a file
3933

4034
## Basic Usage
4135

42-
If you want a drop-in API that behaves like the built-in coverage module, start here:
36+
If you want a familiar API that behaves like the built-in coverage module, start here:
4337

4438
~~~ ruby
4539
require "ruby/coverage"
@@ -55,8 +49,41 @@ pp result[path]
5549
# => {:lines=>[nil, 2]}
5650
~~~
5751

52+
`Ruby::Coverage.result` returns a hash keyed by path. Each value is a hash with a `:lines` array where executable lines contain hit counts, executable-but-unexecuted lines contain `0`, and non-executable lines contain `nil`.
53+
5854
This is the simplest way to get path-based accumulation across repeated evaluation of the same file.
5955

56+
Use `Ruby::Coverage.peek_result` to read counts without stopping coverage:
57+
58+
~~~ ruby
59+
Ruby::Coverage.start
60+
61+
path = "/tmp/example.rb"
62+
Module.new.module_eval("x = 1", path)
63+
64+
result = Ruby::Coverage.peek_result
65+
pp result[path]
66+
# => {:lines=>[nil, 1]}
67+
68+
Ruby::Coverage.result
69+
~~~
70+
71+
Use `Ruby::Coverage.result(stop: false, clear: true)` to clear accumulated counts while keeping coverage active:
72+
73+
~~~ ruby
74+
Ruby::Coverage.start
75+
76+
path = "/tmp/example.rb"
77+
Module.new.module_eval("x = 1", path)
78+
79+
Ruby::Coverage.result(stop: false, clear: true)
80+
81+
pp Ruby::Coverage.peek_result[path]
82+
# => nil
83+
84+
Ruby::Coverage.result
85+
~~~
86+
6087
## Using a Custom Tracer
6188

6289
If you need more control over how counters are allocated or cached, use `{Ruby::Coverage::Tracer}` directly.
@@ -68,8 +95,7 @@ This is useful when you need:
6895
- **Integration with other tooling**: Control exactly when and how coverage data is initialized.
6996

7097
~~~ ruby
71-
require_relative "config/environment"
72-
require_relative "lib/ruby/coverage"
98+
require "ruby/coverage"
7399

74100
files = {}
75101

@@ -108,15 +134,3 @@ The callback receives the file path and the active `RubyVM::InstructionSequence`
108134
- Do not expect stdlib `Coverage` semantics from this library. It intentionally changes the ownership model from `ISeq` to path.
109135
- If you evaluate code under different paths, you will get separate counters even if the source text is identical.
110136
- If you start coverage after code has already been defined, only code executed after startup will be tracked.
111-
112-
## Integration with `covered`
113-
114-
The `covered` gem can use `ruby-coverage` automatically when it is available.
115-
116-
~~~ ruby
117-
# gems.rb / Gemfile
118-
gem "ruby-coverage"
119-
gem "covered"
120-
~~~
121-
122-
This is a good fit when your test environment re-evaluates files and you want the final report to reflect cumulative path-based execution rather than per-compile counters.

readme.md

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,58 +8,14 @@ A native reimplementation of Ruby's built-in `Coverage` module, backed by `rb_ad
88

99
Ruby's built-in `Coverage` module ties its counter store to the ISeq. When a file is re-evaluated under the same path — for example when a test framework loads a file into a fresh anonymous module via `module_eval` — Ruby allocates a fresh counter array and discards the previous one. Any coverage accumulated before the re-eval is lost.
1010

11-
`Ruby::Coverage` owns its own counter store. Re-evaluating a file under the same path simply continues incrementing the same counters. The `covered` gem can optionally use `Ruby::Coverage` in place of `::Coverage` to get correct results in test suites that load files multiple times.
11+
`Ruby::Coverage` owns its own counter store. Re-evaluating a file under the same path simply continues incrementing the same counters, which gives path-oriented reporting tools stable results when test suites load files multiple times.
1212

1313
## Usage
1414

1515
Please see the [project documentation](https://socketry.github.io/ruby-coverage/) for more details.
1616

1717
- [Getting Started](https://socketry.github.io/ruby-coverage/guides/getting-started/index) - This guide explains how to use `ruby-coverage` to collect coverage for code that may be evaluated multiple times under the same path.
1818

19-
### Drop-in module API
20-
21-
``` ruby
22-
require "ruby/coverage"
23-
24-
Ruby::Coverage.start
25-
26-
# ... run code ...
27-
28-
result = Ruby::Coverage.result
29-
# => { "/path/to/file.rb" => { lines: [nil, 3, 1, nil, 0, ...] }, ... }
30-
```
31-
32-
### Low-level `Tracer`
33-
34-
`Ruby::Coverage::Tracer` is the primitive that the module API is built on. It accepts a block that is called once each time execution enters a new file. The block receives the absolute path and must return a Ruby `Array` to use as the line-count store for that file, or `nil` to skip tracking it.
35-
36-
The block controls the caching strategy: returning the same `Array` for the same path accumulates counts across re-evals; returning a fresh `Array` each time gives per-ISeq isolation.
37-
38-
``` ruby
39-
files = {}
40-
41-
tracer = Ruby::Coverage::Tracer.new do |path|
42-
# Accumulate across re-evals of the same path:
43-
files[path] ||= []
44-
end
45-
46-
tracer.start
47-
# ... run tests ...
48-
tracer.stop
49-
50-
# files is now populated with line-count arrays keyed by path.
51-
```
52-
53-
## Integration with `covered`
54-
55-
`covered` multiplexes between `Ruby::Coverage` and `::Coverage` internally. Add `ruby-coverage` to your `Gemfile` and `covered` will prefer it automatically.
56-
57-
``` ruby
58-
# gems.rb / Gemfile
59-
gem "ruby-coverage"
60-
gem "covered"
61-
```
62-
6319
## Releases
6420

6521
Please see the [project releases](https://socketry.github.io/ruby-coverage/releases/index) for all releases.
@@ -84,3 +40,37 @@ Please see the [project releases](https://socketry.github.io/ruby-coverage/relea
8440
## See Also
8541

8642
- [covered](https://github.com/socketry/covered) — the coverage reporting gem that uses this library.
43+
44+
## Contributing
45+
46+
We welcome contributions to this project.
47+
48+
1. Fork it.
49+
2. Create your feature branch (`git checkout -b my-new-feature`).
50+
3. Commit your changes (`git commit -am 'Add some feature'`).
51+
4. Push to the branch (`git push origin my-new-feature`).
52+
5. Create new Pull Request.
53+
54+
### Running Tests
55+
56+
To run the test suite:
57+
58+
``` shell
59+
bundle exec sus
60+
```
61+
62+
### Making Releases
63+
64+
To make a new release:
65+
66+
``` shell
67+
bundle exec bake gem:release:patch # or minor or major
68+
```
69+
70+
### Developer Certificate of Origin
71+
72+
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
73+
74+
### Community Guidelines
75+
76+
This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.

0 commit comments

Comments
 (0)