coverband 4.2.0 → 4.2.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +29 -9
  3. data/.travis.yml +10 -1
  4. data/Gemfile +3 -1
  5. data/Gemfile.rails4 +1 -0
  6. data/README.md +40 -15
  7. data/Rakefile +14 -3
  8. data/changes.md +47 -12
  9. data/coverband.gemspec +3 -1
  10. data/lib/coverband/adapters/base.rb +60 -36
  11. data/lib/coverband/adapters/file_store.rb +8 -8
  12. data/lib/coverband/adapters/redis_store.rb +18 -10
  13. data/lib/coverband/at_exit.rb +2 -11
  14. data/lib/coverband/collectors/coverage.rb +32 -36
  15. data/lib/coverband/collectors/delta.rb +34 -28
  16. data/lib/coverband/configuration.rb +76 -32
  17. data/lib/coverband/integrations/background.rb +8 -4
  18. data/lib/coverband/integrations/{middleware.rb → background_middleware.rb} +2 -6
  19. data/lib/coverband/integrations/bundler.rb +8 -0
  20. data/lib/coverband/integrations/report_middleware.rb +15 -0
  21. data/lib/coverband/integrations/resque.rb +3 -5
  22. data/lib/coverband/reporters/base.rb +39 -14
  23. data/lib/coverband/reporters/html_report.rb +21 -27
  24. data/lib/coverband/reporters/web.rb +13 -21
  25. data/lib/coverband/utils/file_list.rb +16 -5
  26. data/lib/coverband/utils/file_path_helper.rb +14 -3
  27. data/lib/coverband/utils/html_formatter.rb +25 -8
  28. data/lib/coverband/utils/lines_classifier.rb +5 -0
  29. data/lib/coverband/utils/railtie.rb +11 -12
  30. data/lib/coverband/utils/result.rb +1 -37
  31. data/lib/coverband/utils/results.rb +51 -0
  32. data/lib/coverband/utils/source_file.rb +31 -6
  33. data/lib/coverband/utils/tasks.rb +9 -10
  34. data/lib/coverband/version.rb +1 -1
  35. data/lib/coverband.rb +32 -21
  36. data/public/application.js +27 -0
  37. data/test/benchmarks/benchmark.rake +144 -26
  38. data/test/coverband/adapters/base_test.rb +73 -42
  39. data/test/coverband/adapters/file_store_test.rb +48 -37
  40. data/test/coverband/adapters/redis_store_test.rb +41 -10
  41. data/test/coverband/at_exit_test.rb +0 -2
  42. data/test/coverband/collectors/coverage_test.rb +57 -9
  43. data/test/coverband/collectors/delta_test.rb +36 -6
  44. data/test/coverband/configuration_test.rb +47 -7
  45. data/test/coverband/coverband_test.rb +14 -2
  46. data/test/coverband/integrations/background_middleware_test.rb +44 -0
  47. data/test/coverband/integrations/background_test.rb +1 -3
  48. data/test/coverband/integrations/report_middleware_test.rb +44 -0
  49. data/test/coverband/integrations/resque_worker_test.rb +4 -3
  50. data/test/coverband/integrations/test_resque_job.rb +3 -1
  51. data/test/coverband/reporters/base_test.rb +4 -4
  52. data/test/coverband/reporters/console_test.rb +1 -2
  53. data/test/coverband/reporters/html_test.rb +58 -19
  54. data/test/coverband/reporters/web_test.rb +0 -10
  55. data/test/coverband/utils/file_groups_test.rb +11 -5
  56. data/test/coverband/utils/file_list_test.rb +5 -5
  57. data/test/coverband/utils/html_formatter_test.rb +43 -0
  58. data/test/coverband/utils/result_test.rb +6 -47
  59. data/test/coverband/utils/results_test.rb +54 -0
  60. data/test/coverband/utils/s3_report_test.rb +2 -0
  61. data/test/coverband/utils/source_file_test.rb +50 -0
  62. data/test/dog.rb.erb +12 -0
  63. data/test/forked/rails_full_stack_test.rb +106 -0
  64. data/test/forked/rails_rake_full_stack_test.rb +40 -0
  65. data/test/integration/full_stack_test.rb +17 -15
  66. data/test/rails4_dummy/Rakefile +6 -0
  67. data/test/rails4_dummy/config/application.rb +8 -9
  68. data/test/rails4_dummy/config/coverband.rb +5 -3
  69. data/test/rails5_dummy/Rakefile +6 -0
  70. data/test/rails5_dummy/config/application.rb +6 -10
  71. data/test/rails5_dummy/config/coverband.rb +4 -2
  72. data/test/rails_test_helper.rb +22 -5
  73. data/test/test_helper.rb +42 -4
  74. data/test/unique_files.rb +17 -9
  75. data/views/file_list.erb +2 -2
  76. data/views/gem_list.erb +10 -1
  77. data/views/layout.erb +10 -3
  78. data/views/source_file.erb +13 -4
  79. data/views/source_file_loader.erb +1 -1
  80. metadata +52 -9
  81. data/test/coverband/integrations/middleware_test.rb +0 -96
  82. data/test/integration/rails_full_stack_test.rb +0 -95
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e214b1bd6119046657daa64ed6d69f77f821c6c670b72e98d307ede5f08e61f
4
- data.tar.gz: 469d9470799f90b5b52d53d3a630fae75b3b6bff0390375987902331878f530e
3
+ metadata.gz: 0736c0a54102da0309de53707d866be707e72f0c977855bcf69586d281c9d2fe
4
+ data.tar.gz: 4616a0e6a769500797b89e751d8a8b96fa11ad11237c20bf359d592853e5e194
5
5
  SHA512:
