coverband 0.0.26 → 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e9024d421423749a38d48b51ffb2e649e4ef7b12
4
- data.tar.gz: f2d9072445beb98a2399e82b282b321edbad21c1
3
+ metadata.gz: 9ab2f18c3f5f5663bb29a2335e7cd1cdac55f27d
4
+ data.tar.gz: 74eb1c7207c254af8c269906d40d8b069a83c8cd
5
5
  SHA512:
6
- metadata.gz: bc67df5a997a1a11baed1f28641e19dfd72d7430fd64f64acb79d2ad67baa3e09a29a9112f5049b4221ccc2a7c805777a9af7bed85744e9a8d82d9f86517562c
7
- data.tar.gz: ef6211e1506103bf8f7cce7efbad5580f9a58eeeb8c355bfc4a6f32e3f27b46dc9069a17fdb5ab51c1e877d3bc14af1845165fcc6ec8f11f46f061e91a8c285c
6
+ metadata.gz: 13f92b3215f32799e915997294e39b80773d08b6b31a2ec9ad31fee19e2bee9e29f9ef3ebbb8f06ae0da3ae1ecdecd04dc543cac41ce01e1a85d20f5270b980d
7
+ data.tar.gz: 59bb9f499b735e26e21c0d340f7d5cb2a3965446491001ea7a359fb0742d06fecec6cd0cb186f4b8a0e1300c09c12cf45a86a4556e031aee5b5789228772a559
data/README.md CHANGED
@@ -6,7 +6,7 @@ A gem to measure production code coverage. Coverband allows easy configuration t
6
6
  * Ignore directories to avoid overhead data collection on vendor, lib, etc.
7
7
  * Take a baseline to get initial app loading coverage.
8
8
 
