solargraph_test_coverage 0.2.4 → 0.2.5

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: afacac1a6d557ea7ef39c86081fc7f3aafcb7e09c3a8243679e9d252ba47a2c7
4
- data.tar.gz: 9e929da5ff5873ef3c044edebb4a96575cb47f4bfb9b2d36121082257ac03569
3
+ metadata.gz: c76dedeaddccb806778b5846c3587233919f1d78088edde15bb7b61681013896
4
+ data.tar.gz: 387c79384703dd5e92dddf31995982539a233094c7b985ad2977ff1265b2c16c
5
5
  SHA512:
6
- metadata.gz: 58b77e64736847a4d5d6fedb3c67f7b76e6af6056e844926356269c052b8bfe5f29af0c1f76e916f2e26d1ddb5c5628d3d324f53c890ceeff55f289959409b8c
7
- data.tar.gz: 92e5f351f941d99103339f80fb05450e1393cb5929f584cd7d080759450f9cd31422a71d51ba847664b1217b88c761f1f132f346f280106580c8c806ba1c6bd9
6
+ metadata.gz: 8d80b6d4abe2d40414c5dbc84652c1c4161a5b1d439b79e232414a1cbfbab1f27c51cf11e4d00a940309a01d5813ef59b4d88e57374ba1ce8ef81725b56b0c6a
7
+ data.tar.gz: 8bb2180c520a7b8b1c9dcecb191b68fc3c4be7c68c65cd2b4b5bc1ec6f8a40102f069cba5d0e4edebdd28753631657a4f50eb3886b6cbc1bde74c5cee293f70b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- solargraph_test_coverage (0.2.3)
4
+ solargraph_test_coverage (0.2.4)
5
5
  solargraph (~> 0.40, > 0.40)
6
6
 
7
7
  GEM
@@ -3,22 +3,15 @@
3
3
  module SolargraphTestCoverage
4
4
  # Adapted from SimpleCov - Small class that turns branch coverage data into something easier to work with
5
5
  class Branch
6
- class << self
7
- #
8
- # Builds an array of Branch objects for every branch in results hash.
9
- #
10
- # @return [Array]
11
- #
12
- def build_from(results)
13
- results.fetch(:branches, {}).flat_map do |condition, branches|
14
- _condition_type, _condition_id, condition_start_line, * = condition
6
+ def self.build_from(results)
7
+ results.fetch(:branches, {}).flat_map do |condition, branches|
8
+ _condition_type, _condition_id, condition_start_line, * = condition
15
9
 
16
- branches.map do |branch_data, hit_count|
17
- type, _id, start_line, _start_col, end_line, _end_col = branch_data
10
+ branches.map do |branch_data, hit_count|
11
+ type, _id, start_line, _start_col, end_line, _end_col = branch_data
18
12
 
19
- new(start_line: start_line, end_line: end_line, coverage: hit_count,
20
- inline: start_line == condition_start_line, type: type)
21
- end
13
+ new(start_line: start_line, end_line: end_line, coverage: hit_count,
14
+ inline: start_line == condition_start_line, type: type)
22
15
  end
23
16
  end
24
17
  end
@@ -33,44 +26,18 @@ module SolargraphTestCoverage
33
26
  @type = type
34
27
  end
35
28
 
36
- #
37
- # Predicate method for @inline instance variable
38
- #
39
- # @return [Boolean]
40
- #
41
29
  def inline?
42
30
  @inline
43
31
  end
44
32
 
45
- #
46
- # Return true if there is relevant count defined > 0
47
- #
48
- # @return [Boolean]
49
- #
50
33
  def covered?
51
34
  coverage.positive?
52
35
  end
53
36
 
54
- #
55
- # The line on which we want to report the coverage
56
- #
57
- # Usually we choose the line above the start of the branch (so that it shows up
58
- # at if/else) because that
59
- # * highlights the condition
60
- # * makes it distinguishable if the first line of the branch is an inline branch
61
- # (see the nested_branches fixture)
62
- #
63
- # @return [Integer]
64
- #
65
37
  def report_line
66
38
  inline? ? start_line : start_line - 1
67
39
  end
68
40
 
69
- #
70
- # Return array with coverage count and badge
71
- #
72
- # @return [Hash]
73
- #
74
41
  def report
75
42
  { type: type, line: report_line }
76
43
  end
@@ -1,82 +1,124 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # frozen_string_literal = true
4
-
5
3
  module SolargraphTestCoverage