6
- metadata.gz: f1b0f503941ab9dbc2dee6a184fe6d6d937a5f505a5c9112ae7343197372586d6cb42df758f24effde0ee30fb359c0e2e651c64a1f5ee4c9a588a4499683dc73
7
- data.tar.gz: ee700abfe4c730011dcc5c1c8521f55a2cc7ec5149e44b08187c8d09419023160a0f7c8aaba4b2aa0bb405eb13f4aeee1d8ce9cabce4860738d4ea94cac63c04
6
+ metadata.gz: c16f4e0351ffdd49ba3732c203b9932d4ee2ee8e9890b59f0c8d1e0beafcb2e8632d5a47ffc946248813284ebcac727785ceba3e38a6f041b0f5c000c42870f2
7
+ data.tar.gz: a1119724f958c01dfdb333efe95ed43acc6f2c1396d24efe7a208d8606e33d8de687d73a1099a3a20d5a37dbcef6b43c4ba36fb9d9d194d0a584e02957fdd016
data/.rubocop.yml CHANGED
@@ -2,14 +2,21 @@ AllCops:
2
2
  TargetRubyVersion: 2.4
3
3
  Exclude:
4
4
  - docs/**/*
5
+ - test/rails4_dummy/**/*
6
+ - test/rails5_dummy/**/*
7
+ - test/fixtures/**/*
8
+ # Get the code passing first then we will enable for tests
9
+ - test/**/*
5
10
  Documentation:
6
11
  Enabled: false
7
12
  Metrics/MethodLength:
8
13
  Enabled: false
9
14
  Metrics/LineLength:
10
- Max: 120
15
+ Max: 160
11
16
  Metrics/BlockNesting:
12
17
  Max: 5
18
+ Metrics/BlockLength:
19
+ Max: 30
13
20
  Metrics/CyclomaticComplexity:
14
21
  Enabled: false
15
22
  Metrics/PerceivedComplexity:
@@ -22,38 +29,51 @@ Metrics/ModuleLength:
22
29
  Enabled: false
23
30
  Metrics/ParameterLists:
24
31
  Max: 10
25
- Style/AccessorMethodName:
26
- Enabled: false
27
- Style/PredicateName:
32
+ Naming/AccessorMethodName:
28
33
  Enabled: false
34
+ Naming/PredicateName:
35
+ Enabled: true
29
36
  Style/TernaryParentheses:
30
37
  Enabled: false
31
38
  Style/MutableConstant:
32
39
  Enabled: false
40
+ Style/IdenticalConditionalBranches:
41
+ Enabled: false
42
+ Style/ClassVars:
43
+ Enabled: false
44
+ Style/MultilineBlockChain:
45
+ Enabled: false
33
46
  Style/FrozenStringLiteralComment:
34
47
  Enabled: true
35
48
  Style/GuardClause:
36
49
  Enabled: true
37
50
  Style/NumericPredicate:
38
- Enabled: false
51
+ Enabled: true
39
52
  Style/NumericLiterals:
40
53
  Enabled: false
41
54
  Style/NumericLiteralPrefix:
42
55
  Enabled: false
43
56
  Style/ClassAndModuleChildren:
44
57
  Enabled: false
