simplecov_linter_formatter 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 483e6b37b14cb89c8d7d464115018180fa013dd672f8a9f965b5fea0dad83a3f
4
- data.tar.gz: 123ef1b96087793991debd9d356c30fffecefff1f081531bbd3679ed90369267
3
+ metadata.gz: 5f1ca65ad6bdacc453fa5df9593826cf34106da48e60886fd8ff69fccc523cad
4
+ data.tar.gz: e7b97571b7de89cf5babfde9695d06fcac5b3bb492f2e22036e1c566590b0d3e
5
5
  SHA512:
6
- metadata.gz: 90fe058c5340e29ddcb0ae7346781fee8b9cdc8464d6d0b5c8cac06d8ce135d9174d1746e1dcbde8ee5bcb99d4782137ada8cdf62a54f641f3dbeea69341fde6
7
- data.tar.gz: e605b920212343c9d65cdf0aaf9dc476b70bacf5fd5d6af6e27e11c98aaa7e4a7bcfa1c6d323fc85de0ea9897d31058009f669a6a964f51e7bd0532c1b12cfa0
6
+ metadata.gz: 2336fa2a71a62a6f60e99b82bbe1721254aa43269cfc362d97712190490d915d982e55a4d1f15914f433c50ff2d1fb823e6cc158d6967da906e976f51d424049
7
+ data.tar.gz: df7616fa9792a3ac67b84275430f523a8984c2066901c84ead8c5179ce2529010bdb421b6795c58298ef8446544d49889c43b11f02ea3a8cddb774a2d367c384
data/CHANGELOG.md CHANGED
@@ -2,7 +2,12 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
- ### Unreleased
5
+ ### v0.2.0
6
+
7
+ #### Added
8
+
9
+ * Add on screen summary report.
10
+ * Use `git diff` if `reviewdog` is not installed.
6
11
 
7
12
  ### v0.1.0
8
13
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simplecov_linter_formatter (0.1.0)
4
+ simplecov_linter_formatter (0.2.0)
5
+ rainbow
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -5,9 +5,21 @@
5
5
 
6
6
  Linter formatter for SimpleCov code coverage tool
7
7
 
8
- <img src="./docs/assets/not-covered.png" witdh="300" />
9
- <img src="./docs/assets/partial-cov.png" witdh="300" />
10
- <img src="./docs/assets/covered.png" witdh="300" />
8
+ ***Note: To learn more about SimpleCov, check out the main repo at [https://github.com/simplecov-ruby/simplecov](https://github.com/colszowka/simplecov)***
9
+
10
+ This formatter has two features:
11
+
12
+ 1) It generates a json file to feed the [VSCode SimpleCov plugin](https://github.com/anykeyh/simplecov-vscode).
13
+
14
+ The plugin uses by default the json file produced by simplecov but, with this gem, we can filter the file to show code coverage related to our changes.
15
+
16
+ <img src="./docs/assets/not-covered.png" witdh="300" />
17
+ <img src="./docs/assets/partial-cov.png" witdh="300" />
18
+ <img src="./docs/assets/covered.png" witdh="300" />
19
+
20
+ 2) It shows a code coverage report on screen.
21
+
22
+ <img src="./docs/assets/report-example.png" witdh="300" />
11
23
 
12
24
  ## Installation
13
25
 
@@ -17,6 +29,8 @@ Linter formatter for SimpleCov code coverage tool
17
29
  brew install reviewdog/tap/reviewdog
