coverband 2.0.3 → 3.0.0.alpha

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +73 -0
  4. data/.travis.yml +0 -3
  5. data/README.md +3 -3
  6. data/changes.md +65 -49
  7. data/coverband.gemspec +1 -1
  8. data/lib/coverband.rb +9 -6
  9. data/lib/coverband/adapters/base.rb +22 -2
  10. data/lib/coverband/adapters/file_store.rb +11 -11
  11. data/lib/coverband/adapters/redis_store.rb +22 -57
  12. data/lib/coverband/collectors/coverage.rb +57 -53
  13. data/lib/coverband/configuration.rb +6 -14
  14. data/lib/coverband/integrations/background.rb +7 -0
  15. data/lib/coverband/{middleware.rb → integrations/middleware.rb} +1 -3
  16. data/lib/coverband/reporters/base.rb +37 -82
  17. data/lib/coverband/reporters/console_report.rb +3 -0
  18. data/lib/coverband/reporters/simple_cov_report.rb +4 -3
  19. data/lib/coverband/reporters/web.rb +38 -35
  20. data/lib/coverband/utils/s3_report_writer.rb +59 -0
  21. data/lib/coverband/{tasks.rb → utils/tasks.rb} +0 -0
  22. data/lib/coverband/version.rb +1 -1
  23. data/test/benchmarks/benchmark.rake +3 -3
  24. data/test/test_helper.rb +18 -17
  25. data/test/unit/adapters_base_test.rb +29 -0
  26. data/test/unit/adapters_file_store_test.rb +2 -2
  27. data/test/unit/adapters_redis_store_test.rb +14 -51
  28. data/test/unit/collectors_coverage_test.rb +3 -107
  29. data/test/unit/configuration_test.rb +2 -9
  30. data/test/unit/full_stack_test.rb +47 -0
  31. data/test/unit/middleware_test.rb +21 -57
  32. data/test/unit/reports_base_test.rb +12 -71
  33. data/test/unit/reports_console_test.rb +9 -22
  34. data/test/unit/reports_simple_cov_test.rb +3 -37
  35. data/test/unit/reports_web_test.rb +4 -0
  36. data/test/unit/{s3_report_writer_test.rb → utils_s3_report_writer_test.rb} +1 -1
  37. metadata +29 -18
  38. data/lib/coverband/adapters/memory_cache_store.rb +0 -53
  39. data/lib/coverband/collectors/base.rb +0 -126
  40. data/lib/coverband/collectors/trace.rb +0 -122
  41. data/lib/coverband/s3_report_writer.rb +0 -49
  42. data/test/unit/adapters_memory_cache_store_test.rb +0 -66
  43. data/test/unit/collectors_base_test.rb +0 -104
  44. data/test/unit/collectors_trace_test.rb +0 -106
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ module Utils
5
+ ###
6
+ # TODO: this is currently a html report writer
7
+ # this should support writing coverage the current method should be fine
8
+ # to write every report to S3 and sum them later or use the 2 pass
9
+ # method we do for redis if in a background thread
10
+ ###
11
+ class S3ReportWriter
12
+ def initialize(bucket_name, options = {})
13
+ @bucket_name = bucket_name
14
+ @region = options[:region]
15
+ @access_key_id = options[:access_key_id]
16
+ @secret_access_key = options[:secret_access_key]
17
+ begin
18
+ require 'aws-sdk'
19
+ rescue StandardError
20
+ err_msg = 'coverband requires aws-sdk in order use S3ReportWriter.'
21
+ Coverband.configuration.logger.error err_msg
22
+ return
23
+ end
24
+ end
25
+
26
+ def persist!
27
+ object.put(body: coverage_content)
28
+ end
29
+
30
+ private
31
+
32
+ def coverage_content
33
+ version = Gem::Specification.find_by_name('simplecov-html').version.version
34
+ File.read("#{SimpleCov.coverage_dir}/index.html").gsub("./assets/#{version}/", '')
35
+ rescue StandardError
36
+ File.read("#{SimpleCov.coverage_dir}/index.html").to_s.gsub('./assets/0.10.1/', '')
37
+ end
38
+
39
+ def object
40
+ bucket.object('coverband/index.html')
41
+ end
42
+
43
+ def s3
44
+ client_options = {
45
+ region: @region,
46
+ access_key_id: @access_key_id,
47
+ secret_access_key: @secret_access_key
48
+ }
49
+ resource_options = { client: Aws::S3::Client.new(client_options) }
50
+ resource_options = {} if client_options.values.any?(&:nil?)
51
+ Aws::S3::Resource.new(resource_options)
52
+ end
53
+
54
+ def bucket
55
+ s3.bucket(@bucket_name)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Coverband
4
- VERSION = '2.0.3'
4
+ VERSION = '3.0.0.alpha'
5
5
  end