6
- class Config
7
- class << self
8
- DEFAULTS = {
9
- 'preload_rails' => true, # can be true or false - performance optimization
10
- 'test_framework' => 'rspec', # can be 'rspec' or 'minitest'
11
- 'coverage' => [ # All diagnostics are enabled by default
12
- 'line', # Specifying an array with fewer diagnostics will overwrite this
13
- 'branch',
14
- 'test_failing',
15
- 'test_missing'
16
- ],
17
- 'exclude_paths' => [ # don't attempt to find/run a spec for files that match these paths
18
- 'app/controller',
19
- 'concerns'
20
- ]
21
- }.freeze
22
-
23
- def preload_rails?
24
- plugin_config['preload_rails']
25
- end
4
+ module Config
5
+ extend self
26
6
 
27
- def exclude_paths
28
- plugin_config['exclude_paths']
29
- end
7
+ DEFAULTS = {
8
+ 'preload_rails' => true, # can be true or false - performance optimization
9
+ 'test_framework' => 'rspec', # can be 'rspec' or 'minitest'
10
+ 'coverage' => [ # All diagnostics are enabled by default
11
+ 'line', # Specifying an array with fewer diagnostics will overwrite this
12
+ 'branch',
13
+ 'test_failing',
14
+ 'test_missing'
15
+ ],
16
+ 'exclude_paths' => [ # don't attempt to find/run a spec for files that match these paths
17
+ 'app/controller',
18
+ 'concerns'
19
+ ]
20
+ }.freeze
30
21
 
31
- def line_coverage?
32
- plugin_config['coverage'].include? 'line'
33
- end
22
+ def preload_rails?
23
+ plugin_config['preload_rails']
24
+ end
34
25
 
35
- def branch_coverage?
36
- plugin_config['coverage'].include? 'branch'
37
- end
26
+ def exclude_paths
27
+ plugin_config['exclude_paths']
28
+ end
38
29
 
39
- def test_failing_coverage?
40
- plugin_config['coverage'].include? 'test_failing'
41
- end
30
+ def line_coverage?
31
+ plugin_config['coverage'].include? 'line'
32
+ end
42
33
 
43
- def test_missing_coverage?
44
- plugin_config['coverage'].include? 'test_missing'
45
- end
34
+ def branch_coverage?
35
+ plugin_config['coverage'].include? 'branch'
36
+ end
37
+
38
+ def test_failing_coverage?
39
+ plugin_config['coverage'].include? 'test_failing'
40
+ end
41
+
42
+ def test_missing_coverage?
43
+ plugin_config['coverage'].include? 'test_missing'
44
+ end
46
45
 
47
- def test_framework
48
- plugin_config['test_framework']
46
+ def test_framework
47
+ plugin_config['test_framework']
48
+ end
49
+
50
+ def test_dir
51
+ case test_framework
52
+ when 'rspec'
53
+ 'spec'
54
+ when 'minitest'
55
+ 'test'
49
56
  end
57
+ end
50
58
 
51
- def test_dir
52
- case test_framework
53
- when 'rspec'
54
- 'spec'
55
- when 'minitest'
56
- 'test'
57
- end
59
+ def test_file_suffix
60
+ case test_framework
61
+ when 'rspec'
62
+ '_spec.rb'
63
+ when 'minitest'
64
+ '_test.rb'
58
65
  end
66
+ end
59
67
 
60
- def test_file_suffix
61
- case test_framework
62
- when 'rspec'
63
- '_spec.rb'
64
- when 'minitest'
65
- '_test.rb'
66
- end
68
+ def require_testing_framework!
69
+ case test_framework
70
+ when 'rspec'
71
+ require 'rspec/core'
72
+ when 'minitest'
73
+ require 'minitest/autorun'
74
+ else
75
+ raise UnknownTestingGem
67
76
  end
77
+ end
68
78
 
69
- private
79
+ # This gives us a nice speed-boost when running test in child process
80
+ #
81
+ # We rescue the LoadError since Solargraph would catch it otherwise,
82
+ # and not load the plugin at all.
83
+ #
84
+ # Adding the spec/ directory to the $LOAD_PATH lets 'require "spec_helper"'
85
+ # commonly found in rails_helper work.
86
+ #
87
+ # If Coverage was started in Rails/Spec helper by SimpleCov,
88
+ # calling Coverage.result after requiring stops and resets it.
89
+ #
90
+ # This is a bit experimental
91
+ #
92
+ def preload_rails!
93
+ return if defined?(Rails) || !File.file?('spec/rails_helper.rb')
70
94
 
