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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbff118005d968f8d2158135273f108cbb9b867c9c13d783b5fb8a2220dd5540
4
- data.tar.gz: bc7ec947e707d4feaf213a0559f110ae5d11a487ea370f5e9f6a1256c2799701
3
+ metadata.gz: a5cd2e1c2877aa5eefb57baf7b1c51c5e708ef8d5869f01b51a37c3b6e37c931
4
+ data.tar.gz: 4f0a6bc520d84917f989b3c13ec1c5bba2d6ab04db26fb87331cfed536b142f9
5
5
  SHA512:
6
- metadata.gz: af026a80339c3047c62c99c6ec47385288fc7a0fd1d295b646abffdd4b74ea48118f01b2caa2ef997d7dc8775ebc047ce9844189065148f82eaea10fb2bf2978
7
- data.tar.gz: a4555a8209507c66efc7ba2432bb5b743cc45331fead66f038df9823a85e8a1bbf9401cd9b47a450cfd184ff399d429e193527df6745ec1770b0b0e08a863141
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
@@ -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
- if ENV["CI"]
11
- # skipping pry-byebug as it has issues on Ruby 2.3 on travis
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
- [![Build Status](https://travis-ci.org/danmayer/coverband.svg?branch=master)](https://travis-ci.org/danmayer/coverband)
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`. 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.
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 method aliasing by adding require: ['alternative_coverband_patch'] to the gem line as shown above.
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
@@ -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 = ["dan@mayerdan.com"]
12
- spec.description = "Rack middleware to measure production code usage (LOC runtime usage)"
13
- spec.summary = "Rack middleware to measure production code usage (LOC runtime usage)"
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 = ["lib"]
22
+ spec.require_paths = %w[lib]
21
23
 
22
24
  spec.add_development_dependency "benchmark-ips"
23
25
  spec.add_development_dependency "capybara"
@@ -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}").reject { |file| file.match(/(_mailer)/) }.freeze }
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
- Rake.application["environment"].invoke if Rake::Task.task_defined?("environment")
15
- Coverband.configuration.store.merge_mode = true if Coverband.configuration.store.is_a?(Coverband::Adapters::FileStore)
16
- Rack::Server.start app: Coverband::Reporters::Web.new, Port: ENV.fetch("COVERBAND_COVERAGE_PORT", 9022).to_i
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
  ###
@@ -5,5 +5,5 @@
5
5
  # use format '4.2.1.rc.1' ~> 4.2.1.rc to prerelease versions like v4.2.1.rc.2 and v4.2.1.rc.3
6
6
  ###
7
7
  module Coverband
8
- VERSION = "5.0.3"
8
+ VERSION = '5.1.0'
9
9
  end
@@ -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
@@ -3,6 +3,7 @@
3
3
  original_verbosity = $VERBOSE
4
4
  $VERBOSE = nil
5
5
  require "rubygems"
6
+ require "pry-byebug" unless ENV["CI"]
6
7
  require "simplecov"
7
8
  require "coveralls"
8
9
  require "minitest/autorun"
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.3
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-10-09 00:00:00.000000000 Z
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
@@ -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