@@ -155,18 +155,18 @@ namespace :benchmarks do
155
155
  Benchmark.ips do |x|
156
156
  x.config(time: 12, warmup: 5, suite: suite)
157
157
  x.report 'coverband' do
158
- Coverband::Collectors::Base.instance.sample do
158
+ Coverband::Collectors::Coverage.instance.sample do
159
159
  work
160
160
  end
161
161
  end
162
- Coverband::Collectors::Base.instance.stop
162
+ Coverband::Collectors::Coverage.instance.stop
163
163
  x.report 'no coverband' do
164
164
  work
165
165
  end
166
166
  x.hold! 'temp_results' if hold_work
167
167
  x.compare!
168
168
  end
169
- Coverband::Collectors::Base.instance.reset_instance
169
+ Coverband::Collectors::Coverage.instance.reset_instance
170
170
  end
171
171
 
172
172
  def fake_line_numbers
@@ -14,7 +14,7 @@ SimpleCov.start do
14
14
  add_filter '/config/'
15
15
  end
16
16
 
17
- TEST_COVERAGE_FILE = '/tmp/fake_file.json'
17
+ TEST_COVERAGE_FILE = '/tmp/fake_file.json'.freeze
18
18
 
19
19
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
20
20
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -37,33 +37,34 @@ def test(name, &block)
37
37
  end
38
38
  end
39
39
 
40
+ def example_line
41
+ [0, 1, 2]
42
+ end
43
+
44
+ def basic_coverage
45
+ { 'app_path/dog.rb' => example_line }
46
+ end
47
+
40
48
  def fake_redis
41
49
  @redis ||= begin
42
50
  redis = OpenStruct.new
43
- # mocha requires method to exist to mock it
44
- def redis.smembers(key); end
45
- def redis.hgetall(key); end
46
51
  redis
47
52
  end
48
53
  end
49
54
 
50
- def fake_coverband_members
51
- ['/Users/danmayer/projects/hearno/script/tester.rb',
52
- '/Users/danmayer/projects/hearno/app/controllers/application_controller.rb',
53
- '/Users/danmayer/projects/hearno/app/models/account.rb']
54
- end
55
-
56
55
  def fake_coverage_report
57
- { '/Users/danmayer/projects/hearno/script/tester.rb' => [1, nil, 1, 1, nil, nil, nil] }
56
+ file_name = '/Users/danmayer/projects/hearno/script/tester.rb'
57
+ { file_name => [1, nil, 1, 1, nil, nil, nil] }
58
58
  end
59
59
 
60
60
  require 'coverband'
61
61
 
62
62
  Coverband.configure do |config|