58
+ Style/SymbolProc:
59
+ Enabled: false
60
+ Style/RegexpLiteral:
61
+ Enabled: false
45
62
  Performance/Casecmp:
46
63
  Enabled: false
47
- Style/MultilineMethodCallIndentation:
64
+ Performance/RegexpMatch:
65
+ Enabled: false
66
+ Layout/MultilineMethodCallIndentation:
48
67
  Enabled: true
49
- Style/MultilineOperationIndentation:
68
+ Layout/MultilineOperationIndentation:
50
69
  Enabled: true
51
70
  Lint/RescueException:
52
71
  Enabled: true
72
+ Lint/UselessAccessModifier:
73
+ Enabled: true
53
74
  Lint/ShadowingOuterLocalVariable:
54
75
  Enabled: true
55
76
  Style/FormatString:
56
77
  Enabled: true
57
- Lint/Eval:
78
+ Security/Eval:
58
79
  Enabled: true
59
-
data/.travis.yml CHANGED
@@ -9,11 +9,20 @@ gemfile:
9
9
  - Gemfile.rails4
10
10
  services:
11
11
  - redis-server
12
+ script:
13
+ - bundle exec rake rubocop
14
+ - bundle exec rake
15
+ - bundle exec rake forked_tests
16
+ # remove this for now as it is flaky
17
+ # passes locally on 2.3.5 on travis passes sometimes on 2.4 and always on 2.6.1
18
+ #- bundle exec rake benchmarks:memory
19
+ - bundle exec rake benchmarks
12
20
  before_install:
13
21
  - echo 'this is a hack to clear default bundler and force bundler 1.17.3'
14
22
  - ls /home/travis/.rvm/gems/
15
23
  - rm /home/travis/.rvm/gems/ruby-2.3.7@global/specifications/bundler-2.0.1.gemspec || true
16
- - rm /home/travis/.rvm/gems/ruby-2.5.4@global/specifications/bundler-2.0.1.gemspec || true
24
+ - rm /home/travis/.rvm/gems/ruby-2.4.6@global/specifications/bundler-2.0.1.gemspec || true
25
+ - rm /home/travis/.rvm/gems/ruby-2.5.5@global/specifications/bundler-2.0.1.gemspec || true
17
26
  - gem uninstall bundler || true
18
27
  - gem install bundler -v '1.17.3'
19
28
  - bundler --version
data/Gemfile CHANGED
@@ -5,5 +5,7 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in coverband.gemspec
6
6
  gemspec
7
7
  gem 'rails', '~>5'
8
- # this is used for testing gem tracking
8
+ # these gems are used for testing gem tracking
9
+ gem 'irb', require: false
10
+ gem 'pundit'
9
11
  gem 'rainbow', require: false
data/Gemfile.rails4 CHANGED
@@ -7,3 +7,4 @@ gemspec
7
7
  gem 'rails', '~>4'
8
8
  # this is used for testing gem tracking
9
9
  gem 'rainbow', require: false