9
- At the moment, Coverband relies on Ruby's `set_trace_func` hook. I attempted to use the standard lib's `Coverage` support but it proved buggy when sampling or stoping and starting collection. When [Coverage is patched](https://www.ruby-forum.com/topic/1811306) in future Ruby versions it would likely be better. Using `set_trace_func` has some limitations where it doesn't collect covered lines, but I have been impressed with the coverage it shows for both Sinatra and Rails applications.
9
+ At the moment, Coverband relies on Ruby's `set_trace_func` hook. I attempted to use the standard lib's `Coverage` support but it proved buggy when sampling or stoping and starting collection. When [Coverage is patched](https://bugs.ruby-lang.org/issues/9572) in future Ruby versions it would likely be better. Using `set_trace_func` has some limitations where it doesn't collect covered lines, but I have been impressed with the coverage it shows for both Sinatra and Rails applications.
10
10
 
11
11
  ###### Success:
12
12
  After running in production for 30 minutes, we were able very easily delete 2000 LOC after looking through the data. We expect to be able to clean up much more after it has collected more data.
@@ -256,13 +256,19 @@ If you are trying to debug locally wondering what code is being run during a req
256
256
 
257
257
  ## Resources
258
258
 
259
+ ##### Ruby Std-lib Coverage
260
+
261
+ * [Fixed bug causing segfaults on 1.9.X](https://www.ruby-forum.com/topic/1811306)
262
+ * [Current Coverage Bug causing issues on 2.1.1](https://bugs.ruby-lang.org/issues/9572)
263
+ * [Ruby Coverage docs](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/coverage/rdoc/Coverage.html)
264
+
265
+ ##### other
266
+
259
267
  * [erb code coverage](http://stackoverflow.com/questions/13030909/how-to-test-code-coverage-for-rails-erb-templates)
260
268
  * [more erb code coverage](https://github.com/colszowka/simplecov/issues/38)
261
269
  * [erb syntax](http://stackoverflow.com/questions/7996695/rails-erb-syntax) parse out and mark lines as important
262
270
  * [ruby 2 tracer](https://github.com/brightbox/deb-ruby2.0/blob/master/lib/tracer.rb)
263
271
  * [coveralls hosted code coverage tracking](https://coveralls.io/docs/ruby) currently for test coverage but might be a good partner for production coverage
264
- * [bug in Ruby's stl-lib Coverage, needs to be fixed to be more accurate](https://www.ruby-forum.com/topic/1811306)
265
- * [Ruby Coverage docs](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/coverage/rdoc/Coverage.html)
266
272
  * [simplecov walk through](http://www.tamingthemindmonkey.com/2011/09/27/ruby-code-coverage-using-simplecov) copy some of the syntax sugar setup for cover band
267
273
  * [Jruby coverage bug](http://jira.codehaus.org/browse/JRUBY-6106?page=com.atlassian.jira.plugin.system.issuetabpanels:changehistory-tabpanel)
268
274
  * [learn from oboe ruby code](https://github.com/appneta/oboe-ruby#writing-custom-instrumentation)
@@ -1,21 +1,6 @@
1
1
  module Coverband
2
2
  class Base
3
-
4
- def initialize(options = {})
5
- @project_directory = File.expand_path(Coverband.configuration.root)
6
- @enabled = false
7
- @tracer_set = false
8
- @files = {}
9
- @file_usage = Hash.new(0)
10
- @file_line_usage = {}
11
- @startup_delay = Coverband.configuration.startup_delay
12
- @ignore_patterns = Coverband.configuration.ignore
13
- @sample_percentage = Coverband.configuration.percentage
14
- @reporter = Coverband::RedisStore.new(Coverband.configuration.redis) if Coverband.configuration.redis
15
- @stats = Coverband.configuration.stats
16
- @verbose = Coverband.configuration.verbose
17
- @logger = Coverband.configuration.logger || Logger.new(STDOUT)
18
- end
3
+ include Singleton
19
4
 
20
5
  def start
21
6
  @enabled = true
@@ -40,7 +25,26 @@ module Coverband
40
25
  @enabled = false
41
26
  end
42
27
 
43
- protected
28
+ def extended?
29
+ false
30
+ end
31
+
32
+ def reset_instance
33
+ @project_directory = File.expand_path(Coverband.configuration.root)
34
+ @enabled = false
35
+ @tracer_set = false
36
+ @files = {}
37
+ @file_usage = Hash.new(0)
38
+ @file_line_usage = {}
39
+ @startup_delay = Coverband.configuration.startup_delay
40
+ @ignore_patterns = Coverband.configuration.ignore
41
+ @sample_percentage = Coverband.configuration.percentage
42
+ @reporter = Coverband::RedisStore.new(Coverband.configuration.redis) if Coverband.configuration.redis
43
+ @stats = Coverband.configuration.stats
44
+ @verbose = Coverband.configuration.verbose
45
+ @logger = Coverband.configuration.logger || Logger.new(STDOUT)
46
+ self
47
+ end
44
48
 
45
49
  def configure_sampling
46
50
  if @startup_delay!=0 || (rand * 100.0) > @sample_percentage
@@ -65,46 +69,6 @@ module Coverband
65
69
  end
66
70
  end
67
71
 
68
- def set_tracer
69
- unless @tracer_set
70
- set_trace_func proc { |event, file, line, id, binding, classname|
71
- add_file(file, line)
72
- }
73
- @tracer_set = true
74
- end
75
- end
76
-
77
- def unset_tracer
78
- if @tracer_set
79
- set_trace_func(nil)
80
- @tracer_set = false
81
- end
82
- end
83
-
84
- def add_file(file, line)
85
- if !file.match(/(\/gems\/|internal\:prelude)/) && file.match(@project_directory) && !@ignore_patterns.any?{|pattern| file.match(/#{pattern}/) }
86
- if @verbose
87
- @file_usage[file] += 1
88
- @file_line_usage[file] = Hash.new(0) unless @file_line_usage.include?(file)
89
- @file_line_usage[file][line] += 1
90
- end
91
- if @files.include?(file)
92
- @files[file] << line unless @files.include?(line)
93
- else
94
- @files[file] = [line]
95
- end
96
- end
97
- end
98
-
99
- def output_file_line_usage
100
- @logger.info "coverband debug coverband file:line usage:"
101
- @file_line_usage.sort_by {|_key, value| value.length}.each do |pair|
102
- file = pair.first
103
- lines = pair.last
104
- @logger.info "file: #{file} => #{lines.sort_by {|_key, value| value}}"
105
- end
106
- end
107
-
108
72
  def report_coverage
109
73
  unless @enabled
110
74
  @logger.info "coverage disabled" if @verbose
@@ -141,5 +105,62 @@ module Coverband
141
105
  @logger.info "error: #{err.inspect} #{err.message}"
142
106
  end
143
107
  end
108
+
109
+ protected
110
+
111
+ def set_tracer
112
+ unless @tracer_set
113
+ set_trace_func proc { |event, file, line, id, binding, classname|
114
+ add_file(file, line)
115
+ }
116
+ @tracer_set = true
117
+ end
118
+ end
119
+
120
+ def unset_tracer
121
+ if @tracer_set
122
+ set_trace_func(nil)
123
+ @tracer_set = false
124
+ end
125
+ end
126
+
127
+ def add_from_tracepoint(trace_point)
128
+ add_file(trace_point.path, trace_point.lineno)
129
+ end
130
+
131
+ def add_file(file, line)
132
+ if !file.match(/(\/gems\/|internal\:prelude)/) && file.match(@project_directory) && !@ignore_patterns.any?{|pattern| file.match(/#{pattern}/) }
133
+ add_file_without_checks(file, line)
134
+ end
135
+ end
136
+
137
+ def add_file_without_checks(file, line)
138
+ if @verbose
139
+ @file_usage[file] += 1
140
+ @file_line_usage[file] = Hash.new(0) unless @file_line_usage.include?(file)
141
+ @file_line_usage[file][line] += 1
142
+ end
143
+ if @files.include?(file)
144
+ @files[file] << line unless @files.include?(line)
145
+ else
146
+ @files[file] = [line]
147
+ end
148
+ end
149
+
150
+ def output_file_line_usage
151
+ @logger.info "coverband debug coverband file:line usage:"
152
+ @file_line_usage.sort_by {|_key, value| value.length}.each do |pair|
153
+ file = pair.first
154
+ lines = pair.last
155
+ @logger.info "file: #{file} => #{lines.sort_by {|_key, value| value}}"
156
+ end
157
+ end
158
+
159
+ private
160
+
161
+ def initialize
162
+ reset_instance
163
+ end
164
+
144
165
  end
145
166
  end
@@ -1,16 +1,15 @@
1
1
  module Coverband
2
- class Middleware < Base
3
-
2
+ class Middleware
3
+
4
4
  def initialize(app)
5
5
  @app = app
6
- super
7
6
  end
8
7
 
9
8
  def call(env)
10
- configure_sampling
11
- record_coverage
9
+ Coverband::Base.instance.configure_sampling
10
+ Coverband::Base.instance.record_coverage
12
11
  results = @app.call(env)
13
- report_coverage
12
+ Coverband::Base.instance.report_coverage
14
13
  results
15
14
  end
16
15
 
@@ -1,3 +1,3 @@
1
1
  module Coverband
2
- VERSION = "0.0.26"
2
+ VERSION = "0.1.0.pre"
3
3
  end
@@ -3,7 +3,7 @@ require File.expand_path('../test_helper', File.dirname(__FILE__))
3
3
  class BaseTest < Test::Unit::TestCase
4
4
 
5
5
  should "start should enable coverage" do
6
- coverband = Coverband::Base.new
6
+ coverband = Coverband::Base.instance.reset_instance
7
7
  assert_equal false, coverband.instance_variable_get("@enabled")
8
8
  coverband.expects(:record_coverage).once
9
9
  coverband.start
@@ -11,7 +11,7 @@ class BaseTest < Test::Unit::TestCase
11
11
  end
12
12
 
13
13
  should "stop should disable coverage" do
14
- coverband = Coverband::Base.new
14
+ coverband = Coverband::Base.instance.reset_instance
15
15
  assert_equal false, coverband.instance_variable_get("@enabled")
16
16
  coverband.expects(:record_coverage).once
17
17
  coverband.start
@@ -23,7 +23,7 @@ class BaseTest < Test::Unit::TestCase
23
23
 
24
24
  should "allow for sampling with a block and enable when 100 percent sample" do
25
25
  logger = Logger.new(STDOUT)
26
- coverband = Coverband::Base.new
26
+ coverband = Coverband::Base.instance.reset_instance
27
27
  coverband.instance_variable_set("@sample_percentage", 100.0)
28
28
  coverband.instance_variable_set("@verbose", true)
29
29
  coverband.instance_variable_set("@logger", logger)
@@ -36,7 +36,7 @@ class BaseTest < Test::Unit::TestCase
36
36
 
37
37
  should "allow reporting with start stop save" do
38
38
  logger = Logger.new(STDOUT)
39
- coverband = Coverband::Base.new
39
+ coverband = Coverband::Base.instance.reset_instance
40
40
  coverband.instance_variable_set("@sample_percentage", 100.0)
41
41
  coverband.instance_variable_set("@verbose", true)
42
42
  coverband.instance_variable_set("@logger", logger)
@@ -50,7 +50,7 @@ class BaseTest < Test::Unit::TestCase
50
50
  end
51
51
 
52
52
  should "allow reporting to redis start stop save" do
53
- coverband = Coverband::Base.new
53
+ coverband = Coverband::Base.instance.reset_instance
54
54
  coverband.instance_variable_set("@sample_percentage", 100.0)
55
55
  coverband.instance_variable_set("@verbose", true)
56
56
  store = Coverband::RedisStore.new(Redis.new)
@@ -1,18 +1,18 @@
1
1
  require File.expand_path('../test_helper', File.dirname(__FILE__))
2
2
  require 'rack'
3
- FAKE_RACK_APP_PATH = File.expand_path('../fake_app/basic_rack.rb', File.dirname(__FILE__))
4
- require FAKE_RACK_APP_PATH
5
3
 
6
4
  class MiddlewareTest < Test::Unit::TestCase
7
5
 
8
6
  should "call app" do
9
7
  request = Rack::MockRequest.env_for("/anything.json")
8
+ Coverband::Base.instance.reset_instance
10
9
  middleware = Coverband::Middleware.new(fake_app)
11
10
  results = middleware.call(request)
12
11
  assert_equal "/anything.json", results.last
13
12
  end
14
13
 
15
14
  should 'pass all rack lint checks' do
15
+ Coverband::Base.instance.reset_instance
16
16
  app = Rack::Lint.new(Coverband::Middleware.new(fake_app))
17
17
  env = Rack::MockRequest.env_for('/hello')
18
18
  app.call(env)
@@ -20,62 +20,71 @@ class MiddlewareTest < Test::Unit::TestCase
20
20
 
21
21
  should 'always be enabled with sample percentage of 100' do
22
22
  request = Rack::MockRequest.env_for("/anything.json")
23
+ Coverband::Base.instance.reset_instance
23
24
  middleware = Coverband::Middleware.new(fake_app)
24
- assert_equal false, middleware.instance_variable_get("@enabled")
25
- middleware.instance_variable_set("@sample_percentage", 100.0)
25
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@enabled")
26
+ Coverband::Base.instance.instance_variable_set("@sample_percentage", 100.0)
26
27
  results = middleware.call(request)
27
- assert_equal true, middleware.instance_variable_get("@enabled")
28
+ assert_equal true, Coverband::Base.instance.instance_variable_get("@enabled")
28
29
  end
29
30
 
30
31
  should 'never be enabled with sample percentage of 0' do
31
32
  request = Rack::MockRequest.env_for("/anything.json")
33
+ Coverband::Base.instance.reset_instance
32
34
  middleware = Coverband::Middleware.new(fake_app)
33
- assert_equal false, middleware.instance_variable_get("@enabled")
34
- middleware.instance_variable_set("@sample_percentage", 0.0)
35
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@enabled")
36
+ Coverband::Base.instance.instance_variable_set("@sample_percentage", 0.0)
35
37
  results = middleware.call(request)
36
- assert_equal false, middleware.instance_variable_get("@enabled")
38
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@enabled")
37
39
  end
38
40
 
39
41
  should 'always unset function when sampling' do
40
42
  request = Rack::MockRequest.env_for("/anything.json")
43
+ Coverband::Base.instance.reset_instance
41
44
  middleware = Coverband::Middleware.new(fake_app)
42
- assert_equal false, middleware.instance_variable_get("@tracer_set")
43
- middleware.instance_variable_set("@sample_percentage", 100.0)
45
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@tracer_set")
46
+ Coverband::Base.instance.instance_variable_set("@sample_percentage", 100.0)
44
47
  results = middleware.call(request)
45
- assert_equal false, middleware.instance_variable_get("@tracer_set")
48
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@tracer_set")
46
49
  end
47
50
 
48
51
  should 'always unset function when not sampling' do
49
52
  request = Rack::MockRequest.env_for("/anything.json")
53
+ Coverband::Base.instance.reset_instance
50
54
  middleware = Coverband::Middleware.new(fake_app)
51
- assert_equal false, middleware.instance_variable_get("@tracer_set")
55
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@tracer_set")
52
56
  middleware.instance_variable_set("@sample_percentage", 0.0)
53
57
  results = middleware.call(request)
54
- assert_equal false, middleware.instance_variable_get("@tracer_set")
58
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@tracer_set")
55
59
  end
56
60
 
57
61
  should 'always record coverage, set trace func, and add_files when sampling' do
58
62
  request = Rack::MockRequest.env_for("/anything.json")
59
- middleware = Coverband::Middleware.new(fake_app_with_lines)
60
- assert_equal false, middleware.instance_variable_get("@enabled")
61
- middleware.instance_variable_set("@sample_percentage", 100.0)
62
- middleware.expects(:add_file).at_least_once
63
+ Coverband::Base.instance.reset_instance
64
+ middleware = Coverband::Middleware.new(fake_app)
65
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@enabled")
66
+ Coverband::Base.instance.instance_variable_set("@sample_percentage", 100.0)
67
+ Coverband::Base.instance.expects(:add_file).at_least_once
63
68
  results = middleware.call(request)
64
- assert_equal true, middleware.instance_variable_get("@enabled")
69
+ assert_equal true, Coverband::Base.instance.instance_variable_get("@enabled")
65
70
  end
66
71
 
67
72
  should 'always report coverage when sampling' do
68
73
  request = Rack::MockRequest.env_for("/anything.json")
69
- middleware = Coverband::Middleware.new(fake_app_with_lines)
70
- assert_equal false, middleware.instance_variable_get("@enabled")
71
- middleware.instance_variable_set("@sample_percentage", 100.0)
74
+ Coverband::Base.instance.reset_instance
75
+
76
+ file_with_path = File.expand_path('../../lib/coverband/middleware.rb', File.dirname(__FILE__))
77
+
78
+ middleware = Coverband::Middleware.new(fake_app)
79
+ assert_equal false, Coverband::Base.instance.instance_variable_get("@enabled")
80
+ Coverband::Base.instance.instance_variable_set("@sample_percentage", 100.0)
72
81
  fake_redis = Redis.new
73
- middleware.instance_variable_set("@reporter", Coverband::RedisStore.new(fake_redis))
82
+ Coverband::Base.instance.instance_variable_set("@reporter", Coverband::RedisStore.new(fake_redis))
74
83
  fake_redis.stubs(:info).returns({'redis_version' => 3.0})
75
84
  fake_redis.expects(:sadd).at_least_once
76
- fake_redis.expects(:sadd).at_least_once.with("coverband.#{FAKE_RACK_APP_PATH}", [4,5,6])
85
+ fake_redis.expects(:sadd).at_least_once.with("coverband.#{file_with_path}", [11, 11, 11, 12])
77
86
  results = middleware.call(request)
78
- assert_equal true, middleware.instance_variable_get("@enabled")
87
+ assert_equal true, Coverband::Base.instance.instance_variable_get("@enabled")
79
88
  end
80
89
 
81
90
  private
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coverband
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.26
4
+ version: 0.1.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Mayer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-02 00:00:00.000000000 Z
11
+ date: 2014-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -167,9 +167,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
167
167
  version: '0'
168
168
  required_rubygems_version: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - ">="
170
+ - - ">"
171
171
  - !ruby/object:Gem::Version
172
- version: '0'
172
+ version: 1.3.1
173
173
  requirements: []
174
174
  rubyforge_project:
175
175
  rubygems_version: 2.2.2