condition_coverage 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +113 -40
- data/lib/condition_coverage/condition.rb +14 -0
- data/lib/condition_coverage/configuration.rb +98 -0
- data/lib/condition_coverage/gaps.rb +42 -0
- data/lib/condition_coverage/html/file.html +27 -0
- data/lib/condition_coverage/html/index.html +38 -0
- data/lib/condition_coverage/html/sort.js +28 -0
- data/lib/condition_coverage/html/style.css +106 -0
- data/lib/condition_coverage/html/toggle.js +12 -0
- data/lib/condition_coverage/html_file.rb +159 -0
- data/lib/condition_coverage/html_index.rb +43 -0
- data/lib/condition_coverage/html_report.rb +46 -0
- data/lib/condition_coverage/html_template.rb +20 -0
- data/lib/condition_coverage/json_writer.rb +13 -0
- data/lib/condition_coverage/kernel.rb +108 -0
- data/lib/condition_coverage/manifest.rb +92 -0
- data/lib/condition_coverage/recorder.rb +24 -0
- data/lib/condition_coverage/result.rb +31 -0
- data/lib/condition_coverage/rewriter.rb +36 -0
- data/lib/condition_coverage/site.rb +11 -0
- data/lib/condition_coverage/site_tree.rb +39 -0
- data/lib/condition_coverage/source_lines.rb +81 -0
- data/lib/condition_coverage/summary.rb +32 -0
- data/lib/condition_coverage/version.rb +3 -0
- data/lib/condition_coverage.rb +2 -3
- metadata +34 -9
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module ConditionCoverage
|
|
2
|
+
# The lines of one file's page, each with the status of the
|
|
3
|
+
# conditions on it.
|
|
4
|
+
module SourceLines
|
|
5
|
+
# [{number:, text:, status:, span:}] for each line of
|
|
6
|
+
# source. A line in a site's span shares one button with
|
|
7
|
+
# the span's other lines; status and span are nil on a line
|
|
8
|
+
# with no condition.
|
|
9
|
+
def self.of(source, sites, operands)
|
|
10
|
+
marks = marks(source, sites, operands)
|
|
11
|
+
source.lines.each_with_index.map do |text, index|
|
|
12
|
+
number = index + 1
|
|
13
|
+
mark = marks.fetch(number, {})
|
|
14
|
+
{
|
|
15
|
+
number:, text: text.chomp,
|
|
16
|
+
status: mark[:status], span: mark[:span]
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# { line number => {status:, span:} } for each line a site
|
|
22
|
+
# covers, every line of a merged span sharing that span.
|
|
23
|
+
def self.marks(source, sites, operands)
|
|
24
|
+
blocks = merged(spans_of(source, sites, operands))
|
|
25
|
+
blocks.each_with_object({}) do |(span, status), marks|
|
|
26
|
+
span.each { |number| marks[number] = { status:, span: } }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# [span, status] for each site: from the line it starts on
|
|
31
|
+
# to the line its last operand ends on.
|
|
32
|
+
def self.spans_of(source, sites, operands)
|
|
33
|
+
sites.map do |site, condition|
|
|
34
|
+
last = condition.leaves.last
|
|
35
|
+
span = line_of(site)..end_line(source, last)
|
|
36
|
+
[span, status_of(operands.fetch(site))]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The spans merged wherever they overlap, in line order. A
|
|
41
|
+
# merged span has :gaps if any of its sites has, so a
|
|
42
|
+
# covered site never hides another's gaps.
|
|
43
|
+
def self.merged(spans)
|
|
44
|
+
sorted = spans.sort_by { |span, _| span.begin }
|
|
45
|
+
sorted.each_with_object([]) do |(span, status), blocks|
|
|
46
|
+
last_span, last_status = blocks.last
|
|
47
|
+
if last_span && last_span.end >= span.begin
|
|
48
|
+
joined = last_span.begin..[last_span.end, span.end].max
|
|
49
|
+
blocks[-1] = [joined, worse(last_status, status)]
|
|
50
|
+
else
|
|
51
|
+
blocks << [span, status]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# :gaps if either status is :gaps, else :covered.
|
|
57
|
+
def self.worse(one, other)
|
|
58
|
+
[one, other].include?(:gaps) ? :gaps : :covered
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# :covered when every operand was seen both ways, else :gaps.
|
|
62
|
+
def self.status_of(counts)
|
|
63
|
+
counts.all? { |operand| seen_both?(operand) } ? :covered : :gaps
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# True when the operand was seen both true and false.
|
|
67
|
+
def self.seen_both?(counts)
|
|
68
|
+
counts[:truthy].positive? && counts[:falsy].positive?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# The line a site starts on, from its path:line:column name.
|
|
72
|
+
def self.line_of(site)
|
|
73
|
+
site[/:(\d+):\d+\z/, 1].to_i
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# The line of source on which byte range ends.
|
|
77
|
+
def self.end_line(source, range)
|
|
78
|
+
source.byteslice(0, range.end).count("\n") + 1
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module ConditionCoverage
|
|
2
|
+
# The per-file numbers the HTML index page shows.
|
|
3
|
+
module Summary
|
|
4
|
+
# One row per file that has sites in result, in path order.
|
|
5
|
+
def self.files(result)
|
|
6
|
+
by_path = result.operands.group_by { |site, _| path_of(site) }
|
|
7
|
+
by_path.sort.map { |path, sites| row(path, sites) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# The summary row of one file's sites.
|
|
11
|
+
def self.row(path, sites)
|
|
12
|
+
operands = sites.flat_map { |_, counts| counts }
|
|
13
|
+
outcomes = operands.size * 2
|
|
14
|
+
seen = operands.sum { |counts| seen_in(counts) }
|
|
15
|
+
{
|
|
16
|
+
path:, sites: sites.size, seen:, outcomes:,
|
|
17
|
+
percent: (100.0 * seen / outcomes).round,
|
|
18
|
+
missing: outcomes - seen
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# How many of an operand's two outcomes were seen.
|
|
23
|
+
def self.seen_in(counts)
|
|
24
|
+
[counts[:truthy], counts[:falsy]].count(&:positive?)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# The file a site is in: its name minus :line:column.
|
|
28
|
+
def self.path_of(site)
|
|
29
|
+
site.sub(/:\d+:\d+\z/, '')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/condition_coverage.rb
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
end
|
|
1
|
+
require_relative 'condition_coverage/version'
|
|
2
|
+
require_relative 'condition_coverage/kernel'
|
metadata
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: condition_coverage
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jon Jagger
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 2026-10-31 00:00:00.000000000 Z
|
|
@@ -24,8 +24,9 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.0'
|
|
27
|
-
description:
|
|
28
|
-
|
|
27
|
+
description: Records whether each operand of every &&, ||, and and or condition was
|
|
28
|
+
seen both true and false, and reports the gaps in the terminal and as HTML.
|
|
29
|
+
email:
|
|
29
30
|
executables: []
|
|
30
31
|
extensions: []
|
|
31
32
|
extra_rdoc_files: []
|
|
@@ -33,11 +34,35 @@ files:
|
|
|
33
34
|
- LICENSE.md
|
|
34
35
|
- README.md
|
|
35
36
|
- lib/condition_coverage.rb
|
|
37
|
+
- lib/condition_coverage/condition.rb
|
|
38
|
+
- lib/condition_coverage/configuration.rb
|
|
39
|
+
- lib/condition_coverage/gaps.rb
|
|
40
|
+
- lib/condition_coverage/html/file.html
|
|
41
|
+
- lib/condition_coverage/html/index.html
|
|
42
|
+
- lib/condition_coverage/html/sort.js
|
|
43
|
+
- lib/condition_coverage/html/style.css
|
|
44
|
+
- lib/condition_coverage/html/toggle.js
|
|
45
|
+
- lib/condition_coverage/html_file.rb
|
|
46
|
+
- lib/condition_coverage/html_index.rb
|
|
47
|
+
- lib/condition_coverage/html_report.rb
|
|
48
|
+
- lib/condition_coverage/html_template.rb
|
|
49
|
+
- lib/condition_coverage/json_writer.rb
|
|
50
|
+
- lib/condition_coverage/kernel.rb
|
|
51
|
+
- lib/condition_coverage/manifest.rb
|
|
52
|
+
- lib/condition_coverage/recorder.rb
|
|
53
|
+
- lib/condition_coverage/result.rb
|
|
54
|
+
- lib/condition_coverage/rewriter.rb
|
|
55
|
+
- lib/condition_coverage/site.rb
|
|
56
|
+
- lib/condition_coverage/site_tree.rb
|
|
57
|
+
- lib/condition_coverage/source_lines.rb
|
|
58
|
+
- lib/condition_coverage/summary.rb
|
|
59
|
+
- lib/condition_coverage/version.rb
|
|
36
60
|
homepage: https://github.com/cyber-dojo/condition_coverage
|
|
37
61
|
licenses:
|
|
38
62
|
- BSD-2-Clause
|
|
39
|
-
metadata:
|
|
40
|
-
|
|
63
|
+
metadata:
|
|
64
|
+
rubygems_mfa_required: 'true'
|
|
65
|
+
post_install_message:
|
|
41
66
|
rdoc_options: []
|
|
42
67
|
require_paths:
|
|
43
68
|
- lib
|
|
@@ -45,15 +70,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
45
70
|
requirements:
|
|
46
71
|
- - ">="
|
|
47
72
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: '
|
|
73
|
+
version: '3.2'
|
|
49
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
75
|
requirements:
|
|
51
76
|
- - ">="
|
|
52
77
|
- !ruby/object:Gem::Version
|
|
53
78
|
version: '0'
|
|
54
79
|
requirements: []
|
|
55
|
-
rubygems_version: 3.
|
|
56
|
-
signing_key:
|
|
80
|
+
rubygems_version: 3.5.22
|
|
81
|
+
signing_key:
|
|
57
82
|
specification_version: 4
|
|
58
83
|
summary: Condition coverage for Ruby, alongside SimpleCov branch coverage
|
|
59
84
|
test_files: []
|