10
+ gem 'pundit'
data/README.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  [![Build Status](https://travis-ci.org/danmayer/coverband.svg?branch=master)](https://travis-ci.org/danmayer/coverband)
6
6
  [![Coverage Status](https://coveralls.io/repos/github/danmayer/coverband/badge.svg?branch=master)](https://coveralls.io/github/danmayer/coverband?branch=master)
7
+ [![Maintainability](https://api.codeclimate.com/v1/badges/1e6682f9540d75f26da7/maintainability)](https://codeclimate.com/github/danmayer/coverband/maintainability)
7
8
 
8
9
  <p align="center">
9
10
  <a href="#key-features">Key Features</a> •
10
11
  <a href="#installation">Installation</a> •
11
12
  <a href="#coverage-report">Coverage Report</a> •
12
- <a href="#verify-correct-installation">Verify Correct Installation</a> •
13
13
  <a href="#advanced-config">Advanced Config</a> •
14
14
  <a href="#license">License</a> •
15
15
  <a href="/changes.md">Change Log / Roadmap</a>
@@ -24,9 +24,11 @@ A gem to measure production code usage, showing a counter for the number of time
24
24
  The primary goal of Coverband is giving deep insight into your production runtime usage of your application code, while having the least impact on performance possible.
25
25
 
26
26
  - Low performance overhead
27
- - Very simple setup and configuration
27
+ - Simple setup and configuration
28
28
  - Out of the box support for all standard code execution paths (web, cron, background jobs, rake tasks, etc)
29
+ - Splits load time (Rails eager load) and Run time metrics
29
30
  - Easy to understand actionable insights from the report
31
+ - Tracks Gem usage (still in experimental stages and not recommended for production)
30
32
  - Development mode, offers deep insight of code usage details (number of LOC execution during single request, etc) during development.
31
33
  - Mountable web interface to easily share reports
32
34
 
@@ -52,9 +54,17 @@ gem 'coverband'
52
54
 
53
55
  If [tracking gem usage](#collecting-gem--library-usage), be sure to include coverband before other gems you would like to track.
54
56
 
57
+ ## Upgrading to Latest
58
+
59
+ ### No custom code or middleware required
60
+
61
+ With older versions of coverband, projects would report to redis using rack or sidekiq middleware. After coverband 4.0, this should no longer be required and could cause performance issues. Reporting to redis is now automatically done within a background thread with no custom code needed.
62
+
63
+ See [changelog](https://github.com/danmayer/coverband/blob/master/changes.md).
64
+
55
65
  ## Rails
56
66
 
57
- The Railtie integration means you shouldn't need to do anything anything else other than ensure coverband is required after rails within your Gemfile.
67
+ The Railtie integration means you shouldn't need to do anything anything else other than ensure coverband is required after rails within your Gemfile. The only exception to this is gem tracking of `Bundle.require` which depends on requiring coverband within the application.rb. See [Collecting Gem / Library Usage](https://github.com/danmayer/coverband#collecting-gem--library-usage).
58
68
 
59
69
  ## Sinatra
60
70
 
@@ -64,7 +74,7 @@ For the best coverage you want this loaded as early as possible. I have been put
64
74
  require 'coverband'
65
75
  require File.dirname(__FILE__) + '/config/environment'
66
76
 
67
- use Coverband::Middleware
77
+ use Coverband::BackgroundMiddleware
68
78
  run ActionController::Dispatcher.new
69
79
  ```
70
80
 
@@ -88,17 +98,20 @@ Rails.application.routes.draw do
88
98
  end
89
99
  ```
90
100
 
101
+ or you can enable basic auth by setting `ENV['COVERBAND_PASSWORD']` or via your configuration `config.password = 'my_pass'`
102
+
91
103
  ### Coverband Web Endpoint
92
104
 
93
105
  The web endpoint is a barebones endpoint that you can either expose direct (after authentication) or you can just link to the actions you wish to expose. The index is intended as a example to showcase all the features.
94
106
 
95
- ![image](https://raw.github.com/danmayer/coverband/master/docs/coverband_web_update.png)
107
+ ![image](https://raw.github.com/danmayer/coverband/master/docs/coverband_web_ui.png)
96
108
 
97
109
  > The web index as available on the Coverband Demo site
98
110
 
99
111
  - **force coverage collection:** This triggers coverage collection on the current webserver process
100
- - **reload Coverband files:** This has Coverband reload files as configured (force reload of some files that might not capture Coverage on boot). This can be used to reload files on demand.
101
112
  - **clear coverage report:** This will clear the coverage data. This wipes out all collected data (**dangerous**)
113
+ - View individual file details
114
+ - **clear individual file coverage:** This will clear the details of the file you are looking at. This is helpful if you don't want to loose all Coverage data but made a change that you expect would impact a particular file.
102
115
 
103
116
  ### Rake Tasks
104
117
 
@@ -118,14 +131,6 @@ Index Page
118
131
  Details on an example Sinatra app
119
132
  ![image](https://raw.github.com/danmayer/coverband/master/docs/coverband_details.png)
120
133
 
121
- # Verify Correct Installation
122
-
123
- - boot up your application
124
- - run app and hit a controller (via a web request, at least one request must complete)
125
- - run `rake coverband:coverage` this will show app initialization coverage
126
- - make another request, or enough that your reporting frequency will trigger
127
- - run `rake coverband:coverage` and you should see coverage increasing for the endpoints you hit.
128
-
129
134
  # Coverband Demo
130
135
 
131
136
  Take Coverband for a spin on the live Heroku deployed [Coverband Demo](https://coverband-demo.herokuapp.com/). The [full source code for the demo](https://github.com/danmayer/coverband_demo) is available to help with installation, configuration, and understanding of basic usage.
@@ -251,6 +256,8 @@ By adding any files above you will get reporting on those files as part of your
251
256
 
252
257
  ### Collecting Gem / Library Usage
253
258
 
259
+ __WARNING:__ Gem Tracking is still in experimental stages and not recommended for production. We have some performance issues when view reports on large applications. Gem tracing also during background thread data collection has HIGH memory requirements, during report merging (seemingly around 128mb of extra memory, which is crazy). We recommend deploying WITHOUT `track_gems` first and only enabling it after confirming that Coverband is working and performing well.
260
+
254
261
  Gem usage can be tracked by enabling the `track_gems` config.
255
262
 
256
263
  ```
@@ -261,7 +268,20 @@ end
261
268
 
262
269
  The `track_gems` feature exposes a Gems tab in the report which prints out the percentage usage of each Gem. See demo [here](https://coverband-demo.herokuapp.com/coverage?#_Gems).
263
270
 
264
- When tracking gems, it is important that `Coverband#start` is called before the gems to be tracked are required. Since `Coverband#start` is automatically called by default when coverband is required, list coverband before the other gems to be tracked within your Gemfile. The exception to this are gems like rails and resque. Since coverband has some specific intergrations for these frameworks, these two gems should be required first.
271
+ When tracking gems, it is important that `Coverband#start` is called before the gems to be tracked are required. The best way to do this is to require coverband before Bundle.require is called. Within rails, require coverband within the application.rb like so:
272
+
273
+ ```ruby
274
+ require 'coverband'
275
+ Bundler.require(*Rails.groups)
276
+ ```
277
+
278
+ If you are using the resque integration, resque needs to be required before coverband since the integration will not run unless resque is loaded. Within the application.rb just require resque before coverband.
279
+
280
+ ```ruby
281
+ require 'resque'
282
+ require 'coverband'
283
+ Bundler.require(*Rails.groups)
284
+ ```
265
285
 
266
286
  The track_gems config only exposes the overall usage of a gem. In order to see the detail of each file, enable the `gem_details` flag.
267
287
 
@@ -335,6 +355,7 @@ If you submit a change please make sure the tests and benchmarks are passing.
335
355
  - view test coverage: `open coverage/index.html`
336
356
  - run the benchmarks before and after your change to see impact
337
357
  - `rake benchmarks`
358
+ - run a single test by line number like rspec: `bundle exec m test/coverband/reporters/html_test.rb:29`
338
359
 
339
360
  ### Known Issues
340
361
 
@@ -352,6 +373,10 @@ What is the coverage data in Redis?
352
373
 
353
374
  `Coverband.configuration.store.coverage`
354
375
 
376
+ ## Logo
377
+
378
+ The Coverband logo was created by [Dave Woodall](http://davewoodall.com). Thanks Dave!
379
+
355
380
  # License
356
381
 
357
382
  This is a MIT License project...
data/Rakefile CHANGED
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/gem_tasks'
4
-
5
4
  import 'test/benchmarks/benchmark.rake'
5
+ require 'rubocop/rake_task'
6
+
7
+ RuboCop::RakeTask.new
6
8
 
7
- task default: [:test, :benchmarks]
9
+ task default: %i[test]
10
+
11
+ task 'test:all': %i[rubocop test forked_tests benchmarks:memory benchmarks]
8
12
 
9
13
  task :test
10
14
  require 'rake/testtask'
@@ -17,9 +21,16 @@ Rake::TestTask.new(:test) do |test|
17
21
  test.verbose = true
18
22
  end
19
23
 
24
+ Rake::TestTask.new(:forked_tests) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.test_files = FileList['test/forked/**/*_test.rb']
27
+ test.verbose = true
28
+ end
29
+
20
30
  desc 'load irb with this gem'
21
31
  task :console do
22
- exec 'irb -I lib -r coverband'
32
+ puts 'running console'
33
+ exec 'bundle exec console'
23
34
  end
24
35
 
25
36
  # This is really just for testing and development because without configuration
data/changes.md CHANGED
@@ -16,6 +16,8 @@ Will be the fully modern release that drops maintenance legacy support in favor
16
16
  - add built-in support for easy loading via Railties
17
17
  - built in support for activejob, sidekiq, and other common frameworks
18
18
  - reduced configuration options
19
+ - support oneshot
20
+ - drop middleware figure out a way to kick off background without middelware
19
21
  - options on reporting
20
22
  - background reporting
21
23
  - or middleware reporting
@@ -47,6 +49,7 @@ Will be the fully modern release that drops maintenance legacy support in favor
47
49
  - move all code to work with relative paths leaving only stdlib Coverage working on full paths
48
50
  - add gem_safe_lists to track only some gems
49
51
  - add gem_details_safe list to report on details on some gems
52
+ - - display gems that are in loaded with 0 coverage, thanks @kbaum
50
53
 
51
54
  ### Coverband_jam_session
52
55
 
@@ -54,29 +57,61 @@ This is a possible gem to host experimental or more complex features, which woul
54
57
 
55
58
  Feature Ideas:
56
59
 
60
+ - per request coverage implemented via Ruby 2.6.0 coverage.clear https://bugs.ruby-lang.org/issues/15022
57
61
  - statsd adapters (it would allow passing in date ranges on usage)
58
- - move to SimpleCov console out, or make similar console tabular output
59
62
  - Possibly add ability to record code run for a given route
60
63
  - integrate recording with deploy tag or deploy timestamp
61
64
  - diff code usage across deployed versions
62
65
  - what methods increased usage or decreased
63
- - Improve client code api, around manual usage of sampling (like event usage)
64
66
  - ability to change the Coverband config at runtime by changing the config pushed to the Redis hash. In memory cache around the changes to only make that call periodically.
65
67
  - Opposed to just showing code usage on a route allow 'tagging' events which would record line coverage for that tag (this would allow tagging all code that modified an ActiveRecord model for example
66
68
  - additional adapters (tracepoint, ruby-profiler, etc)
67
- - code route tracing (entry point to all code executed for example /some_path -> code coverage of that path)
68
- - tagging of reported Coverage
69
- - allow only to collect coverage based on route (limiting or scoped coverage)
70
- - coverage over some other variable like a set of alpha users
69
+ - tagged coverage reports
70
+ - code route tracing (entry point to all code executed for example /some_path -> code coverage of that path)
71
+ - deploy git hash tagging of reported Coverage
72
+ - allow only to collect coverage based on route (limiting or scoped coverage)
73
+ - coverage over some other variable like a set of alpha users
71
74
  - document how to use this on staging / selenium test suite runs
72
75
  - possible add API to pull report at end of run
73
76
 
74
- # Alpha
77
+ # Alpha / Beta / Release Candidates
78
+
79
+ ### Coverband 4.2.1
80
+
81
+ - larger changes
82
+ - reduce memory usage
83
+ - fix issue where reports didn't include files with 0 activity
84
+ - updated runtime relavent lines and runtime percentages
85
+ - add Oneshot coverage support for Ruby 2.6.0 thanks @zwalker
86
+ - I would consider this our test oneshot release, please report any issues
87
+ - improved control over memory vs functionality
88
+ - oneshot support is the best memory and speed if you are on Ruby 2.6.*
89
+ - simulated_oneshot works for Ruby prior to 2.6.*, keeps lower runtime memory, at a trade of only being able to detect eager_load or runtime hits not both
90
+ - full hit tracking (The previous and current default), this uses more memory than other options, but provides full robust data
91
+
92
+
93
+ - small changes fixes
94
+ - further improvements on eager_loading detection, thanks @kbaum
95
+ - fix on ignore configuration options
96
+ - fix broken static server
97
+ - fix issue where clear and coverage trigger coverage reports
98
+ - improved logging
99
+ - fix on gem runtime code coverage support, thanks @kbaum
100
+ - fix sorting of runtime coverage
101
+ - add runtime coverage to gem summary pages
102
+ - documented redis TTL, thanks @jjb
103
+ - resolve regression on coverband rake tasks recording coverage
104
+ - improved runtime / eager loading tracking
105
+ - fix on small memory leaks
106
+ - added warnings that gem tracking isn't production ready
107
+ - built in support for basic auth on the web rack app, thanks @jjb
108
+ - don't clobber rake environment method definition, thanks @shioyama
109
+ - readme improvements, thanks @yuriyalekseyev
110
+ - fix duplicate requires thanks @yuriyalekseyev
111
+ - various cleanups and improvements, thanks @kbaum
112
+ - additional benchmarks to ensure proper memory handling, thanks @kbaum
113
+ - default redis TTL, thanks @jjb
75
114
 
76
- ### Coverband 4.3.0?
77
-
78
- - further improvements on eager_loading detection
79
- - ?
80
115
 
81
116
  # Released
82
117
 
@@ -96,7 +131,7 @@ Feature Ideas:
96
131
  - move from thread based reporter instance to process based instance
97
132
  - thanks Karl Baum for much of the above mentioned work
98
133
  - clear coverage on individual files
99
- - we have a logo, thanks Dave Woodall
134
+ - we have a logo, thanks Dave Woodall, http://davewoodall.com
100
135
 
101
136
  ### Coverband 4.1.1
102
137
 
data/coverband.gemspec CHANGED
@@ -28,12 +28,14 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency 'm'
29
29
  spec.add_development_dependency 'memory_profiler'
30
30
  spec.add_development_dependency 'minitest'
31
+ spec.add_development_dependency 'minitest-fork_executor'
31
32
  spec.add_development_dependency 'mocha', '~> 1.7.0'
32
33
  spec.add_development_dependency 'rack'
33
34
  spec.add_development_dependency 'rack-test'
34
35
  spec.add_development_dependency 'rake'
35
36
  spec.add_development_dependency 'resque'
36
- # temporarily needed to fun tests for classifier-reborn as part of benchmarks
37
+ spec.add_development_dependency 'rubocop'
38
+ # temporarily needed to run tests for classifier-reborn as part of benchmarks
37
39
  spec.add_development_dependency 'minitest-reporters'
38
40
 
39
41
  # TODO: used for benchmarking and tests I think we have other better benchmarking
@@ -4,26 +4,42 @@ module Coverband
4
4
  module Adapters
5
5
  class Base
6
6
  include Coverband::Utils::FilePathHelper
7
+
8
+ DATA_KEY = 'data'
9
+ FIRST_UPDATED_KEY = 'first_updated_at'
10
+ LAST_UPDATED_KEY = 'last_updated_at'
11
+ FILE_HASH = 'file_hash'
12
+ ABSTRACT_KEY = 'abstract'
13
+
7
14
  attr_accessor :type
8
15
 
9
16
  def initialize
10
17
  @file_hash_cache = {}
18
+ @type = Coverband::RUNTIME_TYPE
11
19
  end
12
20
 
13
21
  def clear!
14
- raise 'abstract'
22
+ raise ABSTRACT_KEY
15
23
  end
16
24
 
17
- def clear_file!(_file)
18
- raise 'abstract'
25
+ def clear_file!(_file = nil)
26
+ raise ABSTRACT_KEY
19
27
  end
20
28
 
21
29
  def migrate!
22
- raise 'abstract'
30
+ raise ABSTRACT_KEY
23
31
  end
24
32
 
25
33
  def size
26
- raise 'abstract'
34
+ raise ABSTRACT_KEY
35
+ end
36
+
37
+ def save_coverage
38
+ raise ABSTRACT_KEY
39
+ end
40
+
41
+ def coverage(_local_type = nil)
42
+ raise ABSTRACT_KEY
27
43
  end
28
44
 
29
45
  def size_in_mib
@@ -36,14 +52,10 @@ module Coverband
36
52
  # and the tradeoff has always been acceptable
37
53
  def save_report(report)
38
54
  data = report.dup
39
- data = merge_reports(data, get_report)
55
+ data = merge_reports(data, coverage)
40
56
  save_coverage(data)
41
57
  end
42
58
 
43
- def coverage
44
- get_report
45
- end
46
-
47
59
  def get_coverage_report
48
60
  data = Coverband.configuration.store.split_coverage(Coverband::TYPES)
49
61
  data.merge(Coverband::MERGED_TYPE => Coverband.configuration.store.merged_coverage(Coverband::TYPES))
@@ -53,47 +65,48 @@ module Coverband
53
65
  coverage.keys || []
54
66
  end
55
67
 
56
- # TODO: deprecate / remove?
57
- def covered_lines_for_file(file)
58
- Array(coverage.dig(file, 'data'))
59
- end
60
-
61
68
  protected
62
69
 
63
70
  def split_coverage(types)
64
71
  types.reduce({}) do |data, type|
65
- data.update(type => get_report(type))
72
+ if type == Coverband::RUNTIME_TYPE && Coverband.configuration.simulate_oneshot_lines_coverage
73
+ data.update(type => simulated_runtime_coverage)
74
+ else
75
+ data.update(type => coverage(type))
76
+ end
66
77
  end
67
78
  end
68
79
 
69
- def merged_coverage(types)
70
- types.reduce({}) do |data, type|
71
- merge_reports(data, get_report(type), skip_expansion: true)
80
+ def simulated_runtime_coverage
81
+ runtime_data = coverage(Coverband::RUNTIME_TYPE)
82
+ eager_data = coverage(Coverband::EAGER_TYPE)
83
+ eager_data.values do |vals|
84
+ vals['data'].map! { |line_coverage| line_coverage ? (0 - line_coverage) : line_coverage }
72
85
  end
86
+ merge_reports(runtime_data, eager_data, skip_expansion: true)
73
87
  end
74
88
 
75
- def save_coverage
76
- raise 'abstract'
77
- end
78
-
79
- def get_report
80
- raise 'abstract'
89
+ def merged_coverage(types)
90
+ types.reduce({}) do |data, type|
91
+ merge_reports(data, coverage(type), skip_expansion: true)
92
+ end
81
93
  end
82
94
 
83
95
  def file_hash(file)
84
96
  @file_hash_cache[file] ||= Digest::MD5.file(file).hexdigest
85
97
  end
86
98
 
99
+ # TODO: modify to extend report inline?
87
100
  def expand_report(report)
88
101
  expanded = {}
89
102
  report_time = Time.now.to_i
90
- updated_time = self.type == Coverband::EAGER_TYPE ? nil : report_time
103
+ updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
91
104
  report.each_pair do |key, line_data|
92
105
  extended_data = {
93
- 'first_updated_at' => report_time,
94
- 'last_updated_at' => updated_time,
95
- 'file_hash' => file_hash(key),
96
- 'data' => line_data
106
+ FIRST_UPDATED_KEY => report_time,
107
+ LAST_UPDATED_KEY => updated_time,
108
+ FILE_HASH => file_hash(key),
109
+ DATA_KEY => line_data
97
110
  }
98
111
  expanded[full_path_to_relative(key)] = extended_data
99
112
  end
@@ -101,12 +114,16 @@ module Coverband
101
114
  end
102
115
 
103
116
  def merge_reports(new_report, old_report, options = {})
117
+ # transparently update from RUNTIME_TYPE = nil to RUNTIME_TYPE = :runtime
118
+ # transparent update for format coveband_3_2
119
+ old_report = coverage(nil, override_type: nil) if old_report.nil? && type == Coverband::RUNTIME_TYPE
120
+
104
121
  new_report = expand_report(new_report) unless options[:skip_expansion]
105
122
  keys = (new_report.keys + old_report.keys).uniq
106
123
  keys.each do |file|
107
124
  new_report[file] = if new_report[file] &&
108
125
  old_report[file] &&
109
- new_report[file]['file_hash'] == old_report[file]['file_hash']
126
+ new_report[file][FILE_HASH] == old_report[file][FILE_HASH]
110
127
  merge_expanded_data(new_report[file], old_report[file])
111
128
  elsif new_report[file]
112
129
  new_report[file]
@@ -119,15 +136,22 @@ module Coverband
119
136
 
120
137
  def merge_expanded_data(new_expanded, old_expanded)
121
138
  {
122
- 'first_updated_at' => old_expanded['first_updated_at'],
123
- 'last_updated_at' => new_expanded['last_updated_at'],
124
- 'file_hash' => new_expanded['file_hash'],
125
- 'data' => array_add(new_expanded['data'], old_expanded['data'])
139
+ FIRST_UPDATED_KEY => old_expanded[FIRST_UPDATED_KEY],
140
+ LAST_UPDATED_KEY => new_expanded[LAST_UPDATED_KEY],
141
+ FILE_HASH => new_expanded[FILE_HASH],
142
+ DATA_KEY => array_add(new_expanded[DATA_KEY], old_expanded[DATA_KEY])
126
143
  }
127
144
  end
128
145
 
146
+ # TODO: This should only be 2 cases get our dup / not dups aligned
129
147
  def array_add(latest, original)
130
- latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
148
+ if Coverband.configuration.use_oneshot_lines_coverage
149
+ latest.map!.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
150
+ elsif Coverband.configuration.simulate_oneshot_lines_coverage
151
+ latest.map.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
152
+ else
153
+ latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
154
+ end
131
155
  end
132
156
  end
133
157
  end
@@ -28,6 +28,14 @@ module Coverband
28
28
  raise NotImplementedError, "FileStore doesn't support migrations"
29
29
  end
30
30
 
31
+ def coverage(_local_type = nil)
32
+ if File.exist?(path)
33
+ JSON.parse(File.read(path))
34
+ else
35
+ {}
36
+ end
37
+ end
38
+
31
39
  private
32
40
 
33
41
  attr_accessor :path
@@ -35,14 +43,6 @@ module Coverband
35
43
  def save_coverage(report)
36
44
  File.open(path, 'w') { |f| f.write(report.to_json) }
37
45
  end
38
-
39
- def get_report
40
- if File.exist?(path)
41
- JSON.parse(File.read(path))
42
- else
43
- {}
44
- end
45
- end
46
46
  end
47
47
  end
48
48
  end