coverband 5.0.3 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/main.yml +30 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +2 -5
- data/README.md +32 -5
- data/changes.md +4 -10
- data/coverband.gemspec +6 -4
- data/lib/coverband/at_exit.rb +3 -0
- data/lib/coverband/collectors/view_tracker.rb +1 -1
- data/lib/coverband/utils/dead_methods.rb +63 -0
- data/lib/coverband/utils/method_definition_scanner.rb +96 -0
- data/lib/coverband/utils/tasks.rb +17 -3
- data/lib/coverband/version.rb +1 -1
- data/test/coverband/collectors/view_tracker_test.rb +10 -0
- data/test/coverband/utils/dead_methods_test.rb +53 -0
- data/test/coverband/utils/method_definition_scanner_test.rb +85 -0
- data/test/fixtures/casting_invitor.rb +60 -0
- data/test/test_helper.rb +1 -0
- metadata +14 -3
- data/.travis.yml +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5cd2e1c2877aa5eefb57baf7b1c51c5e708ef8d5869f01b51a37c3b6e37c931
|
4
|
+
data.tar.gz: 4f0a6bc520d84917f989b3c13ec1c5bba2d6ab04db26fb87331cfed536b142f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb077ceeb315e92dd7f51e355057d855b00701e05d8b4ef7836ff8cae624c2db71ba0ce67ac6e3be5dd5fb87182c4a68d8e8d1ab3c6e4554f2d792db9f214c65
|
7
|
+
data.tar.gz: 0ab9e096d137f1babd34b3cc32899095b6b3f0f87bb0a9aee7d987bf8b116b1815a3fc630ad0f1f73d4550563c2cf08a4bb9e8e20e8c9553dd9246d0dee6414a
|
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Describe the bug**
|
11
|
+
A clear and concise description of what the bug is.
|
12
|
+
|
13
|
+
**To Reproduce**
|
14
|
+
Steps to reproduce the behavior:
|
15
|
+
1. Go to '...'
|
16
|
+
2. Click on '....'
|
17
|
+
3. Scroll down to '....'
|
18
|
+
4. See error
|
19
|
+
|
20
|
+
**Expected behavior**
|
21
|
+
A clear and concise description of what you expected to happen.
|
22
|
+
|
23
|
+
**Screenshots**
|
24
|
+
If applicable, add screenshots to help explain your problem.
|
25
|
+
|
26
|
+
**Desktop (please complete the following information):**
|
27
|
+
- OS: [e.g. iOS]
|
28
|
+
- Browser [e.g. chrome, safari]
|
29
|
+
- Version [e.g. 22]
|
30
|
+
|
31
|
+
**Smartphone (please complete the following information):**
|
32
|
+
- Device: [e.g. iPhone6]
|
33
|
+
- OS: [e.g. iOS8.1]
|
34
|
+
- Browser [e.g. stock browser, safari]
|
35
|
+
- Version [e.g. 22]
|
36
|
+
|
37
|
+
**Additional context**
|
38
|
+
Add any other context about the problem here.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Suggest an idea for this project
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Is your feature request related to a problem? Please describe.**
|
11
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
12
|
+
|
13
|
+
**Describe the solution you'd like**
|
14
|
+
A clear and concise description of what you want to happen.
|
15
|
+
|
16
|
+
**Describe alternatives you've considered**
|
17
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
18
|
+
|
19
|
+
**Additional context**
|
20
|
+
Add any other context or screenshots about the feature request here.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
name: CI
|
2
|
+
# Controls when the action will run.
|
3
|
+
on:
|
4
|
+
# Triggers the workflow on push or pull request events but only for the master branch
|
5
|
+
push:
|
6
|
+
branches: [master]
|
7
|
+
pull_request:
|
8
|
+
branches: [master]
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
strategy:
|
12
|
+
fail-fast: false
|
13
|
+
matrix:
|
14
|
+
# need to figure out how to use redis on macos github actions
|
15
|
+
# os: [ubuntu, macos]
|
16
|
+
os: [ubuntu]
|
17
|
+
# remove until I sort out CI issues for truffle
|
18
|
+
# truffleruby,
|
19
|
+
# truffleruby-head,
|
20
|
+
ruby: [2.3, 2.4, 2.5, 2.6, 2.7, jruby, jruby-head]
|
21
|
+
redis-version: [5]
|
22
|
+
runs-on: ${{ matrix.os }}-latest
|
23
|
+
steps:
|
24
|
+
- uses: actions/checkout@v2
|
25
|
+
- uses: supercharge/redis-github-action@1.1.0
|
26
|
+
- uses: ruby/setup-ruby@v1
|
27
|
+
with:
|
28
|
+
ruby-version: ${{ matrix.ruby }}
|
29
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
30
|
+
- run: bundle exec rake
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
See our [code of conduct](https://github.com/danmayer/coverband/blob/master/CODE_OF_CONDUCT.md)
|
data/Gemfile
CHANGED
@@ -7,11 +7,8 @@ gemspec
|
|
7
7
|
|
8
8
|
# add when debugging
|
9
9
|
# require 'byebug'; byebug
|
10
|
-
|
11
|
-
|
12
|
-
# and we don't really need it on CI
|
13
|
-
else
|
14
|
-
gem "pry-byebug", platforms: [:mri, :mingw, :x64_mingw]
|
10
|
+
unless ENV["CI"]
|
11
|
+
gem "pry-byebug"
|
15
12
|
end
|
16
13
|
|
17
14
|
gem "rails", "~>5"
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# Coverband
|
4
4
|
|
5
|
-
[![
|
5
|
+
[![GithubCI](https://github.com/danmayer/coverband/workflows/CI/badge.svg)](https://github.com/danmayer/coverband/actions)
|
6
6
|
[![Coverage Status](https://coveralls.io/repos/github/danmayer/coverband/badge.svg?branch=master)](https://coveralls.io/github/danmayer/coverband?branch=master)
|
7
7
|
[![Maintainability](https://api.codeclimate.com/v1/badges/1e6682f9540d75f26da7/maintainability)](https://codeclimate.com/github/danmayer/coverband/maintainability)
|
8
8
|
[![Discord Shield](https://img.shields.io/discord/609509533999562753)](https://discord.gg/KAH38EV)
|
@@ -12,6 +12,7 @@
|
|
12
12
|
<a href="#installation">Installation</a> •
|
13
13
|
<a href="#coverband-web-ui">Coverband Web UI</a> •
|
14
14
|
<a href="#advanced-config">Advanced Config</a> •
|
15
|
+
<a href="#newer-features">Newer Features</a> •
|
15
16
|
<a href="#license">License</a> •
|
16
17
|
<a href="/changes.md">Change Log / Roadmap</a> •
|
17
18
|
<a href="/CODE_OF_CONDUCT.md">Code of Conduct</a>
|
@@ -33,6 +34,7 @@ The primary goal of Coverband is giving deep insight into your production runtim
|
|
33
34
|
- Development mode, offers deep insight of code usage details (number of LOC execution during single request, etc) during development.
|
34
35
|
- Mountable web interface to easily share reports
|
35
36
|
|
37
|
+
|
36
38
|
# Installation
|
37
39
|
|
38
40
|
## Redis
|
@@ -65,7 +67,7 @@ The Railtie integration means you shouldn't need to do anything else other than
|
|
65
67
|
|
66
68
|
## Sinatra
|
67
69
|
|
68
|
-
For the best coverage you want this loaded as early as possible. We recommend requiring cover band directly in the `config.ru`.
|
70
|
+
For the best coverage you want this loaded as early as possible. We recommend requiring cover band directly in the `config.ru`. Requiring coverband within an initializer could also work, but you may end up missing some boot up coverage. To start collection require Coverband as early as possible.
|
69
71
|
|
70
72
|
```ruby
|
71
73
|
require 'coverband'
|
@@ -91,7 +93,7 @@ run ActionController::Dispatcher.new
|
|
91
93
|
|
92
94
|
- Clear coverage report
|
93
95
|
|
94
|
-
This will clear the coverage data. This wipes out all collected data.
|
96
|
+
This will clear the coverage data. This wipes out all collected data.
|
95
97
|
|
96
98
|
- Clear individual file coverage
|
97
99
|
|
@@ -304,6 +306,8 @@ rake coverband:coverage # report runtime coverband code coverage
|
|
304
306
|
|
305
307
|
Coverband starts on require of the the library which is usually done within the Gemfile. This can be disabled by setting the `COVERBAND_DISABLE_AUTO_START` environment variable. This environment variable can be useful to toggle coverband on and off in certain environments.
|
306
308
|
|
309
|
+
**NOTE:** That any value set for `COVERBAND_DISABLE_AUTO_START` is considered true, it does not match the string content but only checks the presence of the ENV variable.
|
310
|
+
|
307
311
|
In order to start coverband manually yourself when this flag is enabled, call `Coverband.configure` followed by `Coverband.start`.
|
308
312
|
|
309
313
|
```ruby
|
@@ -333,7 +337,31 @@ If you currently have require: false, remove the 'coverband' string from the req
|
|
333
337
|
gem 'coverband', require: ['alternative_coverband_patch']
|
334
338
|
```
|
335
339
|
|
336
|
-
This conflict happens when a ruby method is patched twice, once using module prepend, and once using method aliasing. See this ruby issue for details. The fix is to apply all patches the same way. Coverband by default will apply its patch using prepend, but you can change that to
|
340
|
+
This conflict happens when a ruby method is patched twice, once using module prepend, and once using method aliasing. See this ruby issue for details. The fix is to apply all patches the same way. Coverband by default will apply its patch using prepend, but you can change that to method aliasing by adding require: ['alternative_coverband_patch'] to the gem line as shown above.
|
341
|
+
|
342
|
+
# Newer Features
|
343
|
+
|
344
|
+
### Dead Method Scanning (ruby 2.6+)
|
345
|
+
|
346
|
+
Rake task that outputs dead methods based on current coverage data:
|
347
|
+
|
348
|
+
```
|
349
|
+
bundle exec rake coverband:dead_methods
|
350
|
+
```
|
351
|
+
|
352
|
+
Outputs:
|
353
|
+
|
354
|
+
```
|
355
|
+
---------------------------------------------------------------------------------------------------
|
356
|
+
| file | class | method | line_number |
|
357
|
+
| ./config/routes.rb | AdminConstraint | matches? | 20 |
|
358
|
+
| ./app/controllers/home_controller.rb | HomeController | trigger_jobs | 8 |
|
359
|
+
| ./app/controllers/home_controller.rb | HomeController | data_tracer | 14 |
|
360
|
+
| ./app/controllers/posts_controller.rb | PostsController | edit | 22 |
|
361
|
+
| ./app/controllers/posts_controller.rb | PostsController | destroy_bad_dangerously | 73 |
|
362
|
+
---------------------------------------------------------------------------------------------------
|
363
|
+
```
|
364
|
+
|
337
365
|
|
338
366
|
# Prerequisites
|
339
367
|
|
@@ -385,7 +413,6 @@ If you submit a change please make sure the tests and benchmarks are passing.
|
|
385
413
|
- **total fail** on front end code, for line for line coverage, because of the precompiled template step basically coverage doesn't work well for `erb`, `slim`, and the like.
|
386
414
|
- related it will try to report something, but the line numbers reported for `ERB` files are often off and aren't considered useful. I recommend filtering out .erb using the `config.ignore` option. The default configuration excludes these files
|
387
415
|
- **NOTE:** We now have file level coverage for view files, but don't support line level detail
|
388
|
-
- The view file detection doesn't workf or mailers at the moment only for web related views / JSON templates. This is due to how Rails active mailer notifications work.
|
389
416
|
- **Coverage does NOT work when used alongside Scout APM Auto Instrumentation**
|
390
417
|
- In an environment that uses Scout's `AUTO_INSTRUMENT=true` (usually production or staging) it stops reporting any coverage, it will show one or two files that have been loaded at the start but everything else will show up as having 0% coverage
|
391
418
|
- Bug tracked here: https://github.com/scoutapp/scout_apm_ruby/issues/343
|
data/changes.md
CHANGED
@@ -55,19 +55,19 @@ Will be the fully modern release that drops maintenance legacy support in favor
|
|
55
55
|
|
56
56
|
### Coverband 5.0.4
|
57
57
|
|
58
|
-
-
|
58
|
+
- add support for tracking email view templates/partials
|
59
59
|
|
60
60
|
# Released
|
61
61
|
|
62
62
|
### Coverband 5.0.3
|
63
63
|
|
64
|
-
- fix for non standard root paths for view_tracker thx @markshawtoronto
|
64
|
+
- fix for non standard root paths for view_tracker thx @markshawtoronto
|
65
65
|
- support basic auth for Rack prior to 2.0 thx @kadru
|
66
66
|
|
67
67
|
### Coverband 5.0.2
|
68
68
|
|
69
69
|
- change default port of local server
|
70
|
-
- update on readme about issue with scout app, thanks @mrbongiolo
|
70
|
+
- update on readme about issue with scout app, thanks @mrbongiolo
|
71
71
|
- fix on configuration page not loading when redis can't load
|
72
72
|
|
73
73
|
### Coverband 5.0.1
|
@@ -82,13 +82,7 @@ Will be the fully modern release that drops maintenance legacy support in favor
|
|
82
82
|
- drops static report support
|
83
83
|
- drops gem support
|
84
84
|
- only loaded web reporter files when required
|
85
|
-
- configuration improvements
|
86
|
-
- improved load order allowing more time for ENV vars (better dotenv, figaro, rails secrets support)
|
87
|
-
- all config options can be set via coverband config, not requiring ENV var support
|
88
|
-
- deprecation notices on soon to be removed config options
|
89
|
-
- config exceptions on invalid configuration combinations
|
90
|
-
- additional testing around configurations
|
91
|
-
- improved defaults and reduced configuration options
|
85
|
+
- configuration improvements - improved load order allowing more time for ENV vars (better dotenv, figaro, rails secrets support) - all config options can be set via coverband config, not requiring ENV var support - deprecation notices on soon to be removed config options - config exceptions on invalid configuration combinations - additional testing around configurations - improved defaults and reduced configuration options
|
92
86
|
- improved resque patching pattern
|
93
87
|
- improved default ignores
|
94
88
|
- additional adapters
|
data/coverband.gemspec
CHANGED
@@ -8,16 +8,18 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.name = "coverband"
|
9
9
|
spec.version = Coverband::VERSION
|
10
10
|
spec.authors = ["Dan Mayer", "Karl Baum"]
|
11
|
-
spec.email = [
|
12
|
-
spec.description =
|
13
|
-
|
11
|
+
spec.email = %w[dan@mayerdan.com]
|
12
|
+
spec.description =
|
13
|
+
"Rack middleware to measure production code usage (LOC runtime usage)"
|
14
|
+
spec.summary =
|
15
|
+
"Rack middleware to measure production code usage (LOC runtime usage)"
|
14
16
|
spec.homepage = "https://github.com/danmayer/coverband"
|
15
17
|
spec.license = "MIT"
|
16
18
|
|
17
19
|
spec.files = `git ls-files`.split("\n").reject { |f| f.start_with?("docs") }
|
18
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
21
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = %w[lib]
|
21
23
|
|
22
24
|
spec.add_development_dependency "benchmark-ips"
|
23
25
|
spec.add_development_dependency "capybara"
|
data/lib/coverband/at_exit.rb
CHANGED
@@ -20,6 +20,9 @@ module Coverband
|
|
20
20
|
# skip reporting
|
21
21
|
else
|
22
22
|
Coverband.report_coverage
|
23
|
+
# to ensure we track mailer views we now need to report views tracking
|
24
|
+
# at exit as well for rake tasks and background tasks that can trigger email
|
25
|
+
Coverband.configuration.view_tracker&.report_views_tracked
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
@@ -23,7 +23,7 @@ module Coverband
|
|
23
23
|
@ignore_patterns = Coverband.configuration.ignore
|
24
24
|
@store = options.fetch(:store) { Coverband.configuration.store }
|
25
25
|
@logger = options.fetch(:logger) { Coverband.configuration.logger }
|
26
|
-
@target = options.fetch(:target) { Dir.glob("#{@project_directory}/app/views/**/*.html.{erb,haml,slim}")
|
26
|
+
@target = options.fetch(:target) { Dir.glob("#{@project_directory}/app/views/**/*.html.{erb,haml,slim}") }
|
27
27
|
|
28
28
|
@roots = options.fetch(:roots) { Coverband.configuration.all_root_patterns }
|
29
29
|
@roots = @roots.split(",") if @roots.is_a?(String)
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: ntrue
|
2
|
+
|
3
|
+
require "coverband/utils/method_definition_scanner"
|
4
|
+
|
5
|
+
module Coverband
|
6
|
+
module Utils
|
7
|
+
module ArrayToTableInConsole
|
8
|
+
refine Array do
|
9
|
+
def to_table
|
10
|
+
column_sizes =
|
11
|
+
reduce([]) { |lengths, row|
|
12
|
+
row.each_with_index.map do |iterand, index|
|
13
|
+
[lengths[index] || 0, iterand.to_s.length].max
|
14
|
+
end
|
15
|
+
}
|
16
|
+
puts head =
|
17
|
+
"-" * (column_sizes.inject(&:+) + (3 * column_sizes.count) + 1)
|
18
|
+
each do |row|
|
19
|
+
row = row.fill(nil, row.size..(column_sizes.size - 1))
|
20
|
+
row =
|
21
|
+
row.each_with_index.map { |v, i|
|
22
|
+
v.to_s + " " * (column_sizes[i] - v.to_s.length)
|
23
|
+
}
|
24
|
+
puts "| " + row.join(" | ") + " |"
|
25
|
+
end
|
26
|
+
puts head
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class DeadMethods
|
32
|
+
using ArrayToTableInConsole
|
33
|
+
def self.scan(file_path:, coverage:)
|
34
|
+
MethodDefinitionScanner.scan(file_path).reject do |method_definition|
|
35
|
+
method_definition.body.coverage?(coverage)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.scan_all
|
40
|
+
coverage = Coverband.configuration.store.coverage
|
41
|
+
coverage.flat_map do |file_path, coverage|
|
42
|
+
scan(file_path: file_path, coverage: coverage["data"])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.output_all
|
47
|
+
rows =
|
48
|
+
scan_all.each_with_object(
|
49
|
+
[%w[file class method line_number]]
|
50
|
+
) { |dead_method, rows|
|
51
|
+
rows <<
|
52
|
+
[
|
53
|
+
dead_method.file_path,
|
54
|
+
dead_method.class_name,
|
55
|
+
dead_method.name,
|
56
|
+
dead_method.first_line_number
|
57
|
+
]
|
58
|
+
}
|
59
|
+
rows.to_table
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if defined?(RubyVM::AbstractSyntaxTree)
|
4
|
+
module Coverband
|
5
|
+
module Utils
|
6
|
+
class MethodDefinitionScanner
|
7
|
+
attr_reader :path
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def scan
|
14
|
+
scan_node(RubyVM::AbstractSyntaxTree.parse_file(path), nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.scan(path)
|
18
|
+
new(path).scan
|
19
|
+
end
|
20
|
+
|
21
|
+
class MethodBody
|
22
|
+
def initialize(method_definition)
|
23
|
+
@method_definition = method_definition
|
24
|
+
end
|
25
|
+
|
26
|
+
def coverage?(file_coverage)
|
27
|
+
body_coverage =
|
28
|
+
file_coverage[(first_line_number - 1)..(last_line_number - 1)]
|
29
|
+
body_coverage.map(&:to_i).any?(&:positive?)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def first_line_number
|
35
|
+
@method_definition.first_line_number + 1
|
36
|
+
end
|
37
|
+
|
38
|
+
def last_line_number
|
39
|
+
@method_definition.last_line_number - 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class MethodDefinition
|
44
|
+
attr_reader :last_line_number,
|
45
|
+
:first_line_number,
|
46
|
+
:name,
|
47
|
+
:class_name,
|
48
|
+
:file_path
|
49
|
+
|
50
|
+
def initialize(
|
51
|
+
first_line_number:,
|
52
|
+
last_line_number:,
|
53
|
+
name:,
|
54
|
+
class_name:,
|
55
|
+
file_path:
|
56
|
+
)
|
57
|
+
@first_line_number = first_line_number
|
58
|
+
@last_line_number = last_line_number
|
59
|
+
@name = name
|
60
|
+
@class_name = class_name
|
61
|
+
@file_path = file_path
|
62
|
+
end
|
63
|
+
|
64
|
+
def body
|
65
|
+
MethodBody.new(self)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def scan_node(node, class_name)
|
72
|
+
definitions = []
|
73
|
+
return definitions unless node.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
74
|
+
current_class = node.type == :CLASS ? node.children.first.children.last : class_name
|
75
|
+
if node.type == :DEFN
|
76
|
+
definitions <<
|
77
|
+
MethodDefinition.new(
|
78
|
+
first_line_number: node.first_lineno,
|
79
|
+
last_line_number: node.last_lineno,
|
80
|
+
name: node.children.first,
|
81
|
+
class_name: current_class,
|
82
|
+
file_path: path
|
83
|
+
)
|
84
|
+
end
|
85
|
+
definitions + scan_children(node, current_class)
|
86
|
+
end
|
87
|
+
|
88
|
+
def scan_children(node, current_class)
|
89
|
+
node.children.flatten.compact.map { |child|
|
90
|
+
scan_node(child, current_class)
|
91
|
+
}.flatten
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -9,11 +9,25 @@ namespace :coverband do
|
|
9
9
|
Coverband::Reporters::ConsoleReport.report(Coverband.configuration.store)
|
10
10
|
end
|
11
11
|
|
12
|
+
if defined?(RubyVM::AbstractSyntaxTree)
|
13
|
+
require "coverband/utils/dead_methods"
|
14
|
+
|
15
|
+
desc "Output all dead methods"
|
16
|
+
task :dead_methods do
|
17
|
+
Coverband::Utils::DeadMethods.output_all
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
12
21
|
desc "report runtime Coverband code coverage"
|
13
22
|
task :coverage_server do
|
14
|
-
|
15
|
-
|
16
|
-
|
23
|
+
if Rake::Task.task_defined?("environment")
|
24
|
+
Rake.application["environment"].invoke
|
25
|
+
end
|
26
|
+
if Coverband.configuration.store.is_a?(Coverband::Adapters::FileStore)
|
27
|
+
Coverband.configuration.store.merge_mode = true
|
28
|
+
end
|
29
|
+
Rack::Server.start app: Coverband::Reporters::Web.new,
|
30
|
+
Port: ENV.fetch("COVERBAND_COVERAGE_PORT", 9022).to_i
|
17
31
|
end
|
18
32
|
|
19
33
|
###
|
data/lib/coverband/version.rb
CHANGED
@@ -42,6 +42,16 @@ class ReporterTest < Minitest::Test
|
|
42
42
|
assert_equal [file_path], tracker.used_views.keys
|
43
43
|
end
|
44
44
|
|
45
|
+
test "track partials that include the word _mailer in the path" do
|
46
|
+
Coverband::Collectors::ViewTracker.expects(:supported_version?).returns(true)
|
47
|
+
store = fake_store
|
48
|
+
file_path = "#{File.expand_path(Coverband.configuration.root)}/_mailer/file"
|
49
|
+
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
|
50
|
+
tracker.track_views("name", "start", "finish", "id", identifier: file_path)
|
51
|
+
tracker.report_views_tracked
|
52
|
+
assert_equal [file_path], tracker.used_views.keys
|
53
|
+
end
|
54
|
+
|
45
55
|
test "ignore partials that include the folder vendor in the path" do
|
46
56
|
Coverband::Collectors::ViewTracker.expects(:supported_version?).returns(true)
|
47
57
|
store = fake_store
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path("../../test_helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
if defined?(RubyVM::AbstractSyntaxTree)
|
6
|
+
require "coverband/utils/dead_methods"
|
7
|
+
module Coverband
|
8
|
+
module Utils
|
9
|
+
class DeadMethodsTest < Minitest::Test
|
10
|
+
attr_accessor :coverband
|
11
|
+
|
12
|
+
def setup
|
13
|
+
super
|
14
|
+
@coverband = Coverband::Collectors::Coverage.instance
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_dog_dead_methods
|
18
|
+
file_path = require_unique_file
|
19
|
+
coverage = [nil, nil, 1, 1, 0, nil, nil]
|
20
|
+
dead_methods =
|
21
|
+
DeadMethods.scan(file_path: file_path, coverage: coverage)
|
22
|
+
assert_equal(1, dead_methods.length)
|
23
|
+
dead_method = dead_methods.first
|
24
|
+
assert_equal(4, dead_method.first_line_number)
|
25
|
+
assert_equal(6, dead_method.last_line_number)
|
26
|
+
assert_equal(file_path, dead_method.file_path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_all_dead_methods
|
30
|
+
require_unique_file
|
31
|
+
@coverband.report_coverage
|
32
|
+
dead_methods = DeadMethods.scan_all
|
33
|
+
dead_method = dead_methods.find { |method| method.class_name == :Dog }
|
34
|
+
assert(dead_method)
|
35
|
+
assert_equal(4, dead_method.first_line_number)
|
36
|
+
assert_equal(6, dead_method.last_line_number)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_output_all
|
40
|
+
require_unique_file
|
41
|
+
@coverband.report_coverage
|
42
|
+
DeadMethods.output_all
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_dog_methods_not_dead
|
46
|
+
file = require_unique_file
|
47
|
+
coverage = [nil, nil, 1, 1, 1, nil, nil]
|
48
|
+
assert_empty(DeadMethods.scan(file_path: file, coverage: coverage))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path("../../test_helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
if defined?(RubyVM::AbstractSyntaxTree)
|
6
|
+
require "coverband/utils/method_definition_scanner"
|
7
|
+
module Coverband
|
8
|
+
module Utils
|
9
|
+
class MethodBodyTest < Minitest::Test
|
10
|
+
def test_no_method_body_coverage
|
11
|
+
method_body =
|
12
|
+
MethodDefinitionScanner::MethodBody.new(
|
13
|
+
MethodDefinitionScanner::MethodDefinition.new(
|
14
|
+
first_line_number: 4,
|
15
|
+
last_line_number: 6,
|
16
|
+
name: :bark,
|
17
|
+
class_name: :Dog,
|
18
|
+
file_path: "./test/dog.rb"
|
19
|
+
)
|
20
|
+
)
|
21
|
+
refute(method_body.coverage?([nil, nil, 1, 1, 0, nil, 1]))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_method_body_coverage
|
25
|
+
method_body =
|
26
|
+
MethodDefinitionScanner::MethodBody.new(
|
27
|
+
MethodDefinitionScanner::MethodDefinition.new(
|
28
|
+
first_line_number: 4,
|
29
|
+
last_line_number: 6,
|
30
|
+
name: :bark,
|
31
|
+
class_name: :Dog,
|
32
|
+
file_path: "./test/dog.rb"
|
33
|
+
)
|
34
|
+
)
|
35
|
+
assert(method_body.coverage?([nil, nil, 1, 1, 1, nil, 1]))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class MethodDefinitionScannerTest < Minitest::Test
|
40
|
+
def test_scan
|
41
|
+
method_definitions = MethodDefinitionScanner.scan("./test/dog.rb")
|
42
|
+
assert(method_definitions)
|
43
|
+
assert_equal(1, method_definitions.length)
|
44
|
+
method_definition = method_definitions.first # assert_equal(4, method.first_line)
|
45
|
+
assert_equal(4, method_definition.first_line_number)
|
46
|
+
assert_equal(6, method_definition.last_line_number)
|
47
|
+
assert_equal(:bark, method_definition.name)
|
48
|
+
assert_equal(:Dog, method_definition.class_name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_scan_large_class
|
52
|
+
method_definitions =
|
53
|
+
MethodDefinitionScanner.scan("./test/fixtures/casting_invitor.rb")
|
54
|
+
method_first_line_numbers =
|
55
|
+
method_definitions.map(&:first_line_number)
|
56
|
+
assert_equal(
|
57
|
+
[6, 13, 17, 35, 40, 44, 48, 52],
|
58
|
+
method_first_line_numbers
|
59
|
+
)
|
60
|
+
method_last_line_numbers = method_definitions.map(&:last_line_number)
|
61
|
+
assert_equal(
|
62
|
+
[11, 15, 31, 38, 42, 46, 50, 59],
|
63
|
+
method_last_line_numbers
|
64
|
+
)
|
65
|
+
method_names = method_definitions.map(&:name)
|
66
|
+
assert_equal(
|
67
|
+
%i[
|
68
|
+
initialize
|
69
|
+
valid?
|
70
|
+
deliver
|
71
|
+
invalid_invitees
|
72
|
+
invitee_list
|
73
|
+
valid_message?
|
74
|
+
valid_invitees?
|
75
|
+
create_invitation
|
76
|
+
],
|
77
|
+
method_names
|
78
|
+
)
|
79
|
+
class_names = method_definitions.map(&:class_name)
|
80
|
+
assert_equal(8.times.map { :CastingInviter }, class_names)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class CastingInviter
|
2
|
+
EMAIL_REGEX = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/
|
3
|
+
|
4
|
+
attr_reader :message, :invitees, :casting
|
5
|
+
|
6
|
+
def initialize(attributes = {})
|
7
|
+
@message = attributes[:message] || ""
|
8
|
+
@invitees = attributes[:invitees] || ""
|
9
|
+
@sender = attributes[:sender]
|
10
|
+
@casting = attributes[:casting]
|
11
|
+
end
|
12
|
+
|
13
|
+
def valid?
|
14
|
+
valid_message? && valid_invitees?
|
15
|
+
end
|
16
|
+
|
17
|
+
def deliver
|
18
|
+
if valid?
|
19
|
+
invitee_list.each do |email|
|
20
|
+
invitation = create_invitation(email)
|
21
|
+
Mailer.invitation_notification(invitation, @message)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
failure_message =
|
25
|
+
"Your #{
|
26
|
+
@casting
|
27
|
+
} message couldn’t be sent. Invitees emails or message are invalid"
|
28
|
+
invitation = create_invitation(@sender)
|
29
|
+
Mailer.invitation_notification(invitation, failure_message)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def invalid_invitees
|
36
|
+
@invalid_invitees ||=
|
37
|
+
invitee_list.map { |item| item unless item.match(EMAIL_REGEX) }.compact
|
38
|
+
end
|
39
|
+
|
40
|
+
def invitee_list
|
41
|
+
@invitee_list ||= @invitees.gsub(/\s+/, "").split(/[\n,;]+/)
|
42
|
+
end
|
43
|
+
|
44
|
+
def valid_message?
|
45
|
+
@message.present?
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid_invitees?
|
49
|
+
invalid_invitees.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_invitation(email)
|
53
|
+
Invitation.create(
|
54
|
+
casting: @casting,
|
55
|
+
sender: @sender,
|
56
|
+
invitee_email: email,
|
57
|
+
status: "pending"
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coverband
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0
|
4
|
+
version: 5.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Mayer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-12-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: benchmark-ips
|
@@ -270,11 +270,14 @@ executables: []
|
|
270
270
|
extensions: []
|
271
271
|
extra_rdoc_files: []
|
272
272
|
files:
|
273
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
274
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
275
|
+
- ".github/workflows/main.yml"
|
273
276
|
- ".gitignore"
|
274
277
|
- ".jrubyrc"
|
275
278
|
- ".standard.yml"
|
276
|
-
- ".travis.yml"
|
277
279
|
- CODE_OF_CONDUCT.md
|
280
|
+
- CONTRIBUTING.md
|
278
281
|
- Gemfile
|
279
282
|
- Gemfile.rails4
|
280
283
|
- Gemfile.rails6
|
@@ -309,11 +312,13 @@ files:
|
|
309
312
|
- lib/coverband/reporters/html_report.rb
|
310
313
|
- lib/coverband/reporters/web.rb
|
311
314
|
- lib/coverband/utils/absolute_file_converter.rb
|
315
|
+
- lib/coverband/utils/dead_methods.rb
|
312
316
|
- lib/coverband/utils/file_hasher.rb
|
313
317
|
- lib/coverband/utils/file_list.rb
|
314
318
|
- lib/coverband/utils/html_formatter.rb
|
315
319
|
- lib/coverband/utils/jruby_ext.rb
|
316
320
|
- lib/coverband/utils/lines_classifier.rb
|
321
|
+
- lib/coverband/utils/method_definition_scanner.rb
|
317
322
|
- lib/coverband/utils/railtie.rb
|
318
323
|
- lib/coverband/utils/relative_file_converter.rb
|
319
324
|
- lib/coverband/utils/result.rb
|
@@ -382,10 +387,12 @@ files:
|
|
382
387
|
- test/coverband/reporters/html_test.rb
|
383
388
|
- test/coverband/reporters/web_test.rb
|
384
389
|
- test/coverband/utils/absolute_file_converter_test.rb
|
390
|
+
- test/coverband/utils/dead_methods_test.rb
|
385
391
|
- test/coverband/utils/file_hasher_test.rb
|
386
392
|
- test/coverband/utils/file_list_test.rb
|
387
393
|
- test/coverband/utils/html_formatter_test.rb
|
388
394
|
- test/coverband/utils/lines_classifier_test.rb
|
395
|
+
- test/coverband/utils/method_definition_scanner_test.rb
|
389
396
|
- test/coverband/utils/relative_file_converter_test.rb
|
390
397
|
- test/coverband/utils/result_test.rb
|
391
398
|
- test/coverband/utils/results_test.rb
|
@@ -396,6 +403,7 @@ files:
|
|
396
403
|
- test/fake_app/basic_rack.rb
|
397
404
|
- test/fixtures/app/controllers/sample_controller.rb
|
398
405
|
- test/fixtures/app/models/user.rb
|
406
|
+
- test/fixtures/casting_invitor.rb
|
399
407
|
- test/fixtures/never.rb
|
400
408
|
- test/fixtures/sample.rb
|
401
409
|
- test/fixtures/skipped.rb
|
@@ -514,10 +522,12 @@ test_files:
|
|
514
522
|
- test/coverband/reporters/html_test.rb
|
515
523
|
- test/coverband/reporters/web_test.rb
|
516
524
|
- test/coverband/utils/absolute_file_converter_test.rb
|
525
|
+
- test/coverband/utils/dead_methods_test.rb
|
517
526
|
- test/coverband/utils/file_hasher_test.rb
|
518
527
|
- test/coverband/utils/file_list_test.rb
|
519
528
|
- test/coverband/utils/html_formatter_test.rb
|
520
529
|
- test/coverband/utils/lines_classifier_test.rb
|
530
|
+
- test/coverband/utils/method_definition_scanner_test.rb
|
521
531
|
- test/coverband/utils/relative_file_converter_test.rb
|
522
532
|
- test/coverband/utils/result_test.rb
|
523
533
|
- test/coverband/utils/results_test.rb
|
@@ -528,6 +538,7 @@ test_files:
|
|
528
538
|
- test/fake_app/basic_rack.rb
|
529
539
|
- test/fixtures/app/controllers/sample_controller.rb
|
530
540
|
- test/fixtures/app/models/user.rb
|
541
|
+
- test/fixtures/casting_invitor.rb
|
531
542
|
- test/fixtures/never.rb
|
532
543
|
- test/fixtures/sample.rb
|
533
544
|
- test/fixtures/skipped.rb
|
data/.travis.yml
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- "2.3"
|
4
|
-
- "2.4"
|
5
|
-
- "2.5"
|
6
|
-
- "2.6.1"
|
7
|
-
- "2.7"
|
8
|
-
- jruby-9.2.6.0
|
9
|
-
gemfile:
|
10
|
-
- Gemfile
|
11
|
-
- Gemfile.rails4
|
12
|
-
- Gemfile.rails6
|
13
|
-
env:
|
14
|
-
global:
|
15
|
-
# --dev improves JRuby startup time
|
16
|
-
# See https://github.com/jruby/jruby/wiki/Improving-startup-time
|
17
|
-
- JRUBY_OPTS="--dev"
|
18
|
-
- JAVA_OPTS="--add-opens java.base/{java.security.cert=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.util.zip=ALL-UNNAMED"
|
19
|
-
|
20
|
-
jobs:
|
21
|
-
exclude:
|
22
|
-
- rvm: "2.3"
|
23
|
-
gemfile: Gemfile.rails6
|
24
|
-
- rvm: "2.4"
|
25
|
-
gemfile: Gemfile.rails6
|
26
|
-
- rvm: "2.7"
|
27
|
-
gemfile: Gemfile.rails4
|
28
|
-
- rvm: jruby-9.2.6.0
|
29
|
-
gemfile: Gemfile.rails4
|
30
|
-
|
31
|
-
cache:
|
32
|
-
bundler: true
|
33
|
-
directories:
|
34
|
-
- $HOME/lua51
|
35
|
-
services:
|
36
|
-
- redis-server
|
37
|
-
script:
|
38
|
-
- sudo ./lua/install.sh
|
39
|
-
- $HOME/lua51/bin/busted lua/test/*
|
40
|
-
- bundle exec standardrb
|
41
|
-
- COVERBAND_HASH_REDIS_STORE=t bundle exec rake
|
42
|
-
- COVERBAND_HASH_REDIS_STORE=t bundle exec rake forked_tests
|
43
|
-
- bundle exec rake
|
44
|
-
- bundle exec rake forked_tests
|
45
|
-
# remove this for now as it is flaky
|
46
|
-
# passes locally on 2.3.5 on travis passes sometimes on 2.4 and always on 2.6.1
|
47
|
-
#- bundle exec rake benchmarks:memory
|
48
|
-
- bundle exec rake benchmarks
|