63
- config.root = Dir.pwd
64
- config.root_paths = ['/app/']
65
- config.ignore = ['vendor']
66
- config.percentage = 100.0
67
- config.reporter = 'std_out'
68
- config.store = Coverband::Adapters::RedisStore.new(Redis.new)
63
+ config.root = Dir.pwd
64
+ config.s3_bucket = nil
65
+ config.root_paths = ['/app_path/']
66
+ config.ignore = ['vendor']
67
+ config.reporting_frequency = 100.0
68
+ config.reporter = 'std_out'
69
+ config.store = Coverband::Adapters::RedisStore.new(Redis.new)
69
70
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../test_helper', File.dirname(__FILE__))
4
+
5
+ class AdaptersBaseTest < Test::Unit::TestCase
6
+ def setup
7
+ @test_file_path = '/tmp/coverband_filestore_test_path.json'
8
+ @store = Coverband::Adapters::FileStore.new(@test_file_path)
9
+ end
10
+
11
+ def test_covered_merge
12
+ old_report = { '/Users/danmayer/projects/coverband_demo/config/coverband.rb' => [5, 7, nil],
13
+ '/Users/danmayer/projects/coverband_demo/config/initializers/assets.rb' => [5, 5, nil],
14
+ '/Users/danmayer/projects/coverband_demo/config/initializers/cookies_serializer.rb' => [5, 5, nil] }
15
+ new_report = { '/Users/danmayer/projects/coverband_demo/config/coverband.rb' => [5, 7, nil],
16
+ '/Users/danmayer/projects/coverband_demo/config/initializers/filter_logging.rb' => [5, 5, nil],
17
+ '/Users/danmayer/projects/coverband_demo/config/initializers/wrap_parameters.rb' => [5, 5, nil],
18
+ '/Users/danmayer/projects/coverband_demo/app/controllers/application_controller.rb' => [5, 5, nil] }
19
+ expected_result = {
20
+ '/Users/danmayer/projects/coverband_demo/app/controllers/application_controller.rb' => [5, 5, nil],
21
+ '/Users/danmayer/projects/coverband_demo/config/coverband.rb' => [10, 14, nil],
22
+ '/Users/danmayer/projects/coverband_demo/config/initializers/assets.rb' => [5, 5, nil],
23
+ '/Users/danmayer/projects/coverband_demo/config/initializers/cookies_serializer.rb' => [5, 5, nil],
24
+ '/Users/danmayer/projects/coverband_demo/config/initializers/filter_logging.rb' => [5, 5, nil],
25
+ '/Users/danmayer/projects/coverband_demo/config/initializers/wrap_parameters.rb' => [5, 5, nil]
26
+ }
27
+ assert_equal expected_result, @store.send(:merge_reports, new_report, old_report)
28
+ end
29
+ end
@@ -28,8 +28,8 @@ class AdaptersFileStoreTest < Test::Unit::TestCase
28
28
  end
29
29
 
30
30
  def test_save_report
31
- @store.save_report('cat.rb' => { 1 => 1 })
32
- assert_equal @store.covered_lines_for_file('cat.rb')['1'], 1
31
+ @store.send(:save_report, 'cat.rb' => [0,1])
32
+ assert_equal @store.covered_lines_for_file('cat.rb')[1], 1
33
33
  end
34
34
 
35
35
  private
@@ -5,42 +5,37 @@ require File.expand_path('../test_helper', File.dirname(__FILE__))
5
5
  class RedisTest < Test::Unit::TestCase
6
6
  BASE_KEY = Coverband::Adapters::RedisStore::BASE_KEY
7
7
 
8
- def example_hash
9
- {'1' => '1', '2' => '2'}
10
- end
11
-
12
8
  def setup
13
9
  @redis = Redis.new
14
- @redis.flushdb
15
10
  @store = Coverband::Adapters::RedisStore.new(@redis)
11
+ @store.clear!
16
12
  end
17
13
 
18
14
  def test_coverage
19
- @redis.sadd(BASE_KEY, 'dog.rb')
20
- @store.send(:pipelined_save, combined_report)
21
- expected = {'dog.rb' => example_hash}
15
+ expected = basic_coverage
16
+ @store.save_report(expected)
22
17
  assert_equal expected, @store.coverage
23
18
  end
24
19
 
