undercover 0.1.0 → 0.1.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
  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