71
- def plugin_config
72
- @plugin_config ||= workspace_config.tap do |config|
73
- DEFAULTS.each_key { |key| config[key] = DEFAULTS[key] unless config.key?(key) }
74
- end
75
- end
95
+ $LOAD_PATH.unshift(test_path) unless $LOAD_PATH.include?(test_path)
96
+
97
+ require File.join(test_path, 'rails_helper')
98
+ Coverage.result(stop: true, clear: true) if Coverage.running?
99
+
100
+ true
101
+ rescue LoadError => e
102
+ Solargraph::Logging.logger.warn "LoadError when trying to require 'rails_helper'"
103
+ Solargraph::Logging.logger.warn "[#{e.class}] #{e.message}"
76
104
 
77
- def workspace_config
78
- Solargraph::Workspace::Config.new(Dir.pwd).raw_data.fetch('test_coverage', {})
105
+ false
106
+ end
107
+
108
+ private
109
+
110
+ def plugin_config
111
+ @plugin_config ||= workspace_config.tap do |config|
112
+ DEFAULTS.each_key { |key| config[key] = DEFAULTS[key] unless config.key?(key) }
79
113
  end
80
114
  end
115
+
116
+ def workspace_config
117
+ Solargraph::Workspace::Config.new(Dir.pwd).raw_data.fetch('test_coverage', {})
118
+ end
119
+
120
+ def test_path
121
+ ReporterHelpers.test_path
122
+ end
81
123
  end
82
124
  end
@@ -5,12 +5,9 @@ module SolargraphTestCoverage
5
5
  # When called with a block, runs the content of said block in a new (forked) process
6
6
  # the return value of the process/block can be captured and used in parent process
7
7
  class ForkProcess
8
- #
9
8
  # Executes block in forked process, and captures returned value of that block
10
9
  # Returns result of block
11
10
  #
12
- # @return [Object]
13
- #
14
11
  def self.run
15
12
  read, write = IO.pipe
16
13
 
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolargraphTestCoverage
4
+ # Some helper functions for the diagnostics
5
+ module ReporterHelpers
6
+ def exclude_file?(source_filename)
7
+ return true if source_filename.start_with? test_path
8
+
9
+ Config.exclude_paths.any? { |path| source_filename.sub(Dir.pwd, '').include? path }
10
+ end
11
+
12
+ def test_file(source)
13
+ relative_filepath = source.location.filename.sub(Dir.pwd, '').split('/').reject(&:empty?)
14
+ relative_filepath[0] = Config.test_dir
15
+
16
+ File.join(Dir.pwd, relative_filepath.join('/')).sub('.rb', Config.test_file_suffix)
17
+ end
18
+
19
+ # @return [Hash]
20
+ def run_test(source)
21
+ ForkProcess.run do
22
+ Coverage.start(lines: true, branches: true)
23
+ runner = TestRunner.with(test_file(source)).run!
24
+ Coverage.result.fetch(source.location.filename, {}).merge({ test_status: runner.passed? })
25
+ end
26
+ end
27
+
28
+ def messages(source, results)
29
+ messages = [
30
+ line_warnings(source, results),
31
+ branch_warnings(source, results),
32
+ test_passing_error(source, results)
33
+ ]
34
+
35
+ messages.flatten.compact
36
+ end
37
+
38
+ def line_warnings(source, results)
39
+ uncovered_lines(results).map { |line| line_coverage_warning(source, line) }
40
+ end
41
+
42
+ def branch_warnings(source, results)
43
+ uncovered_branches(results).map { |branch| branch_coverage_warning(source, branch.report) }
44
+ end
45
+
46
+ def test_passing_error(source, results)
47
+ results[:test_status] ? [] : [test_failing_error(source)]
48
+ end
49
+
50
+ # Adapted from SingleCov
51
+ # Coverage returns nil for untestable lines (like 'do', 'end', 'if' keywords)
52
+ # otherwise returns int showing how many times a line was called
53
+ #
54
+ # [nil, 1, 0, 1, 0] -> [3, 5]
55
+ # Returns array of line numbers with 0 coverage
56
+ def uncovered_lines(results)
57
+ return [] unless results[:lines]
58
+
59
+ results[:lines].each_with_index
60
+ .select { |c, _| c&.zero? }
61
+ .map { |_, i| i }
62
+ .compact
63
+ end
64
+
65
+ def uncovered_branches(results)
66
+ Branch.build_from(results).reject(&:covered?)
67
+ end
68
+
69
+ def range(start_line, start_column, end_line, end_column)
70
+ Solargraph::Range.from_to(start_line, start_column, end_line, end_column).to_hash
71
+ end
72
+
73
+ def self.test_path
74
+ File.join(Dir.pwd, Config.test_dir)
75
+ end
76
+
77
+ def test_path
78
+ ReporterHelpers.test_path
79
+ end
80
+ end
81
+ end
@@ -3,11 +3,8 @@
3
3
  # test_coverage reporter for Solargraph