25
- def test_covered_lines_for_file
26
- @store.send(:pipelined_save, combined_report)
27
- assert_equal [["1", "1"], ["2", "2"]], @store.covered_lines_for_file('dog.rb').sort
20
+ def test_coverage_increments
21
+ expected = basic_coverage
22
+ @store.save_report(expected)
23
+ assert_equal expected, @store.coverage
24
+ @store.save_report(expected)
25
+ assert_equal [0, 2, 4], @store.coverage['app_path/dog.rb']
28
26
  end
29
27
 
30
- def test_covered_lines_for_file__hash
31
- @redis.mapped_hmset("#{BASE_KEY}.dog.rb", '1' => 1, '2' => 2)
32
- @store = Coverband::Adapters::RedisStore.new(@redis)
33
- expected = [%w[1 1], %w[2 2]]
34
- assert_equal expected, @store.covered_lines_for_file('dog.rb').sort
28
+ def test_covered_lines_for_file
29
+ expected = basic_coverage
30
+ @store.save_report(expected)
31
+ assert_equal example_line, @store.covered_lines_for_file('app_path/dog.rb')
35
32
  end
36
33
 
37
34
  def test_covered_lines_when_null
38
- empty_hash = {}
39
- assert_equal empty_hash, @store.covered_lines_for_file('dog.rb')
35
+ assert_equal nil, @store.covered_lines_for_file('app_path/dog.rb')
40
36
  end
41
37
 
42
38
  def test_clear
43
- @redis.expects(:smembers).with(BASE_KEY).once.returns([])
44
39
  @redis.expects(:del).with(BASE_KEY).once
45
40
  @store.clear!
46
41
  end
@@ -63,35 +58,3 @@ class RedisTest < Test::Unit::TestCase
63
58
  }
64
59
  end
65
60
  end
66
-
67
- class RedisStoreTestV3Hash < RedisTest
68
- def setup
69
- @redis = Redis.current.tap do |redis|
70
- redis.stubs(:sadd).with(anything, anything)
71
- end
72
-
73
- @store = Coverband::Adapters::RedisStore.new(@redis)
74
- end
75
-
76
- test 'it stores the files into coverband' do
77
- @redis.expects(:sadd).with(BASE_KEY, [
78
- '/Users/danmayer/projects/cover_band_server/app.rb',
79
- '/Users/danmayer/projects/cover_band_server/server.rb'
80
- ])
81
-
82
- @store.save_report(test_data)
83
- end
84
-
85
- test 'it stores the file lines of the file app.rb' do
86
- @redis.expects(:mapped_hmset).with(
87
- "#{BASE_KEY}./Users/danmayer/projects/cover_band_server/app.rb",
88
- '54' => 1, '55' => 2
89
- )
90
- @redis.expects(:mapped_hmset).with(
91
- "#{BASE_KEY}./Users/danmayer/projects/cover_band_server/server.rb",
92
- '5' => 1
93
- )
94
-
95
- @store.save_report(test_data)
96
- end
97
- end
@@ -9,18 +9,16 @@ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.3.0')
9
9
 
10
10
  def setup
11
11
  Coverband.configure do |config|
12
- config.collector = 'coverage'
13
- config.store = Coverband::Adapters::RedisStore.new(Redis.new)
12
+ config.store = Coverband::Adapters::RedisStore.new(Redis.new)
14
13
  end
15
- @coverband = Coverband::Collectors::Base.instance.reset_instance
14
+ @coverband = Coverband::Collectors::Coverage.instance.reset_instance
16
15
  end
17
16
 
18
17
  def teardown
19
18
  Thread.current[:coverband_instance] = nil
20
19
  Coverband.configure do |config|
21
- config.collector = 'trace'
22
20
  end
23
- @coverband = Coverband::Collectors::Base.instance.reset_instance
21
+ @coverband = Coverband::Collectors::Coverage.instance.reset_instance
24
22
  end
25
23
 
26
24
  test 'gets coverage instance' do
