covered 0.22.1 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/bake/covered/policy.rb +31 -0
- data/bake/covered/validate.rb +3 -16
- data/lib/covered/coverage.rb +11 -58
- data/lib/covered/files.rb +1 -1
- data/lib/covered/minitest.rb +1 -3
- data/lib/covered/persist.rb +6 -1
- data/lib/covered/source.rb +66 -0
- data/lib/covered/statistics.rb +19 -0
- data/lib/covered/version.rb +1 -1
- data/readme.md +24 -68
- data.tar.gz.sig +0 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a79659c74af1e795823f64d18c4829240e5be7cdcf03b3f719680b9d29f9522
|
4
|
+
data.tar.gz: f0d8ad9bb7330adf479b0a028bc7a03e73ff35f091d79c4308f461f984f65f77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d205944455af6959144bc22e7456ed165d308fde5989b5e6b781458aead3ded563fc7efcea3fa3ede628e85d0b678dcad82f0caa4ce851c3fa02ebd2f3432a08
|
7
|
+
data.tar.gz: 5f1d51e92917387f004e38e4e7ad0754ff1063ea348a7a4a36d52b27703fc1bb66ecd8dbc8a5815aeeaeaf71663e49c6faf072e7e7fec984c5c7c368d0035719
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2023, by Samuel Williams.
|
5
|
+
|
6
|
+
def initialize(context)
|
7
|
+
super
|
8
|
+
|
9
|
+
require_relative '../../lib/covered/config'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Load the current coverage policy.
|
13
|
+
def current(paths: nil)
|
14
|
+
policy = Covered::Policy.new
|
15
|
+
|
16
|
+
# Load the default path if no paths are specified:
|
17
|
+
paths ||= Dir.glob(Covered::Persist::DEFAULT_PATH, base: context.root)
|
18
|
+
|
19
|
+
# If no paths are specified, raise an error:
|
20
|
+
if paths.empty?
|
21
|
+
raise ArgumentError, "No coverage paths specified!"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Load all coverage information:
|
25
|
+
paths.each do |path|
|
26
|
+
# It would be nice to have a better algorithm here than just ignoring mtime - perhaps using checksums?
|
27
|
+
Covered::Persist.new(policy.output, path).load!(ignore_mtime: true)
|
28
|
+
end
|
29
|
+
|
30
|
+
return policy
|
31
|
+
end
|
data/bake/covered/validate.rb
CHANGED
@@ -12,22 +12,9 @@ end
|
|
12
12
|
# Validate the coverage of multiple test runs.
|
13
13
|
# @parameter paths [Array(String)] The coverage database paths.
|
14
14
|
# @parameter minimum [Float] The minimum required coverage in order to pass.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# Load the default path if no paths are specified:
|
19
|
-
paths ||= Dir.glob(Covered::Persist::DEFAULT_PATH, base: context.root)
|
20
|
-
|
21
|
-
# If no paths are specified, raise an error:
|
22
|
-
if paths.empty?
|
23
|
-
raise ArgumentError, "No coverage paths specified!"
|
24
|
-
end
|
25
|
-
|
26
|
-
# Load all coverage information:
|
27
|
-
paths.each do |path|
|
28
|
-
# It would be nice to have a better algorithm here than just ignoring mtime - perhaps using checksums?
|
29
|
-
Covered::Persist.new(policy.output, path).load!(ignore_mtime: true)
|
30
|
-
end
|
15
|
+
# @parameter input [Covered::Policy] The input policy to validate.
|
16
|
+
def validate(paths: nil, minimum: 1.0, input:)
|
17
|
+
policy ||= context.lookup("covered:policy:current").call(paths: paths)
|
31
18
|
|
32
19
|
# Calculate statistics:
|
33
20
|
statistics = Covered::Statistics.new
|
data/lib/covered/coverage.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2018-2023, by Samuel Williams.
|
5
5
|
|
6
|
+
require_relative 'source'
|
7
|
+
|
6
8
|
module Covered
|
7
9
|
module Ratio
|
8
10
|
def ratio
|
@@ -20,66 +22,11 @@ module Covered
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
class Source
|
24
|
-
def self.for(path, code, line_offset)
|
25
|
-
self.new(path, code: code, line_offset: line_offset)
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(path, code: nil, line_offset: 1, modified_time: nil)
|
29
|
-
@path = path
|
30
|
-
@code = code
|
31
|
-
@line_offset = line_offset
|
32
|
-
@modified_time = modified_time
|
33
|
-
end
|
34
|
-
|
35
|
-
attr_accessor :path
|
36
|
-
attr :code
|
37
|
-
attr :line_offset
|
38
|
-
attr :modified_time
|
39
|
-
|
40
|
-
def to_s
|
41
|
-
"\#<#{self.class} path=#{path}>"
|
42
|
-
end
|
43
|
-
|
44
|
-
def read(&block)
|
45
|
-
if block_given?
|
46
|
-
File.open(self.path, "r", &block)
|
47
|
-
else
|
48
|
-
File.read(self.path)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# The actual code which is being covered. If a template generates the source, this is the generated code, while the path refers to the template itself.
|
53
|
-
def code!
|
54
|
-
self.code || self.read
|
55
|
-
end
|
56
|
-
|
57
|
-
def code?
|
58
|
-
!!self.code
|
59
|
-
end
|
60
|
-
|
61
|
-
def serialize(packer)
|
62
|
-
packer.write(self.path)
|
63
|
-
packer.write(self.code)
|
64
|
-
packer.write(self.line_offset)
|
65
|
-
packer.write(self.modified_time)
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.deserialize(unpacker)
|
69
|
-
path = unpacker.read
|
70
|
-
code = unpacker.read
|
71
|
-
line_offset = unpacker.read
|
72
|
-
modified_time = unpacker.read
|
73
|
-
|
74
|
-
self.new(path, code: code, line_offset: line_offset, modified_time: modified_time)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
25
|
class Coverage
|
79
26
|
include Ratio
|
80
27
|
|
81
28
|
def self.for(path, **options)
|
82
|
-
self.new(Source.
|
29
|
+
self.new(Source.for(path, **options))
|
83
30
|
end
|
84
31
|
|
85
32
|
def initialize(source, counts = [], annotations = {}, total = nil)
|
@@ -94,6 +41,12 @@ module Covered
|
|
94
41
|
@executed_lines = nil
|
95
42
|
end
|
96
43
|
|
44
|
+
# Construct a new coverage object for the given line numbers. Only the given line numbers will be considered for the purposes of computing coverage.
|
45
|
+
# @parameter line_numbers [Array(Integer)] The line numbers to include in the new coverage object.
|
46
|
+
def for_lines(line_numbers)
|
47
|
+
self.class.new(@source, @counts.values_at(*line_numbers), @annotations)
|
48
|
+
end
|
49
|
+
|
97
50
|
def path
|
98
51
|
@source.path
|
99
52
|
end
|
@@ -104,8 +57,8 @@ module Covered
|
|
104
57
|
|
105
58
|
def fresh?
|
106
59
|
if @source.modified_time.nil?
|
107
|
-
# We don't know when the file was last modified, so we assume it is
|
108
|
-
return
|
60
|
+
# We don't know when the file was last modified, so we assume it is stale:
|
61
|
+
return false
|
109
62
|
end
|
110
63
|
|
111
64
|
unless File.exist?(@source.path)
|
data/lib/covered/files.rb
CHANGED
data/lib/covered/minitest.rb
CHANGED
data/lib/covered/persist.rb
CHANGED
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2018-2023, by Samuel Williams.
|
5
|
+
|
6
|
+
module Covered
|
7
|
+
class Source
|
8
|
+
def self.for(path, **options)
|
9
|
+
if File.exist?(path)
|
10
|
+
options[:code] ||= File.read(path)
|
11
|
+
options[:modified_time] ||= File.mtime(path)
|
12
|
+
end
|
13
|
+
|
14
|
+
self.new(path, **options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(path, code: nil, line_offset: 1, modified_time: nil)
|
18
|
+
@path = path
|
19
|
+
@code = code
|
20
|
+
@line_offset = line_offset
|
21
|
+
@modified_time = modified_time
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :path
|
25
|
+
attr :code
|
26
|
+
attr :line_offset
|
27
|
+
attr :modified_time
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"\#<#{self.class} path=#{path}>"
|
31
|
+
end
|
32
|
+
|
33
|
+
def read(&block)
|
34
|
+
if block_given?
|
35
|
+
File.open(self.path, "r", &block)
|
36
|
+
else
|
37
|
+
File.read(self.path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The actual code which is being covered. If a template generates the source, this is the generated code, while the path refers to the template itself.
|
42
|
+
def code!
|
43
|
+
self.code || self.read
|
44
|
+
end
|
45
|
+
|
46
|
+
def code?
|
47
|
+
!!self.code
|
48
|
+
end
|
49
|
+
|
50
|
+
def serialize(packer)
|
51
|
+
packer.write(self.path)
|
52
|
+
packer.write(self.code)
|
53
|
+
packer.write(self.line_offset)
|
54
|
+
packer.write(self.modified_time)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.deserialize(unpacker)
|
58
|
+
path = unpacker.read
|
59
|
+
code = unpacker.read
|
60
|
+
line_offset = unpacker.read
|
61
|
+
modified_time = unpacker.read
|
62
|
+
|
63
|
+
self.new(path, code: code, line_offset: line_offset, modified_time: modified_time)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/covered/statistics.rb
CHANGED
@@ -11,6 +11,12 @@ module Covered
|
|
11
11
|
end
|
12
12
|
|
13
13
|
class Statistics < Wrapper
|
14
|
+
def self.for(coverage)
|
15
|
+
self.new.tap do |statistics|
|
16
|
+
statistics << coverage
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
14
20
|
def initialize
|
15
21
|
@count = 0
|
16
22
|
@executable_count = 0
|
@@ -26,6 +32,19 @@ module Covered
|
|
26
32
|
# The number of lines that were executed.
|
27
33
|
attr :executed_count
|
28
34
|
|
35
|
+
def as_json
|
36
|
+
{
|
37
|
+
count: count,
|
38
|
+
executable_count: executable_count,
|
39
|
+
executed_count: executed_count,
|
40
|
+
percentage: percentage.to_f.round(2),
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_json(options)
|
45
|
+
as_json.to_json(options)
|
46
|
+
end
|
47
|
+
|
29
48
|
def << coverage
|
30
49
|
@count += 1
|
31
50
|
|
data/lib/covered/version.rb
CHANGED
data/readme.md
CHANGED
@@ -1,86 +1,40 @@
|
|
1
1
|
# Covered
|
2
2
|
|
3
|
-
|
3
|
+
![Screenshot](media/example.png)
|
4
4
|
|
5
|
-
Covered uses modern Ruby features to generate comprehensive coverage, including support for templates which are compiled
|
5
|
+
Covered uses modern Ruby features to generate comprehensive coverage, including support for templates which are compiled
|
6
|
+
into Ruby.
|
6
7
|
|
7
|
-
- Incremental coverage - if you run your full test suite, and the run a subset, it will still report the correct
|
8
|
-
|
8
|
+
- Incremental coverage - if you run your full test suite, and the run a subset, it will still report the correct
|
9
|
+
coverage - so you can incrementally work on improving coverage.
|
10
|
+
- Integration with Sus, Git, RSpec and Minitest- no need to configure anything - out of the box support for these
|
11
|
+
platforms.
|
9
12
|
- Supports coverage of views - templates compiled to Ruby code can be tracked for coverage reporting.
|
10
13
|
|
11
|
-
![
|
14
|
+
[![Development
|
15
|
+
Status](https://github.com/ioquatix/covered/workflows/Test/badge.svg)](https://github.com/ioquatix/covered/actions?workflow=Test)
|
12
16
|
|
13
17
|
## Motivation
|
14
18
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
## Installation
|
20
|
-
|
21
|
-
Add this line to your application's `Gemfile`:
|
22
|
-
|
23
|
-
``` ruby
|
24
|
-
gem 'covered'
|
25
|
-
```
|
26
|
-
|
27
|
-
### RSpec Integration
|
28
|
-
|
29
|
-
In your `spec/spec_helper.rb` add the following before loading any other code:
|
30
|
-
|
31
|
-
``` ruby
|
32
|
-
require 'covered/rspec'
|
33
|
-
```
|
34
|
-
|
35
|
-
Ensure that you have a `.rspec` file with `--require spec_helper`:
|
36
|
-
|
37
|
-
--require spec_helper
|
38
|
-
--format documentation
|
39
|
-
--warnings
|
40
|
-
|
41
|
-
### Minitest Integration
|
19
|
+
Originally, Ruby coverage tools were unable to handle `eval`ed code. This is because the `coverage` module built into
|
20
|
+
Ruby doesn't expose the necessary hooks to capture it. Using the [parser](https://github.com/whitequark/parser) gem and
|
21
|
+
trace points allows us to do our own source code analysis to compute executable lines, thus making it possible to
|
22
|
+
compute coverage for "templates".
|
42
23
|
|
43
|
-
|
44
|
-
|
45
|
-
``` ruby
|
46
|
-
require 'covered/minitest'
|
47
|
-
require 'minitest/autorun'
|
48
|
-
```
|
49
|
-
|
50
|
-
In your test files, e.g. `test/dummy_test.rb` add the following at the top:
|
51
|
-
|
52
|
-
``` ruby
|
53
|
-
require_relative 'test_helper'
|
54
|
-
```
|
24
|
+
After this concept prooved useful, [it was integrated directly into Ruby](https://bugs.ruby-lang.org/issues/19008).
|
55
25
|
|
56
26
|
## Usage
|
57
27
|
|
58
|
-
|
59
|
-
|
60
|
-
COVERAGE=Summary rspec
|
61
|
-
|
62
|
-
If no `COVERAGE` is specified, coverage tracking will be finishd.
|
63
|
-
|
64
|
-
### Template Coverage
|
65
|
-
|
66
|
-
Covered supports coverage of templates which are compiled into Ruby code. This is only supported on Ruby 3.2+ due to enhancements in the coverage interface.
|
67
|
-
|
68
|
-
### Partial Summary
|
69
|
-
|
70
|
-
COVERAGE=PartialSummary rspec
|
71
|
-
|
72
|
-
This report only shows snippets of source code with incomplete coverage.
|
73
|
-
|
74
|
-
### Brief Summary
|
75
|
-
|
76
|
-
COVERAGE=BriefSummary rspec
|
28
|
+
Please see the [project documentation](https://github.com/ioquatix/covered) for more details.
|
77
29
|
|
78
|
-
|
30
|
+
- [Getting Started](https://github.com/ioquatix/coveredguides/getting-started/index) - This guide explains how to get
|
31
|
+
started with `covered` and integrate it with your test suite.
|
79
32
|
|
80
33
|
## See Also
|
81
34
|
|
82
|
-
- [
|
83
|
-
|
35
|
+
- [simplecov](https://github.com/colszowka/simplecov) – one of the original coverage implementations for Ruby, uses
|
36
|
+
the built-in `coverage` library.
|
37
|
+
- [sus](https://github.com/ioquatix/sus) - a test framework which uses `covered` to generate coverage reports.
|
84
38
|
|
85
39
|
## Contributing
|
86
40
|
|
@@ -94,8 +48,10 @@ We welcome contributions to this project.
|
|
94
48
|
|
95
49
|
### Developer Certificate of Origin
|
96
50
|
|
97
|
-
This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this
|
51
|
+
This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this
|
52
|
+
project must agree to this document to have their contributions accepted.
|
98
53
|
|
99
54
|
### Contributor Covenant
|
100
55
|
|
101
|
-
This project is governed by [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and
|
56
|
+
This project is governed by [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and
|
57
|
+
participants agree to abide by its terms.
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: covered
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.23.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -42,7 +42,7 @@ cert_chain:
|
|
42
42
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
43
43
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
44
44
|
-----END CERTIFICATE-----
|
45
|
-
date: 2023-07-
|
45
|
+
date: 2023-07-20 00:00:00.000000000 Z
|
46
46
|
dependencies:
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: console
|
@@ -79,6 +79,7 @@ extensions: []
|
|
79
79
|
extra_rdoc_files: []
|
80
80
|
files:
|
81
81
|
- bake/covered/debug.rb
|
82
|
+
- bake/covered/policy.rb
|
82
83
|
- bake/covered/validate.rb
|
83
84
|
- lib/covered.rb
|
84
85
|
- lib/covered/autostart.rb
|
@@ -92,6 +93,7 @@ files:
|
|
92
93
|
- lib/covered/persist.rb
|
93
94
|
- lib/covered/policy.rb
|
94
95
|
- lib/covered/rspec.rb
|
96
|
+
- lib/covered/source.rb
|
95
97
|
- lib/covered/statistics.rb
|
96
98
|
- lib/covered/summary.rb
|
97
99
|
- lib/covered/sus.rb
|
metadata.gz.sig
CHANGED
Binary file
|