4
4
  module SolargraphTestCoverage
5
5
  class TestCoverageReporter < Solargraph::Diagnostics::Base
6
- include Helpers
6
+ include ReporterHelpers
7
7
 
8
- # LSP Diagnostic method
9
- # @return [Array]
10
- #
11
8
  def diagnose(source, _api_map)
12
9
  return [] if source.code.empty? || exclude_file?(source.location.filename)
13
10
  return [test_missing_error(source)] unless File.file?(test_file(source))
@@ -20,43 +17,6 @@ module SolargraphTestCoverage
20
17
 
21
18
  private
22
19
 
23
- # Compiles all diagnostic messages for source file
24
- # @return [Array]
25
- #
26
- def messages(source, results)
27
- messages = [
28
- line_warnings(source, results),
29
- branch_warnings(source, results),
30
- test_passing_error(source, results)
31
- ]
32
-
33
- messages.flatten.compact
34
- end
35
-
36
- # Creates array of warnings for uncovered lines
37
- # @return [Array]
38
- #
39
- def line_warnings(source, results)
40
- uncovered_lines(results).map { |line| line_coverage_warning(source, line) }
41
- end
42
-
43
- # Creates array of warnings for uncovered branches
44
- # @return [Array]
45
- #
46
- def branch_warnings(source, results)
47
- uncovered_branches(results).map { |branch| branch_coverage_warning(source, branch.report) }
48
- end
49
-
50
- # Creates array containing error for failing spec
51
- # @return [Array]
52
- #
53
- def test_passing_error(source, results)
54
- results[:test_status] ? [] : [test_failing_error(source)]
55
- end
56
-
57
- # Creates LSP warning message for missing line coverage
58
- # @return [Hash]
59
- #
60
20
  def line_coverage_warning(source, line)
61
21
  return unless Config.line_coverage?
62
22
 
@@ -68,11 +28,6 @@ module SolargraphTestCoverage
68
28
  }
69
29
  end
70
30
 
71
- # Creates LSP warning message for missing branch coverage
72
- # Line numbers are off by 1, since Branch Coverage starts counting at 1, not 0
73
- #
74
- # @return [Hash]
75
- #
76
31
  def branch_coverage_warning(source, report)
77
32
  return unless Config.branch_coverage?
78
33
 
@@ -84,9 +39,6 @@ module SolargraphTestCoverage
84
39
  }
85
40
  end
86
41
 
87
- # Creates LSP error message if test file is failing
88
- # @return [Hash]
89
- #
90
42
  def test_failing_error(source)
91
43
  return unless Config.test_failing_coverage?
92
44
 
@@ -98,19 +50,14 @@ module SolargraphTestCoverage
98
50
  }
99
51
  end
100
52
 
101
- #
102
- # Creates LSP error message if no test file can be found
103
- #
104
- # @return [Hash]
105
- #
106
53
  def test_missing_error(source)
107
54
  return unless Config.test_missing_coverage?
108
55
 
109
56
  {
110
57
  range: range(0, 0, 0, source.code.lines[0].length),
111
- severity: Solargraph::Diagnostics::Severities::ERROR,
58
+ severity: Solargraph::Diagnostics::Severities::HINT,
112
59
  source: 'TestCoverage',
113
- message: "No unit test file found at #{test_file(source)}"
60
+ message: "No test file found at '#{test_file(source).sub("#{Dir.pwd}/", '')}'"
114
61
  }
115
62
  end
116
63
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolargraphTestCoverage
4
- VERSION = '0.2.4'
4
+ VERSION = '0.2.5'
5
5
  end
@@ -3,7 +3,7 @@
3
3
  require 'solargraph_test_coverage/version'
4
4
  require 'solargraph_test_coverage/branch'
5
5
  require 'solargraph_test_coverage/fork_process'
6
- require 'solargraph_test_coverage/helpers'
6
+ require 'solargraph_test_coverage/reporter_helpers'
7
7
  require 'solargraph_test_coverage/config'
8
8
  require 'solargraph_test_coverage/test_runner'
9
9
  require 'solargraph_test_coverage/test_coverage_reporter'
@@ -16,8 +16,8 @@ module SolargraphTestCoverage
16
16
 
17
17
  class UnknownTestingGem < StandardError; end
18
18
 
19
- Helpers.require_testing_framework!
20
- Helpers.preload_rails! if Config.preload_rails?
19
+ Config.require_testing_framework!
20
+ Config.preload_rails! if Config.preload_rails?
21
21
 
