undercover 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83b2a35bc1bcadd4892ed21804bf9fd7bd2b3a7a
4
- data.tar.gz: 91ed40ea4c090ce57d05532ed4ab986fe12fd873
3
+ metadata.gz: 95823e9c99d27f235ecf164326d14dfaba5ab716
4
+ data.tar.gz: 6626a7f1d7a6f01a3639f1f682064a30e2fee79c
5
5
  SHA512:
6
- metadata.gz: adeff5d8fe3e1a31b17427f0f53db3d62afaa50802aa52ac15b02a9adfcce82170147b6e327a6fcf59fbf4a9aa64828f7ad830b8aac2aa0ffd388af83643c4bb
7
- data.tar.gz: ef8f9f142bdcf0369a978fd765cbede85d39807cf79f3c5fb7ed89115c88725d4e8e1e3391cf01477e507391884aea7ce54dde04dd2520167fdd4c042a5b41e7
6
+ metadata.gz: 909e534984be8f7db602d5863ee31f1e986acaab8be58b84fd870e51f74ffe744a7625501eccca3f8cda2aec5a7a9dd0a6001cc6b1ca98472a0169e943557918
7
+ data.tar.gz: 6525467a27c472d0b24aa17cec6a986252ab649c8dfe514585dc405f8775803beac8d1aa7840ffc21af362a4bbb804bb890f41c1aca90ca9eeb56ba2b467247b
@@ -8,6 +8,10 @@ Style/RegexpLiteral:
8
8
  Style/Documentation:
9
9
  Enabled: false
10
10
 
11
+ Style/SpaceInsideHashLiteralBraces:
12
+ Enabled: true
13
+ EnforcedStyle: no_space
14
+
11
15
  Metrics/BlockLength:
12
16
  Enabled: true
13
17
  Exclude:
@@ -4,5 +4,9 @@ rvm:
4
4
  - 2.4.4
5
5
  - 2.3.4
6
6
  before_install:
7
- - gem install bundler
7
+ - gem install bundler undercover
8
8
  - gem update --system
9
+ script:
10
+ - bundle exec rake
11
+ - git pull origin master:master
12
+ - undercover --compare master
data/Gemfile CHANGED
@@ -1,6 +1,5 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
4
 
5
- # Specify your gem's dependencies in undercover.gemspec
6
5
  gemspec
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- undercover (0.1.0)
5
- imagen (~> 0.1.0)
4
+ undercover (0.1.1)
5
+ imagen (~> 0.1.1)
6
6
  rainbow (~> 3.0.0)
7
7
  rugged (~> 0.27.0)
8
8
 
@@ -13,12 +13,14 @@ GEM
13
13
  coderay (1.1.2)
14
14
  diff-lcs (1.3)
15
15
  docile (1.3.0)
16
- imagen (0.1.0)
16
+ imagen (0.1.1)
17
17
  parser
18
18
  json (2.1.0)
19
19
  method_source (0.9.0)
20
+ parallel (1.12.1)
20
21
  parser (2.5.1.0)
21
22
  ast (~> 2.4.0)
23
+ powerpack (0.1.1)
22
24
  pry (0.11.3)
23
25
  coderay (~> 1.1.0)
24
26
  method_source (~> 0.9.0)
@@ -37,6 +39,14 @@ GEM
37
39
  diff-lcs (>= 1.2.0, < 2.0)
38
40
  rspec-support (~> 3.7.0)
39
41
  rspec-support (3.7.1)
42
+ rubocop (0.55.0)
43
+ parallel (~> 1.10)
44
+ parser (>= 2.5)
45
+ powerpack (~> 0.1)
46
+ rainbow (>= 2.2.2, < 4.0)
47
+ ruby-progressbar (~> 1.7)
48
+ unicode-display_width (~> 1.0, >= 1.0.1)
49
+ ruby-progressbar (1.9.0)
40
50
  rugged (0.27.0)
41
51
  simplecov (0.16.1)
42
52
  docile (~> 1.1)
@@ -44,17 +54,22 @@ GEM
44
54
  simplecov-html (~> 0.10.0)
45
55
  simplecov-html (0.10.2)
46
56
  simplecov-lcov (0.7.0)
57
+ timecop (0.9.1)
58
+ unicode-display_width (1.3.2)
47
59
 
48
60
  PLATFORMS
49
61
  ruby
62
+ x86_64-darwin-17
50
63
 
51
64
  DEPENDENCIES
