oneshot_coverage 0.3.0 → 0.4.1

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: 2b39908101b69a0d652f8219df289b541f44dd763586f938f714da7990aa801e
4
- data.tar.gz: 9f71dd33954f1cc1e8e88f46a71cd99800f41afea57197851a9d4e46a9c98c49
3
+ metadata.gz: 074f86971202b3cb656203277d3032b669b36bd62fe6938633e57b0c50e6a151
4
+ data.tar.gz: 0c8660a5997eba0e6bb17b8b2c444bae52100c5bff099c90246637e9a9fb005d
5
5
  SHA512:
6
- metadata.gz: cf5c1b77da9e902783c2d62b65fb20827b78e7601cf9322ee0ac2802444d08db108a793634ae50a4891e1bf5809acb9203cd22fe7ad29351717f8f92787be56d
7
- data.tar.gz: 9bad05fb306ccdf11c4ef94e8838f2eb63d24f69444c614439d578a812f2fd8decea5d8e3882256750c17fe8ec9b07f3539385d1c6bb89b01488449f27933a52
6
+ metadata.gz: 6ce75ffbfe041e4f86b5e685fd0e7b8c2c5b58e7ece2095fc526243d129ec20d09a3c875e1a33cd5b779e10cf8b770ba936ae563c5cb3cc26b540d63bada3636
7
+ data.tar.gz: 977016fc11910a04de1d690a23bd6bb44a6bcf4e74ef2384b1d1aca01c1da784c95f8f97973781e52c142e4a27868bc6b431dd5495a3876521bb056556c33074
@@ -0,0 +1,19 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ ruby: [ '2.6', '2.7', '3.0' ]
11
+ name: Test on Ruby ${{ matrix.ruby }}
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: ${{ matrix.ruby }}
17
+ bundler-cache: true
18
+ - name: Execute test
19
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -41,6 +41,7 @@ Temporary Items
41
41
  /test/tmp/
42
42
  /test/version_tmp/
43
43
  /tmp/
44
+ Gemfile.lock
44
45
 
45
46
  # Used by dotenv library to load environment variables.
46
47
  # .env
@@ -93,3 +94,6 @@ build-iPhoneSimulator/
93
94
  /pkg/
94
95
  /spec/reports/
95
96
  /tmp/