@@ -31,107 +29,5 @@ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.3.0')
31
29
  assert_equal Coverband::Adapters::RedisStore, coverband.instance_variable_get('@store').class
32
30
  end
33
31
 
34
- test 'configure memory caching' do
35
- Coverband.configuration.memory_caching = true
36
- coverband = Coverband::Collectors::Base.instance.reset_instance
37
- assert_equal Coverband::Adapters::MemoryCacheStore, coverband.instance_variable_get('@store').class
38
- Coverband.configuration.memory_caching = false
39
- end
40
-
41
- test 'start should enable coverage' do
42
- assert_equal false, coverband.instance_variable_get('@enabled')
43
- coverband.expects(:record_coverage).once
44
- coverband.start
45
- assert_equal true, coverband.instance_variable_get('@enabled')
46
- end
47
-
48
- test 'stop should disable coverage' do
49
- assert_equal false, coverband.instance_variable_get('@enabled')
50
- coverband.expects(:record_coverage).once
51
- coverband.start
52
- assert_equal true, coverband.instance_variable_get('@enabled')
53
- coverband.stop
54
- assert_equal false, coverband.instance_variable_get('@enabled')
55
- end
56
-
57
- test 'allow for sampling with a block and enable when 100 percent sample' do
58
- logger = Logger.new(STDOUT)
59
- coverband.instance_variable_set('@sample_percentage', 100.0)
60
- coverband.instance_variable_set('@verbose', true)
61
- coverband.instance_variable_set('@logger', logger)
62
- coverband.instance_variable_set('@store', nil)
63
- assert_equal false, coverband.instance_variable_get('@enabled')
64
- logger.stubs('info')
65
- logger.expects(:debug).at_least_once
66
- coverband.sample { 1 + 1 }
67
- assert_equal true, coverband.instance_variable_get('@enabled')
68
- end
69
-
70
- test 'allow reporting with start stop save' do
71
- logger = Logger.new(STDOUT)
72
- coverband.instance_variable_set('@sample_percentage', 100.0)
73
- coverband.instance_variable_set('@verbose', true)
74
- coverband.instance_variable_set('@logger', logger)
75
- coverband.instance_variable_set('@store', nil)
76
- assert_equal false, coverband.instance_variable_get('@enabled')
77
- logger.expects(:info).at_least_once
78
- logger.stubs('debug')
79
- coverband.start
80
- logger.info(1 + 1)
81
- coverband.stop
82
- coverband.save
83
- end
84
-
85
- test 'allow reporting to redis start stop save' do
86
- dog_file = File.expand_path('./dog.rb', File.dirname(__FILE__))
87
- coverband.instance_variable_set('@sample_percentage', 100.0)
88
- store = Coverband::Adapters::RedisStore.new(Redis.new)
89
- coverband.instance_variable_set('@store', store)
90
-
91
- prior = Coverage.peek_result[dog_file].dup
92
- prior[4] = prior[4] + 5
93
- expected = {}
94
- prior.each_with_index do |count, index|
95
- expected[(index + 1)] = count if count
96
- end
97
-
98
- store.expects(:save_report).once.with(has_entries(dog_file => expected))
99
- assert_equal false, coverband.instance_variable_get('@enabled')
100
- coverband.start
101
- 5.times { Dog.new.bark }
102
- coverband.stop
103
- coverband.save
104
- end
105
-
106
- test 'coverage should count line numbers only the new calls' do
107
- dog_file = File.expand_path('./dog.rb', File.dirname(__FILE__))
108
- coverband.instance_variable_set('@sample_percentage', 100.0)
109
- coverband.instance_variable_set('@store', nil)
110
- original_count = Coverage.peek_result[dog_file][4]
111
- coverband.start
112
- 100.times { Dog.new.bark }
113
- coverband.stop
114
- coverband.save
115
- assert_equal (original_count + 100), coverband.instance_variable_get('@file_line_usage')[dog_file][5]
116
- 50.times { Dog.new.bark }
117
- coverband.save
118
- assert_equal 50, coverband.instance_variable_get('@file_line_usage')[dog_file][5]
119
- end
120
-
121
- test 'coverage should count line numbers' do
122
- dog_file = File.expand_path('./dog.rb', File.dirname(__FILE__))
123
- coverband.instance_variable_set('@sample_percentage', 100.0)
124
- coverband.instance_variable_set('@store', nil)
125
- original_count = Coverage.peek_result[dog_file][4]
126
- coverband.start
127
- 100.times { Dog.new.bark }
128
- coverband.stop
129
- coverband.save
130
- assert_equal (original_count + 100), coverband.instance_variable_get('@file_line_usage')[dog_file][5]
131
- end
132
-
133
- test 'sample should return the result of the block' do
134
- assert_equal 2, coverband.sample { 1 + 1 }
135
- end
136
32
  end