22
22
  Solargraph::Diagnostics.register 'test_coverage', TestCoverageReporter
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph_test_coverage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Kolkey
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-03 00:00:00.000000000 Z
11
+ date: 2021-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solargraph
@@ -48,7 +48,7 @@ files:
48
48
  - lib/solargraph_test_coverage/branch.rb
49
49
  - lib/solargraph_test_coverage/config.rb
50
50
  - lib/solargraph_test_coverage/fork_process.rb
51
- - lib/solargraph_test_coverage/helpers.rb
51
+ - lib/solargraph_test_coverage/reporter_helpers.rb
52
52
  - lib/solargraph_test_coverage/test_coverage_reporter.rb
53
53
  - lib/solargraph_test_coverage/test_runner.rb
54
54
  - lib/solargraph_test_coverage/version.rb
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SolargraphTestCoverage
4
- # Some helper functions for the diagnostics
5
- module Helpers
6
- # @return [Boolean]
7
- def exclude_file?(source_filename)
8
- return true if source_filename.start_with? Helpers.test_path
9
-
10
- Config.exclude_paths.each { |path| return true if source_filename.sub(Dir.pwd, '').include? path }
11
-
12
- false
13
- end
14
-
15
- # @return [String]
16
- def test_file(source)
17
- relative_filepath = source.location.filename.sub(Dir.pwd, '').split('/').reject(&:empty?)
18
- relative_filepath[0] = Config.test_dir
19
-
20
- File.join(Dir.pwd, relative_filepath.join('/'))
21
- .sub('.rb', Config.test_file_suffix)
22
- end
23
-
24
- # @return [Hash]
25
- def run_test(source)
26
- ForkProcess.run do
27
- Coverage.start(lines: true, branches: true)
28
- runner = TestRunner.with(test_file(source)).run!
29
- Coverage.result.fetch(source.location.filename, {}).merge({ test_status: runner.passed? })
30
- end
31
- end
32
-
33
- # Adapted from SingleCov
34
- # Coverage returns nil for untestable lines (like do, end, if keywords)
35
- # otherwise returns int showing how many times a line was called
36
- #
37
- # [nil, 1, 0, 1, 0] -> [3, 5]
38
- #
39
- # @return [Array]
40
- #
41
- def uncovered_lines(results)
42
- return [] unless results[:lines]
43
-
44
- results[:lines].each_with_index
45
- .select { |c, _| c&.zero? }
46
- .map { |_, i| i }
47
- .compact
48
- end
49
-
50
- # @return [Array]
51
- def uncovered_branches(results)
52
- Branch.build_from(results).reject(&:covered?)
53
- end
54
-
55
- # @return [Hash]
56
- def range(start_line, start_column, end_line, end_column)
57
- Solargraph::Range.from_to(start_line, start_column, end_line, end_column).to_hash
58
- end
59
-
60
- def self.require_testing_framework!
61
- case Config.test_framework
62
- when 'rspec'
63
- require 'rspec/core'
64
- when 'minitest'
65
- require 'minitest/autorun'
66
- else
67
- raise UnknownTestingGem
68
- end
69
- end
70
-
71
- # Only called once, when gem is loaded
72
- # Preloads rails via spec/rails_helper if Rails isn't already defined
73
- # This gives us a nice speed-boost when running test in child process
74
- #
75
- # We rescue the LoadError since Solargraph would catch it otherwise,
76
- # and not load the plugin at all.
77
- #
78
- # Adding the spec/ directory to the $LOAD_PATH lets 'require "spec_helper"'
79
- # commonly found in rails_helper work.
80
- #
81
- # If Coverage was started in Rails/Spec helper by SimpleCov,
82
- # calling Coverage.result after requiring stops and resets it.
83
- #
84
- # This is a bit experimental - I'm not sure if there will be downstream side-effects
85
- #
86
- # @return [Boolean]
87
- #
88
- def self.preload_rails!
89
- return if defined?(Rails) || !File.file?('spec/rails_helper.rb')
90
-
91
- $LOAD_PATH.unshift(test_path) unless $LOAD_PATH.include?(test_path)
92
-
93
- require File.join(test_path, 'rails_helper')
94
- Coverage.result(stop: true, clear: true) if Coverage.running?
95
-
96
- true
97
- rescue LoadError => e
98
- Solargraph::Logging.logger.warn "LoadError when trying to require 'rails_helper'"
99
- Solargraph::Logging.logger.warn "[#{e.class}] #{e.message}"
100
-
101
- false
102
- end
103
-
104
- # @return [String]
105
- def self.test_path
106
- File.join(Dir.pwd, Config.test_dir)
107
- end
108
- end
109
- end