18
30
  ```
19
31
 
32
+ > You can avoid this step and `git status` will be used to filter results instead.
33
+
20
34
  - Install [VSCode SimpleCov plugin](https://github.com/anykeyh/simplecov-vscode)
21
35
 
22
36
  You need to configure `SimpleCovLinterFormatter.json_filename = '.resultset.json'` to use the extension's default configuration.
@@ -41,8 +55,10 @@ Add the formatter to your `spec/spec_helper.rb`.
41
55
  require 'simplecov'
42
56
  require 'simplecov_linter_formatter'
43
57
 
44
- SimpleCovLinterFormatter.json_filename = '.resultset.json'
45
- SimpleCovLinterFormatter.scope = :all
58
+ SimpleCovLinterFormatter.setup do |config|
59
+ config.json_filename = '.resultset.json'
60
+ config.scope = :all
61
+ end
46
62
 
47
63
  SimpleCov.start 'rails' do
48
64
  # ...
@@ -58,6 +74,41 @@ end
58
74
 
59
75
  If you configure `SimpleCovLinterFormatter.scope = :own_changes` instead of `:all` you will see coverage warnings related to your changes only (it uses `git diff`).
60
76
 
77
+ ### Summary Report
78
+
79
+ - Turn on the on screen report with option: `SimpleCovLinterFormatter.summary_enabled = true`
80
+ - Scope variation will affect the report:
81
+ - `SimpleCovLinterFormatter.scope = :all`
82
+
83
+ <img src="./docs/assets/all-summary.png" witdh="300" />
84
+
85
+ - `SimpleCovLinterFormatter.scope = :own_changes`
86
+
87
+ <img src="./docs/assets/own-changes-summary.png" witdh="300" />
88
+
89
+ - Sort by `:alphabet` or, the default, `:coverage` option with `SimpleCovLinterFormatter.summary_files_sorting = :alphabet`
90
+
91
+ <img src="./docs/assets/sorted-summary.png" witdh="300" />
92
+
93
+ - Change the look of the report:
94
+ - Turn off the background with `SimpleCovLinterFormatter.summary_enabled_bg = false`
95
+
96
+ <img src="./docs/assets/no-bg-summary.png" witdh="300" />
97
+
98
+ - Change colors:
99
+
100
+ ```ruby
101
+ SimpleCovLinterFormatter.setup do |config|
102
+ config.summary_enabled_bg = true # you need enabled background
103
+ config.summary_covered_bg_color = :lightblue
104
+ config.summary_not_covered_bg_color = :pink
105
+ config.summary_text_color = :black
106
+ end
107
+ ```
108
+
109
+ <img src="./docs/assets/colors-summary.png" witdh="300" />
110
+
111
+
61
112
  ## Testing
62
113
 
63
114
  To run the specs you need to execute, **in the root path of the gem**, the following command:
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,63 @@
1
+ module SimpleCovLinterFormatter
2
+ class FileLine
3
+ attr_reader :file_name
4
+
5
+ def initialize(line)
6
+ @line = line
7
+ assign_attributes
8
+ end
9
+
10
+ def status
11
+ @status.to_sym
12
+ end
13
+
14
+ def line_number
15
+ @line_number.to_i
16
+ end
17
+
18
+ def line_number_idx
19
+ line_number - 1
20
+ end
21
+
22
+ def column
23
+ @column.to_i
24
+ end
25
+
26
+ def lines_count
27
+ @lines_count.to_i
28
+ end
29
+
30
+ def percentage
31
+ @percentage.to_f
32
+ end
33
+
34
+ def file_short_name
35
+ @file_short_name ||= file_name.gsub(project_path, "")
36
+ end
37
+
38
+ def file_int_percentage
39
+ @file_int_percentage ||= percentage.to_i
40
+ end
41
+
42
+ private
43
+
44
+ def project_path
45
+ root_path = ""
46
+ return root_path unless Object.const_defined?('Rails')
47
+ return root_path unless Rails.respond_to?(:root)
48
+
49
+ Rails.root.to_s
50
+ rescue NameError
51
+ ""
52
+ end
53
+
54
+ def assign_attributes
55
+ @file_name, @line_number, @column, status_lines_count = @line.split(
56
+ SimpleCovLinterFormatter::LINE_SECTIONS_DIVIDER
57
+ )
58
+ @status, @lines_count, @percentage = status_lines_count.split(
59
+ SimpleCovLinterFormatter::MSG_DIVIDER
60
+ )
61
+ end
62
+ end
63
+ end
@@ -8,19 +8,31 @@ module SimpleCovLinterFormatter
8
8
 
9
9
  def format
10
10
  lines.map do |line|
11
- build_message(line)
11
+ build_line_text(line)
12
12
  end
13
13
  end
14
14
 
15
15
  private
16
16
 
17
- def build_message(line)
17
+ def build_line_text(line)
18
18
  [
19
19
  @source_file.filename,
20
20
  line.line_number,
21
21
  FILE_COLUMN,
22
- "#{line.status}-#{lines_count}"
23
- ].map(&:to_s).join(":")
22
+ build_line_msg(line)
23
+ ].map(&:to_s).join(SimpleCovLinterFormatter::LINE_SECTIONS_DIVIDER)
24
+ end
25
+
26
+ def build_line_msg(line)
27
+ [
28
+ line.status,
29
+ lines_count,
30
+ stats.percent
31
+ ].map(&:to_s).join(SimpleCovLinterFormatter::MSG_DIVIDER)
32
+ end
33
+
34
+ def stats
35
+ @stats ||= @source_file.coverage_statistics[:line]
24
36
  end
25
37
 
26
38
  def lines_count
@@ -19,10 +19,9 @@ module SimpleCovLinterFormatter
19
19
  result = {}
20
20
 
21
21
  @lines.each do |line|
22
- file_name, line_number, _column, status_lines_count = line.split(":")
23
- status, lines_count = status_lines_count.split("-")
24
- result[file_name] ||= { lines: [nil] * lines_count.to_i }
25
- result[file_name][:lines][line_number.to_i - 1] = status.to_sym == :missed ? 0 : nil
22
+ file = SimpleCovLinterFormatter::FileLine.new(line)
23
+ result[file.file_name] ||= { lines: [nil] * file.lines_count }
24
+ result[file.file_name][:lines][file.line_number_idx] = file.status == :missed ? 0 : nil
26
25
  end
27
26
 
28
27
  result
@@ -0,0 +1,127 @@
1
+ module SimpleCovLinterFormatter
2
+ class SummaryBuilder
3
+ PERCENT_TEXT_SIZE = 3
4
+
5
+ def initialize(lines)
6
+ @lines = lines
7
+ @largest_file_name = 0
8
+ @largest_percentage = 0
9
+ end
10
+
11
+ def build
12
+ body = build_body
13
+ return body if body == ""
14
+
15
+ "#{build_title}\n#{body}#{divider}"
16
+ end
17
+
18
+ private
19
+
20
+ def build_title
21
+ "SimpleCov Report - #{build_coverage_title}:\n#{divider}"
22
+ end
23
+
24
+ def divider
25
+ '-' * report_width
26
+ end
27
+
28
+ def report_width
29
+ @largest_file_name + @largest_percentage + PERCENT_TEXT_SIZE
30
+ end
31
+
32
+ def build_coverage_title
33
+ if SimpleCovLinterFormatter.cover_all?
34
+ return "Total Coverage"
35
+ end
36
+
37
+ "Own Changes"
38
+ end
39
+
40
+ def build_body
41
+ result = ""
42
+
43
+ files.each do |file|
44
+ result += "#{build_line_output(file)}\n"
45
+ end
46
+
47
+ result
48
+ end
49
+
50
+ def files
51
+ unique_files = []
52
+ added_files = {}
53
+
54
+ @lines.each do |line|
55
+ file = SimpleCovLinterFormatter::FileLine.new(line)
56
+ next if added_files[file.file_short_name]
57
+
58
+ unique_files << file
59
+ added_files[file.file_short_name] = true
60
+ file_size = file.file_short_name.size
61
+ file_percentage = file.file_int_percentage.to_s.size
62
+ @largest_file_name = file_size if file_size > @largest_file_name
63
+ @largest_percentage = file_percentage if file_percentage > @largest_percentage
64
+ end
65
+
66
+ sort_files(unique_files)
67
+ end
68
+
69
+ def sort_files(files)
70
+ sorting_strategy = if SimpleCovLinterFormatter.summary_coverage_sorting?
71
+ Proc.new { |file| [file.percentage, file.file_short_name] }
72
+ else
73
+ Proc.new { |file| file.file_short_name }
74
+ end
75
+ files.sort_by { |file| sorting_strategy.call(file) }
76
+ end
77
+
78
+ def build_line_output(file)
79
+ file_name = adjusted_file_name(file)
80
+ covered_size = @largest_file_name * file.percentage / 100.0
81
+ covered_text = colorize_text(
82
+ covered_size.zero? ? "" : file_name[0..(covered_size - 1)],
83
+ :summary_covered_bg_color
84
+ )
85
+ not_covered_text = colorize_text(
86
+ file_name[covered_size..-1],
87
+ :summary_not_covered_bg_color
88
+ )
89
+ "#{build_percentage_output(file)} #{covered_text}#{not_covered_text}"
90
+ end
91
+
92
+ def colorize_text(text, bg_option)
93
+ text = Rainbow(text).color(SimpleCovLinterFormatter.summary_text_color)
94
+ return text unless SimpleCovLinterFormatter.summary_enabled_bg
95
+
96
+ text.bg(SimpleCovLinterFormatter.send(bg_option))
97
+ end
98
+
99
+ def build_percentage_output(file)
100
+ percentage_size = file.file_int_percentage.to_s.size
101
+ diff = @largest_percentage - percentage_size
102
+ Rainbow("#{' ' * diff}#{file.file_int_percentage} %").send(
103
+ get_percetage_color(file.file_int_percentage)
104
+ )
105
+ end
106
+
107
+ def get_percetage_color(percentage)
108
+ case percentage
109
+ when 100
110
+ :green
111
+ when 0
112
+ :red
113
+ else
114
+ :yellow
115
+ end
116
+ end
117
+
118
+ def adjusted_file_name(file)
119
+ diff = @largest_file_name - file.file_short_name.size
120
+ file.file_short_name + (" " * diff)
121
+ end
122
+
123
+ def covered_size(file)
124
+ @largest_file_name * file.percentage / 100.0
125
+ end
126
+ end
127
+ end
@@ -5,24 +5,51 @@ module SimpleCovLinterFormatter
5
5
  end
6
6
 
7
7
  def filter
8
- file_content = filter_result
9
- format_result(file_content)
8
+ return [] if text_content == ""
9
+ return filter_with_reviewdog if reviewdog?
10
+
11
+ filter_with_git_status
10
12
  end
11
13
 
12
14
  private
13
15
 
14
- def filter_result
15
- return "" if text_content == ""
16
+ def reviewdog?
17
+ silence_stream($stdout) { !!system("reviewdog --version") }
18
+ end
19
+
20
+ def filter_with_reviewdog
21
+ `echo "#{text_content}" | reviewdog -efm="#{efm_param}" -diff="git diff"`.to_s.split("\n")
22
+ end
23
+
24
+ def efm_param
25
+ %w{%f %l %c %m}.join(SimpleCovLinterFormatter::LINE_SECTIONS_DIVIDER)
26
+ end
27
+
28
+ def filter_with_git_status
29
+ status_files = status_to_lines(`git status --porcelain`)
30
+ regexp = /#{status_files.join('|')}/
31
+ @text_lines.grep(regexp)
32
+ end
16
33
 
17
- `echo "#{text_content}" | reviewdog -efm="%f:%l:%c:%m" -diff="git diff"`
34
+ def status_to_lines(status)
35
+ status.split("\n").map do |change|
36
+ file = change.split(" ").last
37
+ file.end_with?("/") ? nil : file
38
+ end.compact
18
39
  end
19
40
 
20
41
  def text_content
21
- @text_content ||= @text_lines.join('\n')
42
+ @text_content ||= @text_lines.join("\n")
22
43
  end
23
44
 
24
- def format_result(file_content)
25
- file_content.to_s.split("\n")
45
+ def silence_stream(stream)
46
+ old_stream = stream.dup
47
+ stream.reopen(File::NULL)
48
+ stream.sync = true
49
+ yield
50
+ ensure
51
+ stream.reopen(old_stream)
52
+ old_stream.close
26
53
  end
27
54
  end
28
55
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleCovLinterFormatter
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,35 +1,89 @@
1
+ require 'rainbow'
2
+
1
3
  require 'simplecov_linter_formatter/version'
4
+ require 'simplecov_linter_formatter/file_line'
2
5
  require 'simplecov_linter_formatter/formatters/result_formatter'
3
6
  require 'simplecov_linter_formatter/formatters/source_file_formatter'
4
7
  require 'simplecov_linter_formatter/formatters/text_lines_formatter'
5
8
  require 'simplecov_linter_formatter/exporters/json_result_exporter'
6
9
  require 'simplecov_linter_formatter/text_lines_filter'
10
+ require 'simplecov_linter_formatter/summary_builder'
7
11
 
8
12
  module SimpleCovLinterFormatter
13
+ extend self
14
+
9
15
  SCOPES = [:all, :own_changes]
16
+ SORTING_MODES = [:coverage, :alphabet]
17
+ MSG_DIVIDER = "-"
18
+ LINE_SECTIONS_DIVIDER = ":"
10
19
 
11
- def self.json_filename=(value)
12
- @json_filename = value
13
- end
20
+ attr_writer(
21
+ :json_filename,
22
+ :summary_covered_bg_color,
23
+ :summary_not_covered_bg_color,
24
+ :summary_text_color,
25
+ :summary_enabled_bg,
26
+ :summary_enabled
27
+ )
14
28
 
15
- def self.json_filename
29
+ def json_filename
16
30
  @json_filename || 'coverage.linter.json'
17
31
  end
18
32
 
19
- def self.cover_all?
33
+ def scope=(value)
34
+ if !SCOPES.include?(value.to_sym)
35
+ raise "Invalid scope. Must be one of: #{SCOPES.map(&:to_s).join(', ')}"
36
+ end
37
+
38
+ @scope = value
39
+ end
40
+
41
+ def scope
42
+ (@scope || :all).to_sym
43
+ end
44
+
45
+ def cover_all?
20
46
  scope == :all
21
47
  end
22
48
 
23
- def self.scope=(value)
24
- if !SCOPES.include?(value)
25
- raise "Invalid scope. Must be one of: #{SCOPES.map(&:to_s).join('', '')}"
49
+ def summary_enabled
50
+ !!@summary_enabled
51
+ end
52
+
53
+ def summary_files_sorting=(value)
54
+ if !SORTING_MODES.include?(value.to_sym)
55
+ raise "Invalid summary_files_sorting. Must be one of: #{SORTING_MODES.map(&:to_s).join(', ')}"
26
56
  end
27
57
 
28
- @scope = value
58
+ @summary_files_sorting = value
59
+ end
60
+
61
+ def summary_files_sorting
62
+ (@summary_files_sorting || :coverage).to_sym
63
+ end
64
+
65
+ def summary_coverage_sorting?
66
+ summary_files_sorting == :coverage
67
+ end
68
+
69
+ def summary_enabled_bg
70
+ !!@summary_enabled_bg
71
+ end
72
+
73
+ def summary_covered_bg_color
74
+ (@summary_covered_bg_color || :darkgreen).to_sym
29
75
  end
30
76
 
31
- def self.scope
32
- @scope || :all
77
+ def summary_not_covered_bg_color
78
+ (@summary_not_covered_bg_color || :firebrick).to_sym
79
+ end
80
+
81
+ def summary_text_color
82
+ (@summary_text_color || :white).to_sym
83
+ end
84
+
85
+ def setup
86
+ yield self
33
87
  end
34
88
  end
35
89
 
@@ -38,6 +92,7 @@ module SimpleCov
38
92
  class LinterFormatter
39
93
  def format(simplecov_result)
40
94
  text_lines = get_text_lines(simplecov_result)
95
+ show_coverage_summary(text_lines)
41
96
  hash_result = format_text_lines(simplecov_result.command_name, text_lines)
42
97
  export_to_json(hash_result)
43
98
  nil
@@ -52,6 +107,12 @@ module SimpleCov
52
107
  filter_text_lines(text_lines)
53
108
  end
54
109
 
110
+ def show_coverage_summary(text_lines)
111
+ return unless SimpleCovLinterFormatter.summary_enabled
112
+
113
+ puts(SimpleCovLinterFormatter::SummaryBuilder.new(text_lines).build)
114
+ end
115
+
55
116
  def filter_text_lines(text_lines)
56
117
  SimpleCovLinterFormatter::TextLinesFilter.new(text_lines).filter
57
118
  end
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.add_dependency "rainbow"
21
+
20
22
  spec.add_development_dependency "bundler", "~> 2.2.15"
21
23
  spec.add_development_dependency "guard-rspec"
22
24
  spec.add_development_dependency "pry"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simplecov_linter_formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Platanus
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-09-27 00:00:00.000000000 Z
12
+ date: 2021-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rainbow
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: bundler
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -162,14 +176,22 @@ files:
162
176
  - Rakefile
163
177
  - bin/console
164
178
  - bin/setup
179
+ - docs/assets/all-summary.png
180
+ - docs/assets/colors-summary.png
165
181
  - docs/assets/covered.png
182
+ - docs/assets/no-bg-summary.png
166
183
  - docs/assets/not-covered.png
184
+ - docs/assets/own-changes-summary.png
167
185
  - docs/assets/partial-cov.png
186
+ - docs/assets/report-example.png
187
+ - docs/assets/sorted-summary.png
168
188
  - lib/simplecov_linter_formatter.rb
169
189
  - lib/simplecov_linter_formatter/exporters/json_result_exporter.rb
190
+ - lib/simplecov_linter_formatter/file_line.rb
170
191
  - lib/simplecov_linter_formatter/formatters/result_formatter.rb
171
192
  - lib/simplecov_linter_formatter/formatters/source_file_formatter.rb
172
193
  - lib/simplecov_linter_formatter/formatters/text_lines_formatter.rb
194
+ - lib/simplecov_linter_formatter/summary_builder.rb
173
195
  - lib/simplecov_linter_formatter/text_lines_filter.rb
174
196
  - lib/simplecov_linter_formatter/version.rb
175
197
  - simplecov_linter_formatter.gemspec