137
33
  end
@@ -3,15 +3,8 @@
3
3
  require File.expand_path('../test_helper', File.dirname(__FILE__))
4
4
 
5
5
  class BaseTest < Test::Unit::TestCase
6
- test 'defaults to ignore gems' do
7
- assert_equal Coverband.configuration.include_gems, false
8
- coverband = Coverband::Collectors::Base.instance.reset_instance
9
- assert_equal ['vendor', 'internal:prelude', 'schema.rb', 'gems'], coverband.instance_variable_get('@ignore_patterns')
10
- end
11
-
12
- test "doesn't ignore gems if include_gems = true" do
13
- Coverband.configuration.include_gems = true
14
- coverband = Coverband::Collectors::Base.instance.reset_instance
6
+ test 'defaults ' do
7
+ coverband = Coverband::Collectors::Coverage.instance.reset_instance
15
8
  assert_equal ['vendor', 'internal:prelude', 'schema.rb'], coverband.instance_variable_get('@ignore_patterns')
16
9
  end
17
10
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../test_helper', File.dirname(__FILE__))
4
+ require 'rack'
5
+
6
+ class FullStackTest < Test::Unit::TestCase
7
+ BASE_KEY = Coverband::Adapters::RedisStore::BASE_KEY
8
+ TEST_RACK_APP = '../fake_app/basic_rack.rb'.freeze
9
+
10
+ def setup
11
+ Coverband::Collectors::Coverage.instance.reset_instance
12
+ Coverband.configure do |config|
13
+ config.reporting_frequency = 100.0
14
+ config.store = Coverband::Adapters::RedisStore.new(Redis.new)
15
+ config.s3_bucket = nil
16
+ end
17
+ Coverband.configuration.store.clear!
18
+ Coverband.start
19
+ @rack_file = File.expand_path(TEST_RACK_APP, File.dirname(__FILE__))
20
+ require @rack_file
21
+ end
22
+
23
+ test 'call app' do
24
+ request = Rack::MockRequest.env_for('/anything.json')
25
+ middleware = Coverband::Middleware.new(fake_app_with_lines)
26
+ results = middleware.call(request)
27
+ assert_equal 'Hello Rack!', results.last
28
+ expected = [nil, nil, 1, nil, 1, 1, 1, nil, nil]
29
+ assert_equal expected, Coverband.configuration.store.coverage[@rack_file]
30
+
31
+ # additional calls increase count by 1
32
+ middleware.call(request)
33
+ expected = [nil, nil, 1, nil, 1, 1, 2, nil, nil]
34
+ assert_equal expected, Coverband.configuration.store.coverage[@rack_file]
35
+
36
+ expected = nil
37
+ # TODO: read the html to test it matches expectations? or return data as a hash?
38
+ actual = Coverband::Reporters::SimpleCovReport.report(Coverband.configuration.store, open_report: false)
39
+ assert_equal expected, actual
40
+ end
41
+
42
+ private
43
+
44
+ def fake_app_with_lines
45
+ @fake_app_with_lines ||= ::HelloWorld.new
46
+ end
47
+ end