simplecov-compare 0.1.0

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.
@@ -0,0 +1,59 @@
1
+ {
2
+ "RSpec": {
3
+ "coverage": {
4
+ "/path/to/app/helpers/application_helper.rb": {
5
+ "lines": [
6
+ 1,
7
+ null
8
+ ]
9
+ },
10
+ "/path/to/app/models/model_name.rb": {
11
+ "lines": [
12
+ 1,
13
+ 1,
14
+ null,
15
+ 1,
16
+ 1,
17
+ null,
18
+ 1,
19
+ 6,
20
+ null,
21
+ null,
22
+ null,
23
+ 1,
24
+ null,
25
+ 7,
26
+ 12,
27
+ 0,
28
+ null,
29
+ 0,
30
+ null,
31
+ null,
32
+ null,
33
+ null
34
+ ]
35
+ },
36
+ "/path/to/app/models/other_model.rb": {
37
+ "lines": [
38
+ 7,
39
+ 5,
40
+ 5,
41
+ 4,
42
+ 4,
43
+ 4,
44
+ null,
45
+ 0,
46
+ 0,
47
+ 0,
48
+ null,
49
+ 0,
50
+ 0,
51
+ 0,
52
+ null
53
+ ],
54
+ "branches": {}
55
+ }
56
+ },
57
+ "timestamp": 1770264586
58
+ }
59
+ }
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module Simplecov
6
+ module Compare
7
+ describe FileComparison do
8
+ describe "#same_file?" do
9
+ it "is true when the file names of both file results are the same" do
10
+ base = FileResult.new("name.txt", coverage_data: nil)
11
+ other = FileResult.new("name.txt", coverage_data: nil)
12
+
13
+ comparison = FileComparison.new(base, to: other)
14
+
15
+ assert_equal true, comparison.same_file?
16
+ end
17
+
18
+ it "is false when the file names of both file results are different" do
19
+ base = FileResult.new("name.txt", coverage_data: nil)
20
+ other = FileResult.new("different.txt", coverage_data: nil)
21
+
22
+ comparison = FileComparison.new(base, to: other)
23
+
24
+ assert_equal false, comparison.same_file?
25
+ end
26
+
27
+ it "is false when there is no base" do
28
+ other = FileResult.new("different.txt", coverage_data: nil)
29
+
30
+ comparison = FileComparison.new(nil, to: other)
31
+
32
+ assert_equal false, comparison.same_file?
33
+ end
34
+ end
35
+
36
+ describe "#filename" do
37
+ it "is the name of the base file when base exists" do
38
+ base = FileResult.new("name.txt", coverage_data: nil)
39
+ other = FileResult.new("different.txt", coverage_data: nil)
40
+
41
+ comparison = FileComparison.new(base, to: other)
42
+
43
+ assert_equal "name.txt", comparison.filename
44
+ end
45
+
46
+ it "is the name of the other file when there is no base" do
47
+ other = FileResult.new("different.txt", coverage_data: nil)
48
+
49
+ comparison = FileComparison.new(nil, to: other)
50
+
51
+ assert_equal "different.txt", comparison.filename
52
+ end
53
+
54
+ it "is nil when there is neither a base nor another file" do
55
+ comparison = FileComparison.new(nil, to: nil)
56
+
57
+ assert_nil comparison.filename
58
+ end
59
+ end
60
+
61
+ describe "#lines_coverage_different?" do
62
+ it "is true when the lines coverage is different" do
63
+ base = Mocktail.of(FileResult)
64
+ stubs { base.lines_covered_percent }.with { 5 }
65
+
66
+ other = Mocktail.of(FileResult)
67
+ stubs { other.lines_covered_percent }.with { 6 }
68
+
69
+ comparison = FileComparison.new(base, to: other)
70
+
71
+ assert_equal true, comparison.lines_coverage_different?
72
+ end
73
+
74
+ it "is false when the lines coverage is the same" do
75
+ base = Mocktail.of(FileResult)
76
+ stubs { base.lines_covered_percent }.with { 5 }
77
+
78
+ other = Mocktail.of(FileResult)
79
+ stubs { other.lines_covered_percent }.with { 5 }
80
+
81
+ comparison = FileComparison.new(base, to: other)
82
+
83
+ assert_equal false, comparison.lines_coverage_different?
84
+ end
85
+ end
86
+
87
+ describe "#lines_coverage_equal?" do
88
+ it "is true when the lines coverage is the same" do
89
+ base = Mocktail.of(FileResult)
90
+ stubs { base.lines_covered_percent }.with { 5 }
91
+
92
+ other = Mocktail.of(FileResult)
93
+ stubs { other.lines_covered_percent }.with { 5 }
94
+
95
+ comparison = FileComparison.new(base, to: other)
96
+
97
+ assert_equal true, comparison.lines_coverage_equal?
98
+ end
99
+
100
+ it "is false when the lines coverage is different" do
101
+ base = Mocktail.of(FileResult)
102
+ stubs { base.lines_covered_percent }.with { 5 }
103
+
104
+ other = Mocktail.of(FileResult)
105
+ stubs { other.lines_covered_percent }.with { 6 }
106
+
107
+ comparison = FileComparison.new(base, to: other)
108
+
109
+ assert_equal false, comparison.lines_coverage_equal?
110
+ end
111
+ end
112
+
113
+ describe "#lines_coverage_increased?" do
114
+ it "is true when the lines coverage of the other is higher" do
115
+ base = Mocktail.of(FileResult)
116
+ stubs { base.lines_covered_percent }.with { 5 }
117
+
118
+ other = Mocktail.of(FileResult)
119
+ stubs { other.lines_covered_percent }.with { 6 }
120
+
121
+ comparison = FileComparison.new(base, to: other)
122
+
123
+ assert_equal true, comparison.lines_coverage_increased?
124
+ end
125
+
126
+ it "is false when the lines coverage of the base is higher" do
127
+ base = Mocktail.of(FileResult)
128
+ stubs { base.lines_covered_percent }.with { 6 }
129
+
130
+ other = Mocktail.of(FileResult)
131
+ stubs { other.lines_covered_percent }.with { 5 }
132
+
133
+ comparison = FileComparison.new(base, to: other)
134
+
135
+ assert_equal false, comparison.lines_coverage_increased?
136
+ end
137
+
138
+ it "is false when the lines coverage is the same" do
139
+ base = Mocktail.of(FileResult)
140
+ stubs { base.lines_covered_percent }.with { 5 }
141
+
142
+ other = Mocktail.of(FileResult)
143
+ stubs { other.lines_covered_percent }.with { 5 }
144
+
145
+ comparison = FileComparison.new(base, to: other)
146
+
147
+ assert_equal false, comparison.lines_coverage_increased?
148
+ end
149
+ end
150
+
151
+ describe "#lines_coverage_decreased?" do
152
+ it "is true when the lines coverage of the base is higher" do
153
+ base = Mocktail.of(FileResult)
154
+ stubs { base.lines_covered_percent }.with { 6 }
155
+
156
+ other = Mocktail.of(FileResult)
157
+ stubs { other.lines_covered_percent }.with { 5 }
158
+
159
+ comparison = FileComparison.new(base, to: other)
160
+
161
+ assert_equal true, comparison.lines_coverage_decreased?
162
+ end
163
+
164
+ it "is false when the lines coverage of the other is higher" do
165
+ base = Mocktail.of(FileResult)
166
+ stubs { base.lines_covered_percent }.with { 5 }
167
+
168
+ other = Mocktail.of(FileResult)
169
+ stubs { other.lines_covered_percent }.with { 6 }
170
+
171
+ comparison = FileComparison.new(base, to: other)
172
+
173
+ assert_equal false, comparison.lines_coverage_decreased?
174
+ end
175
+
176
+ it "is false when the lines coverage is the same" do
177
+ base = Mocktail.of(FileResult)
178
+ stubs { base.lines_covered_percent }.with { 5 }
179
+
180
+ other = Mocktail.of(FileResult)
181
+ stubs { other.lines_covered_percent }.with { 5 }
182
+
183
+ comparison = FileComparison.new(base, to: other)
184
+
185
+ assert_equal false, comparison.lines_coverage_decreased?
186
+ end
187
+ end
188
+
189
+ describe "#lines_coverage_delta_points" do
190
+ it "is the positive difference between the base and the higher other coverage" do
191
+ base = Mocktail.of(FileResult)
192
+ stubs { base.lines_covered_percent }.with { 50 }
193
+
194
+ other = Mocktail.of(FileResult)
195
+ stubs { other.lines_covered_percent }.with { 60 }
196
+
197
+ comparison = FileComparison.new(base, to: other)
198
+
199
+ assert_equal 10, comparison.lines_coverage_delta_points
200
+ end
201
+
202
+ it "is the negative difference between the base and the lower other coverage" do
203
+ base = Mocktail.of(FileResult)
204
+ stubs { base.lines_covered_percent }.with { 60 }
205
+
206
+ other = Mocktail.of(FileResult)
207
+ stubs { other.lines_covered_percent }.with { 50 }
208
+
209
+ comparison = FileComparison.new(base, to: other)
210
+
211
+ assert_equal(-10, comparison.lines_coverage_delta_points)
212
+ end
213
+
214
+ it "is a positive amount of the other lines coverage when there is no base" do
215
+ other = Mocktail.of(FileResult)
216
+ stubs { other.lines_covered_percent }.with { 50 }
217
+
218
+ comparison = FileComparison.new(nil, to: other)
219
+
220
+ assert_equal(50, comparison.lines_coverage_delta_points)
221
+ end
222
+
223
+ it "is a negative amount of the base lines coverage when there is no other" do
224
+ base = Mocktail.of(FileResult)
225
+ stubs { base.lines_covered_percent }.with { 50 }
226
+
227
+ comparison = FileComparison.new(base, to: nil)
228
+
229
+ assert_equal(-50, comparison.lines_coverage_delta_points)
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module Simplecov
6
+ module Compare
7
+ describe FileLine do
8
+ describe "#irrelevant?" do
9
+ it "is true when the covered count is nil" do
10
+ line = FileLine.new(line_number: 3, covered_count: nil)
11
+
12
+ assert_equal true, line.irrelevant?
13
+ end
14
+
15
+ it "is false when the covered count is a number" do
16
+ line = FileLine.new(line_number: 3, covered_count: 1)
17
+
18
+ assert_equal false, line.irrelevant?
19
+ end
20
+ end
21
+
22
+ describe "#relevant?" do
23
+ it "is false when the covered count is nil" do
24
+ line = FileLine.new(line_number: 3, covered_count: nil)
25
+
26
+ assert_equal false, line.relevant?
27
+ end
28
+
29
+ it "is true when the covered count is a number" do
30
+ line = FileLine.new(line_number: 3, covered_count: 1)
31
+
32
+ assert_equal true, line.relevant?
33
+ end
34
+ end
35
+
36
+ describe "#missed?" do
37
+ it "is true when a relevant line has a covered count of zero" do
38
+ line = FileLine.new(line_number: 3, covered_count: 0)
39
+
40
+ assert_equal true, line.missed?
41
+ end
42
+
43
+ it "is false when the line is irrelevant" do
44
+ line = FileLine.new(line_number: 3, covered_count: nil)
45
+
46
+ assert_equal false, line.missed?
47
+ end
48
+
49
+ it "is false for a relevant line with a covered count" do
50
+ line = FileLine.new(line_number: 3, covered_count: 1)
51
+
52
+ assert_equal false, line.missed?
53
+ end
54
+ end
55
+
56
+ describe "#covered?" do
57
+ it "is true for a relevant line with a covered count" do
58
+ line = FileLine.new(line_number: 3, covered_count: 1)
59
+
60
+ assert_equal true, line.covered?
61
+ end
62
+
63
+ it "is false when a relevant line has a covered count of zero" do
64
+ line = FileLine.new(line_number: 3, covered_count: 0)
65
+
66
+ assert_equal false, line.covered?
67
+ end
68
+
69
+ it "is false when the line is irrelevant" do
70
+ line = FileLine.new(line_number: 3, covered_count: nil)
71
+
72
+ assert_equal false, line.covered?
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module Simplecov
6
+ module Compare
7
+ describe FileResult do
8
+ describe "#lines" do
9
+ it "converts the lines coverage data into a collection of file lines" do
10
+ coverage_data = { "lines" => [0, 1, nil, 47] }
11
+ file = FileResult.new(nil, coverage_data:)
12
+
13
+ assert_equal 4, file.lines.size
14
+ assert_equal FileLine, file.lines.first.class
15
+ assert_equal [1, 2, 3, 4], file.lines.map { _1.line_number }
16
+ assert_equal [false, true, false, true], file.lines.map { _1.covered? }
17
+ end
18
+
19
+ it "is an empty collection when no coverage data is provided" do
20
+ file = FileResult.new(nil, coverage_data: nil)
21
+
22
+ assert_empty file.lines
23
+ end
24
+
25
+ it "is an empty collection with no lines coverage" do
26
+ file = FileResult.new(nil, coverage_data: {})
27
+
28
+ assert_empty file.lines
29
+ end
30
+ end
31
+
32
+ describe "#relevant_lines" do
33
+ it "provides the lines with relevant coverage information" do
34
+ coverage_data = { "lines" => [0, 1, nil, 47] }
35
+ file = FileResult.new(nil, coverage_data:)
36
+
37
+ assert_equal [1, 2, 4], file.relevant_lines.map { _1.line_number }
38
+ end
39
+ end
40
+
41
+ describe "#covered_lines" do
42
+ it "provides the lines that have been covered in the coverage report" do
43
+ coverage_data = { "lines" => [0, 1, nil, 47] }
44
+ file = FileResult.new(nil, coverage_data:)
45
+
46
+ assert_equal [2, 4], file.covered_lines.map { _1.line_number }
47
+ end
48
+ end
49
+
50
+ describe "#lines_covered_percent" do
51
+ it "is the percentage of relevant lines in the file that have been covered" do
52
+ coverage_data = { "lines" => [0, 1, nil, 47] }
53
+ file = FileResult.new(nil, coverage_data:)
54
+
55
+ assert_equal 66.67, file.lines_covered_percent
56
+ end
57
+
58
+ it "is 100 when there are no relevant lines" do
59
+ file = FileResult.new(nil, coverage_data: nil)
60
+
61
+ assert_equal 100, file.lines_covered_percent
62
+ end
63
+ end
64
+
65
+ describe "#same_file?" do
66
+ it "is true when file results share the same name" do
67
+ file = FileResult.new("name.txt", coverage_data: nil)
68
+ other = FileResult.new("name.txt", coverage_data: nil)
69
+
70
+ assert_equal true, file.same_file?(other)
71
+ end
72
+
73
+ it "is true when file results share the same name with different casing" do
74
+ file = FileResult.new("name.txt", coverage_data: nil)
75
+ other = FileResult.new("NAme.txt", coverage_data: nil)
76
+
77
+ assert_equal true, file.same_file?(other)
78
+ end
79
+
80
+ it "is false when the file results have a different name" do
81
+ file = FileResult.new("name.txt", coverage_data: nil)
82
+ other = FileResult.new("different.txt", coverage_data: nil)
83
+
84
+ assert_equal false, file.same_file?(other)
85
+ end
86
+
87
+ it "is false when the passed in comparison is not a file result" do
88
+ file = FileResult.new("name.txt", coverage_data: nil)
89
+
90
+ assert_equal false, file.same_file?(1)
91
+ end
92
+
93
+ it "is false when the file result has no filename" do
94
+ file = FileResult.new(nil, coverage_data: nil)
95
+ other = FileResult.new("different.txt", coverage_data: nil)
96
+
97
+ assert_equal false, file.same_file?(other)
98
+ end
99
+
100
+ it "is false when the other file result has no filename" do
101
+ file = FileResult.new("name.txt", coverage_data: nil)
102
+ other = FileResult.new(nil, coverage_data: nil)
103
+
104
+ assert_equal false, file.same_file?(other)
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module Simplecov
6
+ module Compare
7
+ module Formatter
8
+ describe MarkdownFormatter do
9
+ describe "#format" do
10
+ it "is a string of text in markdown describing the difference between two coverage reports with the biggest decreases in coverage in files at the top" do
11
+ comparison = Mocktail.of(ResultSetComparison)
12
+ stubs { comparison.original_lines_covered_percent }.with { 33 }
13
+ stubs { comparison.new_lines_covered_percent }.with { 42 }
14
+ stubs { comparison.lines_coverage_increased? }.with { true }
15
+ stubs { comparison.lines_coverage_delta_points }.with { 9 }
16
+ stubs { comparison.file_differences? }.with { true }
17
+
18
+ big_decrease = Mocktail.of(FileComparison)
19
+ stubs { big_decrease.filename }.with { "big_decrease.rb" }
20
+ stubs { big_decrease.lines_coverage_delta_points }.with { -20 }
21
+ small_decrease = Mocktail.of(FileComparison)
22
+ stubs { small_decrease.filename }.with { "small_decrease.rb" }
23
+ stubs { small_decrease.lines_coverage_delta_points }.with { -3 }
24
+ small_increase = Mocktail.of(FileComparison)
25
+ stubs { small_increase.filename }.with { "small_increase.rb" }
26
+ stubs { small_increase.lines_coverage_delta_points }.with { 7 }
27
+ big_increase = Mocktail.of(FileComparison)
28
+ stubs { big_increase.filename }.with { "big_increase.rb" }
29
+ stubs { big_increase.lines_coverage_delta_points }.with { 25 }
30
+
31
+ stubs { comparison.file_differences }.with { [big_increase, small_decrease, big_decrease, small_increase] }
32
+
33
+ markdown_result = <<~MARKDOWN
34
+ # Coverage Comparison
35
+
36
+ ## Overall Impact: 📈
37
+
38
+ Coverage increased 9 points from 33% to 42%.
39
+
40
+ ## File Differences
41
+
42
+ | File Name | Coverage Change |
43
+ | --------- | --------------- |
44
+ | big_decrease.rb | -20 |
45
+ | small_decrease.rb | -3 |
46
+ | small_increase.rb | 7 |
47
+ | big_increase.rb | 25 |
48
+
49
+
50
+ MARKDOWN
51
+
52
+ formatter = MarkdownFormatter.new
53
+
54
+ assert_equal markdown_result, formatter.format(comparison)
55
+ end
56
+
57
+ it "shows a positive change when the coverage increased" do
58
+ comparison = Mocktail.of(ResultSetComparison)
59
+ stubs { comparison.original_lines_covered_percent }.with { 33 }
60
+ stubs { comparison.new_lines_covered_percent }.with { 42 }
61
+ stubs { comparison.lines_coverage_increased? }.with { true }
62
+ stubs { comparison.lines_coverage_delta_points }.with { 9 }
63
+
64
+ formatter = MarkdownFormatter.new
65
+
66
+ assert_includes formatter.format(comparison), "## Overall Impact: 📈\n\nCoverage increased 9 points from 33% to 42%."
67
+ end
68
+
69
+ it "shows a negative change when the coverage decreased" do
70
+ comparison = Mocktail.of(ResultSetComparison)
71
+ stubs { comparison.original_lines_covered_percent }.with { 42 }
72
+ stubs { comparison.new_lines_covered_percent }.with { 33 }
73
+ stubs { comparison.lines_coverage_increased? }.with { false }
74
+ stubs { comparison.lines_coverage_decreased? }.with { true }
75
+ stubs { comparison.lines_coverage_delta_points }.with { -9 }
76
+
77
+ formatter = MarkdownFormatter.new
78
+
79
+ assert_includes formatter.format(comparison), "## Overall Impact: 📉\n\nCoverage decreased 9 points from 42% to 33%."
80
+ end
81
+
82
+ it "shows no change when the coverage is the same" do
83
+ comparison = Mocktail.of(ResultSetComparison)
84
+ stubs { comparison.original_lines_covered_percent }.with { 33 }
85
+ stubs { comparison.new_lines_covered_percent }.with { 33 }
86
+ stubs { comparison.lines_coverage_increased? }.with { false }
87
+ stubs { comparison.lines_coverage_decreased? }.with { false }
88
+ formatter = MarkdownFormatter.new
89
+
90
+ assert_includes formatter.format(comparison), "## Overall Impact: 🟰\n\nCoverage maintained at 33%."
91
+ end
92
+
93
+ it "tells that all files have the same coverage when there are no file differences" do
94
+ comparison = Mocktail.of(ResultSetComparison)
95
+ stubs { comparison.file_differences? }.with { false }
96
+
97
+ formatter = MarkdownFormatter.new
98
+
99
+ assert_includes formatter.format(comparison), "## File Differences\n\nAll files maintained the same level of coverage."
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module Simplecov
6
+ module Compare
7
+ module Reporter
8
+ describe SimpleReporter do
9
+ describe "#report" do
10
+ it "outputs the provided information to std-out" do
11
+ assert_output("here are all the differences\n") { SimpleReporter.new.report("here are all the differences") }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module Simplecov
6
+ module Compare
7
+ describe ResultFile do
8
+ describe "#coverage_data" do
9
+ it "extracts the coverage data out of the provided file as a hash" do
10
+ file = ResultFile.new("test/fixtures/sample_resultset.json")
11
+
12
+ hash_from_file = {
13
+ "/path/to/app/helpers/application_helper.rb" => {
14
+ "lines" => [1, nil],
15
+ },
16
+ "/path/to/app/models/model_name.rb" => {
17
+ "lines" => [1, 1, nil, 1, 1, nil, 1, 6, nil, nil, nil, 1, nil, 7, 12, 0, nil, 0, nil, nil, nil, nil],
18
+ },
19
+ "/path/to/app/models/other_model.rb" => {
20
+ "lines" => [7, 5, 5, 4, 4, 4, nil, 0, 0, 0, nil, 0, 0, 0, nil],
21
+ "branches" => {}},
22
+ }
23
+
24
+ assert_equal(hash_from_file, file.coverage_data)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end