97
+
98
+ target_app/coverage.json
99
+ target_app/coverage/
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## 0.4.1
2
+
3
+ - Add SimplecovReporter
4
+
5
+ ## 0.4.0
6
+
7
+ - Provide options for checking bundle_path (#7)
8
+ - Fix error when empty log file is exist (#4)
data/Gemfile CHANGED
@@ -4,3 +4,8 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in oneshot_coverage.gemspec
6
6
  gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+ gem "bundler", "> 1.17"
10
+
11
+ gem "minitest", "~> 5.0"
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # OneshotCoverage
2
2
 
3
- This gem may not be very useful when you want to use [Coverage onetshot mode](https://bugs.ruby-lang.org/issues/15022),
3
+ This gem may not be very useful when you want to use [Coverage oneshot mode](https://bugs.ruby-lang.org/issues/15022),
4
4
  however, It could be good example to study how to implement by yourself.
5
5
 
6
6
  This gem provides simple tools to use oneshot mode easier. It gives you:
@@ -9,7 +9,7 @@ This gem provides simple tools to use oneshot mode easier. It gives you:
9
9
  - Pluggable logger interface
10
10
 
11
11
  Please notice that it records code executions under the target path(usually, project base path).
12
- If you have bundle gem path under target path, It will be ignored automatically.
12
+ If you have bundle gem path under target path, It will be ignored by default.
13
13
 
14
14
  ## Installation
15
15
 
@@ -36,6 +36,7 @@ OneshotCoverage.configure(
36
36
  target_path: '/base/project/path',
37
37
  logger: OneshotCoverage::Logger::NullLogger.new,
38
38
  emit_term: nil, # emit per `emit_term` seconds. It tries to emit per request when `nil`.
39
+ cover_bundle_path: false, # record bundle gem path. Default value is false.
39
40
  )
40
41
  OneshotCoverage.start
41
42
  ```
@@ -98,6 +99,28 @@ to emit via `at_exit`.
98
99
  On the other hand, it's not, then you need to emit it manually
99
100
  at proper timing(i.e. when batch finished)
100
101
 
102
+ ### Generate report with simplecov
103
+
104
+ You can generate pretty report using simplecov(confirmed with 0.21.2). Here is some example:
105
+
106
+ ```ruby
107
+ require 'simplecov'
108
+ require 'oneshot_coverage/simplecov_reporter'
109
+
110
+ OneshotCoverage::SimplecovReporter.new(
111
+ project_path: Dir.pwd, # target project path. Dir.pwd is default.
112
+ log_path: 'coverage.json', # oneshot coverage log generated by FileLogger or same scheme json file acceptable
113
+ file_filter: OneshotCoverage::SimplecovReporter::DefaultFilter # Object respond to #call with return true | false. this filter used for coverage target. file_filter.call(path) return false, then path will not be included to report. DefaultFilter is default, which exclude non-ruby file, files under /spec/, /test/, /script/, /config/
114
+ ).run
115
+ ```
116
+
117
+ This code generates html report under 'project_path/`coverage/`'
118
+
119
+ ### Note
120
+
121
+ Note that `cover_bundle_path` only cover managed gem by bundler.
122
+ In the other words, the gem installed with `path` option, which bundler just load it, will not be included by this.
123
+
101
124
  ## License
102
125
 
103
126
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,2 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
- task :default => :spec
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task default: %i[test]
@@ -22,7 +22,14 @@ module OneshotCoverage
22
22
  OneshotLog = Struct.new(:path, :md5_hash, :lines)
23
23
 
24
24
  class Reporter
25
- def initialize(target_path:, logger:, emit_term: nil)
25
+ def initialize(
26
+ coverage_module:,
27
+ target_path:,
28
+ logger:,
29
+ emit_term: nil,
30
+ cover_bundle_path: false
31
+ )
32
+ @coverage_module = coverage_module
26
33
  @target_path = target_path
27
34
  @logger = logger
28
35
  @emit_term = emit_term
@@ -32,24 +39,28 @@ module OneshotCoverage
32
39
 
33
40
  if defined?(Bundler)
34
41
  @bundler_path = Bundler.bundle_path.to_s
42
+ @cover_bundle_path = cover_bundle_path
35
43
  end
36
44
  end
37
45
 
38
46
  def emit(force_emit)
39
47
  if !force_emit
40
48
  if !time_to_emit?
41
- return true
49
+ return
42
50
  end
43
51
  end
44
52
 
45
53
  logs =
46
- Coverage.result(clear: true, stop: false).
54
+ @coverage_module.result(clear: true, stop: false).
47
55
  select { |k, v| is_target?(k, v) }.
48
56
  map do |filepath, v|
49
- OneshotLog.new(relative_path(filepath), md5_hash_for(filepath), v[:oneshot_lines])
57
+ formatted_path = format_filepath(filepath)
58
+ OneshotLog.new(format_filepath(filepath), md5_hash_for(filepath), v[:oneshot_lines])
50
59
  end
51
60
 
52
- @logger.post(logs)
61
+ if logs.size > 0
62
+ @logger.post(logs)
63
+ end
53
64
  end
54
65
 
55
66
  private
@@ -67,13 +78,29 @@ module OneshotCoverage
67
78
 
68
79
  def is_target?(filepath, value)
69
80
  return false if value[:oneshot_lines].empty?
81
+ return @cover_bundle_path if from_bundler?(filepath)
70
82
  return false if !filepath.start_with?(@target_path)
71
- return false if @bundler_path && filepath.start_with?(@bundler_path)
72
83
  true
73
84
  end
74
85
 
86
+ def from_bundler?(filepath)
87
+ @bundler_path && filepath.start_with?(@bundler_path)
88
+ end
89
+
90
+ def format_filepath(filepath)
91
+ if from_bundler?(filepath)
92
+ filepath
93
+ else
94
+ relative_path(filepath)
95
+ end
96
+ end
97
+
75
98
  def relative_path(filepath)
76
- filepath[@target_path.size..-1]
99
+ if filepath.include?(@target_path)
100
+ filepath[@target_path.size..-1]
101
+ else
102
+ filepath
103
+ end
77
104
  end
78
105
 
79
106
  def md5_hash_cache
@@ -104,17 +131,19 @@ module OneshotCoverage
104
131
  @reporter&.emit(force_emit)
105
132
  end
106
133
 
107
- def configure(target_path:, logger: OneshotCoverage::Logger::NullLogger.new, emit_term: nil)
108
- target_path_by_pathname =
109
- if target_path.is_a? Pathname
110
- target_path
111
- else
112
- Pathname.new(target_path)
113
- end
134
+ def configure(
135
+ target_path:,
136
+ logger: OneshotCoverage::Logger::NullLogger.new,
137
+ coverage_module: Coverage,
138
+ emit_term: nil,
139
+ cover_bundle_path: false
140
+ )
114
141
  @reporter = OneshotCoverage::Reporter.new(
115
- target_path: target_path_by_pathname.cleanpath.to_s + "/",
142
+ coverage_module: coverage_module,
143
+ target_path: Pathname.new(target_path).cleanpath.to_s + "/",
116
144
  logger: logger,
117
145
  emit_term: emit_term,
146
+ cover_bundle_path: cover_bundle_path
118
147
  )
119
148
  end
120
149
  end
@@ -22,7 +22,7 @@ module OneshotCoverage
22
22
  private
23
23
 
24
24
  def fetch
25
- JSON.load(File.read(@log_path))
25
+ JSON.load(File.read(@log_path)) || {}
26
26
  rescue Errno::ENOENT
27
27
  {}
28
28
  end
@@ -0,0 +1,95 @@
1
+ require 'coverage'
2
+ require 'find'
3
+ require 'json'
4
+
5
+ module OneshotCoverage
6
+ class SimplecovReporter
7
+ module DefaultFilter
8
+ module_function def call(path)
9
+ return false unless File.extname(path) == '.rb'
10
+ return false if path.include?('/spec/')
11
+ return false if path.include?('/test/')
12
+ return false if path.include?('/script/')
13
+ return false if path.include?('/config/')
14
+
15
+ true
16
+ end
17
+ end
18
+
19
+ # @option log_path [String] oneshot coverage log generated by FileLogger or same scheme json file acceptable
20
+ # @option project_path [String] target project path.
21
+ # @option file_filter [Object] Object respond to #call with return true | false. this filter used for coverage target. file_filter.call(path) return false, then path will not be included to report
22
+ def initialize(
23
+ log_path:,
24
+ project_path: Dir.pwd,
25
+ file_filter: DefaultFilter
26
+ )
27
+ @project_path = project_path.end_with?('/') ? project_path : "#{project_path}/"
28
+ @log_path = log_path
29
+ @file_filter = file_filter
30
+ end
31
+
32
+ def run
33
+ raise "Please install & require 'simplecov' if you want to use this" unless defined? SimpleCov
34
+
35
+ coverages = coverage_stubs
36
+ fill_lines(coverages)
37
+ gen_html(coverages)
38
+ end
39
+
40
+ private
41
+
42
+ def coverage_candidates
43
+ @coverage_candidates ||=
44
+ Find.find(@project_path).
45
+ select { |fp| @file_filter.call(fp) }
46
+ # map { |fp| fp.sub(@project_path, '') }
47
+ end
48
+
49
+ def coverage_stubs
50
+ {}.tap do |stubs|
51
+ coverage_candidates.each do |filepath|
52
+ stub = Coverage.line_stub(filepath)
53
+ stubs[filepath] = stub
54
+ end
55
+ end
56
+ end
57
+
58
+ def oneshot_coverage_logs
59
+ @oneshot_coverage_logs ||= begin
60
+ raise "#{@log_path} isn't exist!" unless File.exist?(@log_path)
61
+
62
+ JSON.parse(File.read(@log_path)).transform_keys do |filepath_with_md5_hash|
63
+ *path_tokens, _md5_hash = filepath_with_md5_hash.split('-')
64
+ "#{@project_path}#{path_tokens.join('-')}"
65
+ end
66
+ end
67
+ end
68
+
69
+ def fill_lines(coverages)
70
+ oneshot_coverage_logs.each do |filepath, linenums|
71
+ linenums.each do |linenum|
72
+ coverages[filepath][linenum - 1] = 1
73
+ end
74
+ end
75
+ end
76
+
77
+ def format_data(coverages)
78
+ coverages.transform_values do |lines|
79
+ { "lines" => lines }
80
+ end
81
+ end
82
+
83
+ def gen_html(coverages)
84
+ coverages_for_simcov = format_data(coverages)
85
+ SimpleCov.root(@project_path)
86
+ result = SimpleCov::Result.from_hash({
87
+ 'oneshot' => {
88
+ 'coverage' => coverages_for_simcov,
89
+ 'timestamp' => Time.now.to_i
90
+ }
91
+ }).first
92
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
93
+ end
94
+ end
95
+ end
@@ -1,3 +1,3 @@
1
1
  module OneshotCoverage
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -36,7 +36,4 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  # Release ruby version lock temperary
38
38
  # spec.required_ruby_version = '>= 2.6'
39
-
40
- spec.add_development_dependency "bundler", "~> 1.17"
41
- spec.add_development_dependency "rake", "~> 10.0"
42
39
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gem "minitest"
8
+ gem "simplecov"
@@ -0,0 +1,21 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ docile (1.4.0)
5
+ minitest (5.14.4)
6
+ simplecov (0.21.2)
7
+ docile (~> 1.1)
8
+ simplecov-html (~> 0.11)
9
+ simplecov_json_formatter (~> 0.1)
10
+ simplecov-html (0.12.3)
11
+ simplecov_json_formatter (0.1.3)
12
+
13
+ PLATFORMS
14
+ x86_64-darwin-20
15
+
16
+ DEPENDENCIES
17
+ minitest
18
+ simplecov
19
+
20
+ BUNDLED WITH
21
+ 2.2.3
@@ -0,0 +1,10 @@
1
+ class Adder
2
+ def initialize(a, b)
3
+ @a = a
4
+ @b = b
5
+ end
6
+
7
+ def call
8
+ @a + @b
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
2
+ require "oneshot_coverage"
3
+ require "oneshot_coverage/logger/file_logger"
4
+
5
+ OneshotCoverage.configure(
6
+ target_path: Dir.pwd,
7
+ logger: OneshotCoverage::Logger::FileLogger.new('coverage.json'),
8
+ emit_term: nil,
9
+ cover_bundle_path: ENV["COVER_BUNDLE_PATH"] == "1",
10
+ )
11
+
12
+ OneshotCoverage.start
13
+
14
+ require "minitest"
15
+ require_relative "adder"
16
+
17
+ Adder.new(1, 2).call
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
2
+
3
+ require 'simplecov'
4
+ require 'oneshot_coverage/simplecov_reporter'
5
+
6
+ OneshotCoverage::SimplecovReporter.new(
7
+ project_path: Dir.pwd,
8
+ log_path: 'coverage.json',
9
+ file_filter: OneshotCoverage::SimplecovReporter::DefaultFilter
10
+ ).run
metadata CHANGED
@@ -1,43 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oneshot_coverage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shia
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-16 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.17'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.17'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
11
+ date: 2021-07-14 00:00:00.000000000 Z
12
+ dependencies: []
41
13
  description: OneshotCoverage will help you to measure oneshot coverage on production
42
14
  email:
43
15
  - rise.shia@gmail.com
@@ -45,10 +17,11 @@ executables: []
45
17
  extensions: []
46
18
  extra_rdoc_files: []
47
19
  files:
20
+ - ".github/workflows/main.yml"
48
21
  - ".gitignore"
22
+ - CHANGELOG.md
49
23
  - CODE_OF_CONDUCT.md
50
24
  - Gemfile
51
- - Gemfile.lock
52
25
  - LICENSE.txt
53
26
  - README.md
54
27
  - Rakefile
@@ -59,8 +32,14 @@ files:
59
32
  - lib/oneshot_coverage/logger/null_logger.rb
60
33
  - lib/oneshot_coverage/logger/stdout_logger.rb
61
34
  - lib/oneshot_coverage/railtie.rb
35
+ - lib/oneshot_coverage/simplecov_reporter.rb
62
36
  - lib/oneshot_coverage/version.rb
63
37
  - oneshot_coverage.gemspec
38
+ - target_app/Gemfile
39
+ - target_app/Gemfile.lock
40
+ - target_app/adder.rb
41
+ - target_app/cover_code_test.rb
42
+ - target_app/gen_simplecov_report.rb
64
43
  homepage: https://github.com/riseshia/oneshot_coverage
65
44
  licenses:
66
45
  - MIT
@@ -68,7 +47,7 @@ metadata:
68
47
  homepage_uri: https://github.com/riseshia/oneshot_coverage
69
48
  source_code_uri: https://github.com/riseshia/oneshot_coverage
70
49
  changelog_uri: https://github.com/riseshia/oneshot_coverage
71
- post_install_message:
50
+ post_install_message:
72
51
  rdoc_options: []
73
52
  require_paths:
74
53
  - lib
@@ -83,8 +62,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
62
  - !ruby/object:Gem::Version
84
63
  version: '0'
85
64
  requirements: []
86
- rubygems_version: 3.0.3
87
- signing_key:
65
+ rubygems_version: 3.2.3
66
+ signing_key:
88
67
  specification_version: 4
89
68
  summary: Simple toolbox for oneshot coverage
90
69
  test_files: []
data/Gemfile.lock DELETED
@@ -1,20 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- oneshot_coverage (0.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- rake (10.5.0)
10
-
11
- PLATFORMS
12
- ruby
13
-
14
- DEPENDENCIES
15
- bundler (~> 1.17)
16
- oneshot_coverage!
17
- rake (~> 10.0)
18
-
19
- BUNDLED WITH
20
- 1.17.2