You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: context/getting-started.md
+35-21Lines changed: 35 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,12 +10,6 @@ Add the gem to your project:
10
10
$ bundle add ruby-coverage
11
11
~~~
12
12
13
-
If you are using `covered`, add that too:
14
-
15
-
~~~bash
16
-
$ bundle add covered
17
-
~~~
18
-
19
13
## Motivation
20
14
21
15
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
39
33
40
34
## Basic Usage
41
35
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:
43
37
44
38
~~~ruby
45
39
require"ruby/coverage"
@@ -55,8 +49,41 @@ pp result[path]
55
49
# => {:lines=>[nil, 2]}
56
50
~~~
57
51
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
+
58
54
This is the simplest way to get path-based accumulation across repeated evaluation of the same file.
59
55
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
+
60
87
## Using a Custom Tracer
61
88
62
89
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:
68
95
-**Integration with other tooling**: Control exactly when and how coverage data is initialized.
69
96
70
97
~~~ruby
71
-
require_relative"config/environment"
72
-
require_relative"lib/ruby/coverage"
98
+
require"ruby/coverage"
73
99
74
100
files = {}
75
101
@@ -108,15 +134,3 @@ The callback receives the file path and the active `RubyVM::InstructionSequence`
108
134
- Do not expect stdlib `Coverage` semantics from this library. It intentionally changes the ownership model from `ISeq` to path.
109
135
- If you evaluate code under different paths, you will get separate counters even if the source text is identical.
110
136
- 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.
Copy file name to clipboardExpand all lines: guides/getting-started/readme.md
+35-21Lines changed: 35 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,12 +10,6 @@ Add the gem to your project:
10
10
$ bundle add ruby-coverage
11
11
~~~
12
12
13
-
If you are using `covered`, add that too:
14
-
15
-
~~~bash
16
-
$ bundle add covered
17
-
~~~
18
-
19
13
## Motivation
20
14
21
15
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
39
33
40
34
## Basic Usage
41
35
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:
43
37
44
38
~~~ruby
45
39
require"ruby/coverage"
@@ -55,8 +49,41 @@ pp result[path]
55
49
# => {:lines=>[nil, 2]}
56
50
~~~
57
51
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
+
58
54
This is the simplest way to get path-based accumulation across repeated evaluation of the same file.
59
55
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
+
60
87
## Using a Custom Tracer
61
88
62
89
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:
68
95
-**Integration with other tooling**: Control exactly when and how coverage data is initialized.
69
96
70
97
~~~ruby
71
-
require_relative"config/environment"
72
-
require_relative"lib/ruby/coverage"
98
+
require"ruby/coverage"
73
99
74
100
files = {}
75
101
@@ -108,15 +134,3 @@ The callback receives the file path and the active `RubyVM::InstructionSequence`
108
134
- Do not expect stdlib `Coverage` semantics from this library. It intentionally changes the ownership model from `ISeq` to path.
109
135
- If you evaluate code under different paths, you will get separate counters even if the source text is identical.
110
136
- 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.
Copy file name to clipboardExpand all lines: readme.md
+35-45Lines changed: 35 additions & 45 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,58 +8,14 @@ A native reimplementation of Ruby's built-in `Coverage` module, backed by `rb_ad
8
8
9
9
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.
10
10
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.
12
12
13
13
## Usage
14
14
15
15
Please see the [project documentation](https://socketry.github.io/ruby-coverage/) for more details.
16
16
17
17
-[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.
`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.newdo |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
-
63
19
## Releases
64
20
65
21
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
84
40
## See Also
85
41
86
42
-[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