52
65
  bundler (~> 1.16)
53
66
  pry
54
67
  rake (~> 10.0)
55
68
  rspec (~> 3.0)
69
+ rubocop (~> 0.55.0)
56
70
  simplecov
57
71
  simplecov-lcov
72
+ timecop
58
73
  undercover!
59
74
 
60
75
  BUNDLED WITH
data/README.md CHANGED
@@ -1,11 +1,21 @@
1
- # Undercover
1
+ # undercover 👮‍♂️
2
2
 
3
- [![Build Status](https://travis-ci.org/grodowski/undercover.svg?branch=master)](https://travis-ci.org/grodowski/undercover)
4
- [![codebeat badge](https://codebeat.co/badges/be548247-2421-4448-bdab-896d13eb02e9)](https://codebeat.co/projects/github-com-grodowski-undercover-master)
3
+ **RuboCop for code coverage**
4
+
5
+ Meaningful warnings for methods and classes which lack testing, using data from coverage reports, git metadata and a parsed structure of your Ruby codebase. `undercover` automates the coverage feedback loop and makes sure no code review passes without tests.
6
+
7
+ A sample output of `undercover` ran before a commit may look like this:
5
8
 
6
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/undercover`. To experiment with that code, run `bin/console` for an interactive prompt.
9
+ ![screenshot warning](screenshot_warnings.png)
7
10
 
8
- TODO: Delete this and the text above, and describe your gem
11
+ And like this, given that specs were added:
12
+
13
+ ![screenshot success](screenshot_success.png)
14
+
15
+ The project is in an early phase, so please expect the unexpected and [report any problems or feedback as issues](https://github.com/grodowski/undercover/issues).
16
+
17
+ [![Build Status](https://travis-ci.org/grodowski/undercover.svg?branch=master)](https://travis-ci.org/grodowski/undercover)
18
+ [![codebeat badge](https://codebeat.co/badges/be548247-2421-4448-bdab-896d13eb02e9)](https://codebeat.co/projects/github-com-grodowski-undercover-master)
9
19
 
10
20
  ## Installation
11
21
 
@@ -23,9 +33,65 @@ Or install it yourself as:
23
33
 
24
34
  $ gem install undercover
25
35
 
36
+ ## Setting up required LCOV reporting
37
+
38
+ Undercover depends on a git diff, code structure generated by [`imagen`](https://github.com/grodowski/imagen_rb) and a coverage report in LCOV format.
39
+
40
+ To make your specs compatible with `undercover` by providing an LCOV report, please add `simplecov` and `simplecov-lcov` to your test setup. Example for rspec:
41
+
42
+ ```ruby
43
+ # Gemfile
44
+ group :test do
45
+ gem 'simplecov'
46
+ gem 'simplecov-lcov'
47
+ end
48
+
49
+ # the very top of spec_helper.rb
50
+ require 'simplecov'
51
+ require 'simplecov-lcov'
52
+ SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
53
+ SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
54
+ SimpleCov.start do
55
+ add_filter(/^\/spec\//)
56
+ end
57
+
58
+ require 'undercover'
59
+
60
+ # ...
61
+ ```
62
+
26
63
  ## Usage
27
64
 
28
- TODO: Write usage instructions here
65
+ ### Compare method and class coverage with latest commit
66
+
67
+ ```sh
68
+ undercover
69
+ ```
70
+
71
+ ### Compare with branch/ref
72
+
73
+ Undercover will list all methods and classes that haven't been covered in specs and have been added since a given git `ref`. Use the `-c --compare ref` flag to specify a git ref (commit hash, branch name, tag) to compare against.
74
+
75
+ **This is a recommended usage for CI/CD build environments**, as `undercover` will `exit 1` if there are any warnings.
76
+
77
+ ```sh
78
+ undercover --compare master
79
+ ```
80
+
81
+ ### Options
82
+
83
+ ```sh
84
+ undercover -h
85
+ Usage: undercover [options]
86
+ -l, --lcov path LCOV report file path
87
+ -p, --path path Project directory
88
+ -g, --git-dir dir Override `.git` with a custom directory
89
+ -c, --compare ref Generate coverage warnings for all changes after `ref`
90
+ -h, --help Prints this help
91
+ --version Show version
92
+ ```
93
+
94
+ The defaults assume that the program is run from the top level of the project directory.
29
95
 
30
96
  ## Development
31
97
 
@@ -35,7 +101,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
35
101
 
36
102
  ## Contributing
37
103
 
38
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/undercover.
104
+ Bug reports and pull requests are welcome on GitHub at https://github.com/grodowski/undercover.
39
105
 
40
106
  ## License
41
107
 
data/Rakefile CHANGED
@@ -1,6 +1,13 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
3
2
 
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ desc 'Run RuboCop'
8
+ RuboCop::RakeTask.new(:rubocop)
9
+
10
+ desc 'Run Tests'
4
11
  RSpec::Core::RakeTask.new(:spec)
5
12
 
6
- task :default => :spec
13
+ task default: %i[rubocop spec]
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH.unshift("#{__dir__}/../../lib")
4
+ $LOAD_PATH.unshift("#{__dir__}/../lib")
5
5
 
6
6
  require 'undercover'
7
7
  require 'benchmark'
@@ -19,7 +19,6 @@ module Undercover
19
19
  def_delegators :changeset, :validate
20
20
 
21
21
  attr_reader :changeset,
22
- :code_structure,
23
22
  :lcov,
24
23
  :results
25
24
 
@@ -27,8 +26,6 @@ module Undercover
27
26
  # add dependecy on "options" for all opts (dirs, git_dir, etc)
28
27
  def initialize(lcov_report_path, code_dir, git_dir: '.git', compare: nil)
29
28
  @lcov = LcovParser.parse(File.open(lcov_report_path))
30
- # TODO: optimise by building changeset structure only!
31
- @code_structure = Imagen.from_local(code_dir)
32
29
  @changeset = Changeset.new(File.join(code_dir, git_dir), compare).update
33
30
  @results = Hash.new { |hsh, key| hsh[key] = [] }
34
31
  end
@@ -71,13 +68,16 @@ module Undercover
71
68
 
72
69
  private
73
70
 
71
+ # TODO: some of this could be moved to the imagen gem
72
+ # TODO: should that start from changeset.file_paths?
73
+ # this way we could report things that weren't even loaded in any spec,
74
+ # so is this still good idea? (Rakefile, .gemspec etc)
74
75
  def each_result_arg
75
- matches_path = lambda do |path|
76
- ->(node) { node.file_path.end_with?(path) }
77
- end
78
-
76
+ match_all = ->(_) { true }
79
77
  lcov.source_files.each do |filename, coverage|
80
- code_structure.find_all(matches_path[filename]).each do |node|
78
+ ast = Imagen::Node::Root.new
79
+ Imagen::Visitor.traverse(Parser::CurrentRuby.parse_file(filename), ast)
80
+ ast.children[0].find_all(match_all).each do |node|
81
81
  yield(filename, coverage, node)
82
82
  end
83
83
  end
@@ -35,13 +35,18 @@ module Undercover
35
35
  end
36
36
 
37
37
  def last_modified
38
- mod = files.keys.map do |f|
39
- next T_ZERO unless File.exists?(f)
40
- File.mtime(File.join(repo.workdir, f))
38
+ mod = file_paths.map do |f|
39
+ path = File.join(repo.workdir, f)
40
+ next T_ZERO unless File.exist?(path)
41
+ File.mtime(path)
41
42
  end.max
42
43
  mod || T_ZERO
43
44
  end
44
45
 
46
+ def file_paths
47
+ files.keys.sort
48
+ end
49
+
45
50
  def each_changed_line
46
51
  files.each do |filepath, line_numbers|
47
52
  line_numbers.each { |ln| yield filepath, ln }
@@ -14,6 +14,8 @@ module Undercover
14
14
  no_changes: Rainbow('✅ No reportable changes').green
15
15
  }.freeze
16
16
 
17
+ WARNINGS_TO_EXITCODE = {stale_coverage: 1, no_changes: 0}.freeze
18
+
17
19
  # TODO: add executable in ./bin later
18
20
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
19
21
  def self.run(args)
@@ -28,7 +30,7 @@ module Undercover
28
30
  error = report.validate(opts.lcov)
29
31
  if error
30
32
  puts(WARNINGS_TO_S[error])
31
- return 1
33
+ return WARNINGS_TO_EXITCODE[error]
32
34
  end
33
35
 
34
36
  warnings = report.build_warnings
@@ -15,7 +15,7 @@ module Undercover
15
15
 
16
16
  def formatted_warnings
17
17
  @results.map.with_index(1) do |res, idx|
18
- "🚨 #{idx}) node `#{res.node.name}` type: #{res.node.class},\n" +
18
+ "🚨 #{idx}) node `#{res.node.name}` type: #{res.node.human_name},\n" +
19
19
  (' ' * pad_size) + "loc: #{res.file_path_with_lines}," \
20
20
  " coverage: #{res.coverage_f * 100}%\n" +
21
21
  res.pretty_print
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Undercover
2
- VERSION = "0.1.0"
4
+ VERSION = '0.1.1'
3
5
  end
Binary file
Binary file
@@ -1,33 +1,37 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "undercover/version"
5
+ require 'undercover/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "undercover"
8
+ spec.name = 'undercover'
8
9
  spec.version = Undercover::VERSION
9
- spec.authors = ["Jan Grodowski"]
10
- spec.email = ["jgrodowski@gmail.com"]
10
+ spec.authors = ['Jan Grodowski']
11
+ spec.email = ['jgrodowski@gmail.com']
11
12
 
12
- spec.summary = %q{Actionable code coverage - detects untested code blocks in recent changes}
13
- spec.homepage = "https://github.com/grodowski/undercover"
14
- spec.license = "MIT"
13
+ spec.summary = 'Actionable code coverage - detects untested' \
14
+ ' code blocks in recent changes'
15
+ spec.homepage = 'https://github.com/grodowski/undercover'
16
+ spec.license = 'MIT'
15
17
 
16
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
- f.match(%r{^(test|spec|features)/})
19
+ f.match(/^(test|spec|features)\//)
18
20
  end
19
- spec.bindir = "bin"
20
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
- spec.require_paths = ["lib"]
21
+ spec.bindir = 'bin'
22
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
22
24
 
23
- spec.add_dependency 'imagen', '~> 0.1.0'
25
+ spec.add_dependency 'imagen', '~> 0.1.1'
24
26
  spec.add_dependency 'rainbow', '~> 3.0.0'
25
27
  spec.add_dependency 'rugged', '~> 0.27.0'
26
28
 
27
- spec.add_development_dependency "bundler", "~> 1.16"
28
- spec.add_development_dependency "rake", "~> 10.0"
29
- spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency 'bundler', '~> 1.16'
30
30
  spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'rake', '~> 10.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'rubocop', '~> 0.55.0'
31
34
  spec.add_development_dependency 'simplecov'
32
35
  spec.add_development_dependency 'simplecov-lcov'
36
+ spec.add_development_dependency 'timecop'
33
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: undercover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Grodowski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-10 00:00:00.000000000 Z
11
+ date: 2018-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: imagen
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.0
19
+ version: 0.1.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.0
26
+ version: 0.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rainbow
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.16'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -95,7 +109,21 @@ dependencies:
95
109
  - !ruby/object:Gem::Version
96
110
  version: '3.0'
97
111
  - !ruby/object:Gem::Dependency
98
- name: pry
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.55.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.55.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
129
  - - ">="
@@ -109,7 +137,7 @@ dependencies:
109
137
  - !ruby/object:Gem::Version
110
138
  version: '0'
111
139
  - !ruby/object:Gem::Dependency
112
- name: simplecov
140
+ name: simplecov-lcov
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
143
  - - ">="
@@ -123,7 +151,7 @@ dependencies:
123
151
  - !ruby/object:Gem::Version
124
152
  version: '0'
125
153
  - !ruby/object:Gem::Dependency
126
- name: simplecov-lcov
154
+ name: timecop
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
157
  - - ">="
@@ -140,8 +168,6 @@ description:
140
168
  email:
141
169
  - jgrodowski@gmail.com
142
170
  executables:
143
- - console
144
- - setup
145
171
  - undercover
146
172
  extensions: []
147
173
  extra_rdoc_files: []
@@ -155,8 +181,6 @@ files:
155
181
  - LICENSE.txt
156
182
  - README.md
157
183
  - Rakefile
158
- - bin/console
159
- - bin/setup
160
184
  - bin/undercover
161
185
  - lib/undercover.rb
162
186
  - lib/undercover/changeset.rb
@@ -166,6 +190,8 @@ files:
166
190
  - lib/undercover/options.rb
167
191
  - lib/undercover/result.rb
168
192
  - lib/undercover/version.rb
193
+ - screenshot_success.png
194
+ - screenshot_warnings.png
169
195
  - undercover.gemspec
170
196
  homepage: https://github.com/grodowski/undercover
171
197
  licenses:
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "undercover"
5
- require "pry"
6
-
7
- Pry.start
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here