coverband 3.0.0 → 3.0.1.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.
- checksums.yaml +5 -5
- data/README.md +2 -1
- data/changes.md +9 -3
- data/coverband.gemspec +10 -4
- data/lib/coverband.rb +4 -1
- data/lib/coverband/adapters/base.rb +57 -8
- data/lib/coverband/adapters/file_store.rb +4 -22
- data/lib/coverband/adapters/redis_store.rb +7 -27
- data/lib/coverband/collectors/coverage.rb +5 -0
- data/lib/coverband/configuration.rb +4 -1
- data/lib/coverband/integrations/background.rb +25 -1
- data/lib/coverband/integrations/rack_server_check.rb +27 -0
- data/lib/coverband/reporters/simple_cov_report.rb +1 -7
- data/lib/coverband/reporters/web.rb +2 -20
- data/lib/coverband/utils/s3_report.rb +108 -0
- data/lib/coverband/version.rb +1 -1
- data/test/benchmarks/benchmark.rake +14 -1
- data/test/test_helper.rb +16 -1
- data/test/unit/adapters_base_test.rb +34 -13
- data/test/unit/adapters_file_store_test.rb +8 -4
- data/test/unit/adapters_redis_store_test.rb +7 -13
- data/test/unit/background_test.rb +16 -0
- data/test/unit/collectors_coverage_test.rb +24 -0
- data/test/unit/coverband_test.rb +26 -0
- data/test/unit/rack_server_checkout_test.rb +24 -0
- data/test/unit/reports_base_test.rb +0 -2
- data/test/unit/reports_console_test.rb +1 -0
- data/test/unit/reports_simple_cov_test.rb +1 -10
- data/test/unit/reports_web_test.rb +1 -3
- data/test/unit/utils_s3_report_test.rb +44 -0
- metadata +33 -12
- data/lib/coverband/utils/s3_report_writer.rb +0 -59
- data/test/unit/utils_s3_report_writer_test.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b33132c4d855470c5510444a91b0df3a99ef3ee8
|
4
|
+
data.tar.gz: e9a6c32142c9421251ce7588dcb80a4686c48e45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74411fa1d49db9c7bea3b59e49fcc2432a48650ecfae86c2e09273623c48e148995606ce8bdde73aaa789e8973655394672c01967827e97cd345443cd3a39d2f
|
7
|
+
data.tar.gz: 37dbb381f412f2b11269dbf9550148ab97cd273d60e9afae47ee47772427c0855dd4fe286dce2e9c1e73f686f257a9154f72c928de3ca22cf50008a3c9594ceb
|
data/README.md
CHANGED
@@ -194,8 +194,9 @@ run ActionController::Dispatcher.new
|
|
194
194
|
# Verify Correct Installation
|
195
195
|
|
196
196
|
* boot up your application
|
197
|
+
* run app and hit a controller (via a web request, at least one request must complete)
|
197
198
|
* run `rake coverband:coverage` this will show app initialization coverage
|
198
|
-
*
|
199
|
+
* make another request, or enough that your reporting frequency will trigger
|
199
200
|
* run `rake coverband:coverage` and you should see coverage increasing for the endpoints you hit.
|
200
201
|
|
201
202
|
## Installation Session
|
data/changes.md
CHANGED
@@ -30,7 +30,7 @@ Will be the fully modern release that drops maintenance legacy support in favor
|
|
30
30
|
Will be a stable and fast release that drops maintenance legacy support in favor of increased performance and maintainability.
|
31
31
|
|
32
32
|
- expects to drop Tracepoint collection engine
|
33
|
-
-
|
33
|
+
- drop anything below Ruby 2.3
|
34
34
|
- release begins to simplify ease of use
|
35
35
|
- drop collectors adapter
|
36
36
|
- reduced configuration options
|
@@ -44,6 +44,8 @@ Will be a stable and fast release that drops maintenance legacy support in favor
|
|
44
44
|
- add additional config / protection options on Coverage clear
|
45
45
|
- add memory benchmarks showing memory overhead of coverband
|
46
46
|
- add articles / podcasts like prontos readme https://github.com/prontolabs/pronto
|
47
|
+
- add meta data information first seen last recorded to the coverage report views (probably need to drop simplecov for that).
|
48
|
+
- more details in this issue: https://github.com/danmayer/coverband/issues/118
|
47
49
|
|
48
50
|
### Coverband_jam_session
|
49
51
|
|
@@ -70,8 +72,12 @@ Feature Ideas:
|
|
70
72
|
|
71
73
|
### Coverband 3.0.1
|
72
74
|
|
73
|
-
*
|
74
|
-
|
75
|
+
* update documentation around verification steps (https://github.com/danmayer/coverband/issues/135), thanks @kbaum
|
76
|
+
* resolve coverage drift issue, https://github.com/danmayer/coverband/issues/118, thanks for MD5 hash ideas @dnasseri and @kbaum
|
77
|
+
* first version of background thread coverage reporting https://github.com/danmayer/coverband/pull/138, thanks @kbaum
|
78
|
+
* auto-detection of Rack & Rails thanks @kbaum
|
79
|
+
* improved tests allowing exceptions to raise in tests @kbaum
|
80
|
+
* add support for both aws-sdk 1.x and 2.x thanks @jared
|
75
81
|
|
76
82
|
# Released
|
77
83
|
|
data/coverband.gemspec
CHANGED
@@ -19,22 +19,28 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
+
# to test support for sdk 1, uncomment this line
|
23
|
+
# spec.add_development_dependency 'aws-sdk', '~> 1'
|
24
|
+
# to test sdk 2 use this one
|
22
25
|
spec.add_development_dependency 'aws-sdk', '~> 2'
|
26
|
+
spec.add_development_dependency 'benchmark-ips'
|
23
27
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
28
|
spec.add_development_dependency 'mocha', '~> 0.14.0'
|
25
29
|
spec.add_development_dependency 'rack'
|
26
30
|
spec.add_development_dependency 'rack-test'
|
27
31
|
spec.add_development_dependency 'rake'
|
28
|
-
spec.add_development_dependency 'test-unit'
|
29
32
|
spec.add_development_dependency 'redis'
|
30
|
-
spec.add_development_dependency '
|
33
|
+
spec.add_development_dependency 'test-unit'
|
34
|
+
spec.add_development_dependency 'm'
|
35
|
+
|
31
36
|
# used for benchmarking and tests
|
32
37
|
spec.add_development_dependency 'classifier-reborn'
|
33
38
|
# add when debugging
|
34
39
|
# require 'byebug'; byebug
|
35
|
-
spec.add_development_dependency 'byebug'
|
40
|
+
spec.add_development_dependency 'pry-byebug'
|
36
41
|
|
37
|
-
#
|
42
|
+
# TODO: make an optional dependency for simplecov reports
|
38
43
|
# also likely should just require simplecov-html not the whole lib
|
44
|
+
# I tried this but it was harder than I thought
|
39
45
|
spec.add_runtime_dependency 'simplecov', '> 0.11.1'
|
40
46
|
end
|
data/lib/coverband.rb
CHANGED
@@ -8,11 +8,13 @@ require 'coverband/configuration'
|
|
8
8
|
require 'coverband/adapters/base'
|
9
9
|
require 'coverband/adapters/redis_store'
|
10
10
|
require 'coverband/adapters/file_store'
|
11
|
-
require 'coverband/utils/
|
11
|
+
require 'coverband/utils/s3_report'
|
12
12
|
require 'coverband/collectors/coverage'
|
13
13
|
require 'coverband/reporters/base'
|
14
14
|
require 'coverband/reporters/simple_cov_report'
|
15
15
|
require 'coverband/reporters/console_report'
|
16
|
+
require 'coverband/integrations/background'
|
17
|
+
require 'coverband/integrations/rack_server_check'
|
16
18
|
require 'coverband/reporters/web'
|
17
19
|
require 'coverband/integrations/middleware'
|
18
20
|
require 'coverband/integrations/background'
|
@@ -44,5 +46,6 @@ module Coverband
|
|
44
46
|
|
45
47
|
def self.start
|
46
48
|
Coverband::Collectors::Coverage.instance
|
49
|
+
Background.start if configuration.background_reporting_enabled && !RackServerCheck.running?
|
47
50
|
end
|
48
51
|
end
|
@@ -4,36 +4,70 @@ module Coverband
|
|
4
4
|
module Adapters
|
5
5
|
class Base
|
6
6
|
def initialize
|
7
|
-
|
7
|
+
@file_hash_cache = {}
|
8
8
|
end
|
9
9
|
|
10
10
|
def clear!
|
11
11
|
raise 'abstract'
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
# Note: This could lead to slight race on redis
|
15
|
+
# where multiple processes pull the old coverage and add to it then push
|
16
|
+
# the Coverband 2 had the same issue,
|
17
|
+
# and the tradeoff has always been acceptable
|
18
|
+
def save_report(report)
|
19
|
+
data = report.dup
|
20
|
+
merge_reports(data, get_report)
|
21
|
+
save_coverage(data)
|
16
22
|
end
|
17
23
|
|
18
24
|
def coverage
|
19
|
-
|
25
|
+
simple_report(get_report)
|
20
26
|
end
|
21
27
|
|
22
28
|
def covered_files
|
29
|
+
coverage.keys || []
|
30
|
+
end
|
31
|
+
|
32
|
+
def covered_lines_for_file(file)
|
33
|
+
coverage[file] || []
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def save_coverage
|
23
39
|
raise 'abstract'
|
24
40
|
end
|
25
41
|
|
26
|
-
def
|
42
|
+
def get_report
|
27
43
|
raise 'abstract'
|
28
44
|
end
|
29
45
|
|
30
|
-
|
46
|
+
def file_hash(file)
|
47
|
+
@file_hash_cache[file] ||= Digest::MD5.file(file).hexdigest
|
48
|
+
end
|
49
|
+
|
50
|
+
def expand_report(report)
|
51
|
+
report_time = Time.now.to_i
|
52
|
+
report.each_pair do |key, line_data|
|
53
|
+
extended_data = {
|
54
|
+
'first_updated_at' => report_time,
|
55
|
+
'last_updated_at' => report_time,
|
56
|
+
'file_hash' => file_hash(key),
|
57
|
+
'data' => line_data
|
58
|
+
}
|
59
|
+
report[key] = extended_data
|
60
|
+
end
|
61
|
+
end
|
31
62
|
|
32
63
|
def merge_reports(new_report, old_report)
|
64
|
+
new_report = expand_report(new_report)
|
33
65
|
keys = (new_report.keys + old_report.keys).uniq
|
34
66
|
keys.each do |file|
|
35
|
-
new_report[file] = if new_report[file] &&
|
36
|
-
|
67
|
+
new_report[file] = if new_report[file] &&
|
68
|
+
old_report[file] &&
|
69
|
+
new_report[file]['file_hash'] == old_report[file]['file_hash']
|
70
|
+
merge_expanded_data(new_report[file], old_report[file])
|
37
71
|
elsif new_report[file]
|
38
72
|
new_report[file]
|
39
73
|
else
|
@@ -43,9 +77,24 @@ module Coverband
|
|
43
77
|
new_report
|
44
78
|
end
|
45
79
|
|
80
|
+
def merge_expanded_data(new_expanded, old_expanded)
|
81
|
+
{
|
82
|
+
'first_updated_at' => old_expanded['first_updated_at'],
|
83
|
+
'last_updated_at' => new_expanded['last_updated_at'],
|
84
|
+
'file_hash' => new_expanded['file_hash'],
|
85
|
+
'data' => array_add(new_expanded['data'], old_expanded['data'])
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
46
89
|
def array_add(latest, original)
|
47
90
|
latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
|
48
91
|
end
|
92
|
+
|
93
|
+
def simple_report(report)
|
94
|
+
report.each_with_object({}) do |(key, extended_data), simple|
|
95
|
+
simple[key] = extended_data['data']
|
96
|
+
end
|
97
|
+
end
|
49
98
|
end
|
50
99
|
end
|
51
100
|
end
|
@@ -8,9 +8,8 @@ module Coverband
|
|
8
8
|
# Not recommended for production deployment
|
9
9
|
###
|
10
10
|
class FileStore < Base
|
11
|
-
attr_accessor :path
|
12
|
-
|
13
11
|
def initialize(path, _opts = {})
|
12
|
+
super()
|
14
13
|
@path = path
|
15
14
|
|
16
15
|
config_dir = File.dirname(@path)
|
@@ -21,32 +20,15 @@ module Coverband
|
|
21
20
|
File.delete(path) if File.exist?(path)
|
22
21
|
end
|
23
22
|
|
24
|
-
def save_report(report)
|
25
|
-
merge_reports(report, coverage)
|
26
|
-
save_coverage(report)
|
27
|
-
end
|
28
|
-
|
29
|
-
def coverage
|
30
|
-
existing_data(path)
|
31
|
-
end
|
32
|
-
|
33
|
-
def covered_files
|
34
|
-
report = existing_data(path)
|
35
|
-
existing_data(path).merge(report).keys || []
|
36
|
-
end
|
37
|
-
|
38
|
-
def covered_lines_for_file(file)
|
39
|
-
report = existing_data(path)
|
40
|
-
report[file] || []
|
41
|
-
end
|
42
|
-
|
43
23
|
private
|
44
24
|
|
25
|
+
attr_accessor :path
|
26
|
+
|
45
27
|
def save_coverage(report)
|
46
28
|
File.open(path, 'w') { |f| f.write(report.to_json) }
|
47
29
|
end
|
48
30
|
|
49
|
-
def
|
31
|
+
def get_report
|
50
32
|
if File.exist?(path)
|
51
33
|
JSON.parse(File.read(path))
|
52
34
|
else
|
@@ -6,9 +6,10 @@ module Coverband
|
|
6
6
|
# RedisStore store a merged coverage file to redis
|
7
7
|
###
|
8
8
|
class RedisStore < Base
|
9
|
-
BASE_KEY = '
|
9
|
+
BASE_KEY = 'coverband3_1'
|
10
10
|
|
11
11
|
def initialize(redis, opts = {})
|
12
|
+
super()
|
12
13
|
@redis = redis
|
13
14
|
@ttl = opts[:ttl]
|
14
15
|
@redis_namespace = opts[:redis_namespace]
|
@@ -18,27 +19,6 @@ module Coverband
|
|
18
19
|
@redis.del(base_key)
|
19
20
|
end
|
20
21
|
|
21
|
-
def save_report(report)
|
22
|
-
# Note: This could lead to slight races
|
23
|
-
# where multiple processes pull the old coverage and add to it then push
|
24
|
-
# the Coverband 2 had the same issue,
|
25
|
-
# and the tradeoff has always been acceptable
|
26
|
-
merge_reports(report, coverage)
|
27
|
-
save_coverage(base_key, report)
|
28
|
-
end
|
29
|
-
|
30
|
-
def coverage
|
31
|
-
get_report(base_key)
|
32
|
-
end
|
33
|
-
|
34
|
-
def covered_files
|
35
|
-
coverage.keys
|
36
|
-
end
|
37
|
-
|
38
|
-
def covered_lines_for_file(file)
|
39
|
-
coverage[file]
|
40
|
-
end
|
41
|
-
|
42
22
|
private
|
43
23
|
|
44
24
|
attr_reader :redis
|
@@ -47,13 +27,13 @@ module Coverband
|
|
47
27
|
@base_key ||= [BASE_KEY, @redis_namespace].compact.join('.')
|
48
28
|
end
|
49
29
|
|
50
|
-
def save_coverage(
|
51
|
-
redis.set
|
52
|
-
redis.expire(
|
30
|
+
def save_coverage(data)
|
31
|
+
redis.set base_key, data.to_json
|
32
|
+
redis.expire(base_key, @ttl) if @ttl
|
53
33
|
end
|
54
34
|
|
55
|
-
def get_report
|
56
|
-
data = redis.get
|
35
|
+
def get_report
|
36
|
+
data = redis.get base_key
|
57
37
|
data ? JSON.parse(data) : {}
|
58
38
|
end
|
59
39
|
end
|
@@ -24,12 +24,16 @@ module Coverband
|
|
24
24
|
@verbose = Coverband.configuration.verbose
|
25
25
|
@logger = Coverband.configuration.logger
|
26
26
|
@current_thread = Thread.current
|
27
|
+
@test_env = Coverband.configuration.test_env
|
28
|
+
@background_reporting_enabled = Coverband.configuration.background_reporting_enabled
|
27
29
|
Thread.current[:coverband_instance] = nil
|
28
30
|
self
|
29
31
|
end
|
30
32
|
|
31
33
|
def report_coverage(force_report = false)
|
34
|
+
return Background.start if @background_reporting_enabled
|
32
35
|
return if !ready_to_report? && !force_report
|
36
|
+
|
33
37
|
unless @store
|
34
38
|
@logger.debug 'no store set, no-op'
|
35
39
|
return
|
@@ -44,6 +48,7 @@ module Coverband
|
|
44
48
|
@logger.error "error: #{err.inspect} #{err.message}"
|
45
49
|
@logger.error err.backtrace
|
46
50
|
end
|
51
|
+
raise err if @test_env
|
47
52
|
end
|
48
53
|
|
49
54
|
protected
|
@@ -7,7 +7,8 @@ module Coverband
|
|
7
7
|
:reporter, :reporting_frequency,
|
8
8
|
:disable_on_failure_for,
|
9
9
|
:redis_namespace, :redis_ttl,
|
10
|
-
:safe_reload_files
|
10
|
+
:safe_reload_files, :background_reporting_enabled,
|
11
|
+
:background_reporting_sleep_seconds, :test_env
|
11
12
|
|
12
13
|
attr_writer :logger, :s3_region, :s3_bucket, :s3_access_key_id, :s3_secret_access_key
|
13
14
|
|
@@ -29,6 +30,8 @@ module Coverband
|
|
29
30
|
@s3_secret_access_key = nil
|
30
31
|
@redis_namespace = nil
|
31
32
|
@redis_ttl = nil
|
33
|
+
@test_env = nil
|
34
|
+
@background_reporting_sleep_seconds = 30
|
32
35
|
end
|
33
36
|
|
34
37
|
def logger
|
@@ -2,6 +2,30 @@
|
|
2
2
|
|
3
3
|
module Coverband
|
4
4
|
class Background
|
5
|
-
|
5
|
+
@semaphore = Mutex.new
|
6
|
+
|
7
|
+
def self.start
|
8
|
+
return if @background_reporting_running
|
9
|
+
|
10
|
+
logger = Coverband.configuration.logger
|
11
|
+
@semaphore.synchronize do
|
12
|
+
return if @background_reporting_running
|
13
|
+
|
14
|
+
@background_reporting_running = true
|
15
|
+
sleep_seconds = Coverband.configuration.background_reporting_sleep_seconds
|
16
|
+
Thread.new do
|
17
|
+
loop do
|
18
|
+
Coverband::Collectors::Coverage.instance.report_coverage
|
19
|
+
logger&.debug("Reported coverage from thread. Sleeping for #{sleep_seconds} seconds")
|
20
|
+
sleep(sleep_seconds)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
at_exit do
|
25
|
+
Coverband::Collectors::Coverage.instance.report_coverage
|
26
|
+
logger&.debug("Reported coverage before exit")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
6
30
|
end
|
7
31
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coverband
|
4
|
+
class RackServerCheck
|
5
|
+
def self.running?
|
6
|
+
new(Kernel.caller_locations).running?
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(stack)
|
10
|
+
@stack = stack
|
11
|
+
end
|
12
|
+
|
13
|
+
def running?
|
14
|
+
rack_server? || rails_server?
|
15
|
+
end
|
16
|
+
|
17
|
+
def rack_server?
|
18
|
+
@stack.any? { |line| line.path.include?('lib/rack/') }
|
19
|
+
end
|
20
|
+
|
21
|
+
def rails_server?
|
22
|
+
@stack.any? do |location|
|
23
|
+
location.path.include?('rails/commands/commands_tasks.rb') && location.label == 'server'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -38,13 +38,7 @@ module Coverband
|
|
38
38
|
Coverband.configuration.logger.info "report is ready and viewable: open #{SimpleCov.coverage_dir}/index.html"
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
region: Coverband.configuration.s3_region,
|
43
|
-
access_key_id: Coverband.configuration.s3_access_key_id,
|
44
|
-
secret_access_key: Coverband.configuration.s3_secret_access_key
|
45
|
-
}
|
46
|
-
Coverband::Utils::S3ReportWriter.new(Coverband.configuration.s3_bucket,
|
47
|
-
s3_writer_options).persist! if Coverband.configuration.s3_bucket
|
41
|
+
Coverband::Utils::S3Report.instance.persist! if Coverband.configuration.s3_bucket
|
48
42
|
end
|
49
43
|
end
|
50
44
|
end
|
@@ -71,7 +71,7 @@ module Coverband
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def show
|
74
|
-
html =
|
74
|
+
html = Coverband::Utils::S3Report.instance.retrieve
|
75
75
|
# HACK: the static HTML assets to link to the path where this was mounted
|
76
76
|
html = html.gsub("src='", "src='#{base_path}")
|
77
77
|
html = html.gsub("href='", "href='#{base_path}")
|
@@ -126,30 +126,12 @@ module Coverband
|
|
126
126
|
|
127
127
|
# This method should get the root mounted endpoint
|
128
128
|
# for example if the app is mounted like so:
|
129
|
-
# mount Coverband::
|
129
|
+
# mount Coverband::Web, at: '/coverage'
|
130
130
|
# "/coverage/collect_coverage?" become:
|
131
131
|
# /coverage/
|
132
132
|
def base_path
|
133
133
|
request.path.match("\/.*\/") ? request.path.match("\/.*\/")[0] : '/'
|
134
134
|
end
|
135
|
-
|
136
|
-
def s3
|
137
|
-
begin
|
138
|
-
require 'aws-sdk'
|
139
|
-
rescue StandardError
|
140
|
-
Coverband.configuration.logger.error "coverband requires 'aws-sdk' in order use S3ReportWriter."
|
141
|
-
return
|
142
|
-
end
|
143
|
-
@s3 ||= begin
|
144
|
-
client_options = {
|
145
|
-
region: Coverband.configuration.s3_region,
|
146
|
-
access_key_id: Coverband.configuration.s3_access_key_id,
|
147
|
-
secret_access_key: Coverband.configuration.s3_secret_access_key
|
148
|
-
}
|
149
|
-
client_options = {} if client_options.values.any?(&:nil?)
|
150
|
-
Aws::S3::Client.new(client_options)
|
151
|
-
end
|
152
|
-
end
|
153
135
|
end
|
154
136
|
end
|
155
137
|
end
|
@@ -0,0 +1,108 @@
|
|
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 S3Report
|
12
|
+
def self.instance
|
13
|
+
s3_options = {
|
14
|
+
region: Coverband.configuration.s3_region,
|
15
|
+
access_key_id: Coverband.configuration.s3_access_key_id,
|
16
|
+
secret_access_key: Coverband.configuration.s3_secret_access_key
|
17
|
+
}
|
18
|
+
new(Coverband.configuration.s3_bucket, s3_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(bucket_name, options = {})
|
22
|
+
@bucket_name = bucket_name
|
23
|
+
@region = options[:region]
|
24
|
+
@access_key_id = options[:access_key_id]
|
25
|
+
@secret_access_key = options[:secret_access_key]
|
26
|
+
begin
|
27
|
+
require 'aws-sdk'
|
28
|
+
rescue StandardError
|
29
|
+
err_msg = 'coverband requires aws-sdk in order use S3Report.'
|
30
|
+
Coverband.configuration.logger.error err_msg
|
31
|
+
return
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def persist!
|
36
|
+
if defined?(Aws)
|
37
|
+
object.put(body: coverage_content)
|
38
|
+
else
|
39
|
+
object.write(coverage_content)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def retrieve
|
44
|
+
if defined?(Aws)
|
45
|
+
s3_client.get_object(bucket: Coverband.configuration.s3_bucket,
|
46
|
+
key: 'coverband/index.html').body.read
|
47
|
+
else
|
48
|
+
object.read
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def coverage_content
|
55
|
+
version = Gem::Specification.find_by_name('simplecov-html').version.version
|
56
|
+
File.read("#{SimpleCov.coverage_dir}/index.html").gsub("./assets/#{version}/", '')
|
57
|
+
rescue StandardError
|
58
|
+
File.read("#{SimpleCov.coverage_dir}/index.html").to_s.gsub('./assets/0.10.1/', '')
|
59
|
+
end
|
60
|
+
|
61
|
+
def object
|
62
|
+
if defined?(Aws)
|
63
|
+
bucket.object('coverband/index.html')
|
64
|
+
else
|
65
|
+
bucket.objects['coverband/index.html']
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def client_options
|
70
|
+
{
|
71
|
+
region: @region,
|
72
|
+
access_key_id: @access_key_id,
|
73
|
+
secret_access_key: @secret_access_key
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def s3_client
|
78
|
+
if defined?(Aws)
|
79
|
+
# AWS SDK v2
|
80
|
+
Aws::S3::Client.new(client_options)
|
81
|
+
else
|
82
|
+
# AWS SDK v1
|
83
|
+
AWS::S3::Client.new(client_options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def s3
|
88
|
+
resource_options = { client: s3_client }
|
89
|
+
resource_options = {} if client_options.values.any?(&:nil?)
|
90
|
+
if defined?(Aws)
|
91
|
+
# AWS SDK v2
|
92
|
+
Aws::S3::Resource.new(resource_options)
|
93
|
+
else
|
94
|
+
# AWS SDK v1
|
95
|
+
AWS::S3.new(resource_options)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def bucket
|
100
|
+
if defined?(Aws)
|
101
|
+
s3.bucket(@bucket_name)
|
102
|
+
else
|
103
|
+
s3.buckets[@bucket_name]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/coverband/version.rb
CHANGED
@@ -169,6 +169,18 @@ namespace :benchmarks do
|
|
169
169
|
def reporting_speed
|
170
170
|
report = fake_report
|
171
171
|
store = benchmark_redis_store
|
172
|
+
store.clear!
|
173
|
+
|
174
|
+
###
|
175
|
+
# this is a hack because in the benchmark we don't have real files
|
176
|
+
###
|
177
|
+
def store.file_hash(file)
|
178
|
+
if @file_hash_cache[file]
|
179
|
+
@file_hash_cache[file]
|
180
|
+
else
|
181
|
+
@file_hash_cache[file] = Digest::MD5.file(__FILE__).hexdigest
|
182
|
+
end
|
183
|
+
end
|
172
184
|
|
173
185
|
5.times { store.save_report(report) }
|
174
186
|
Benchmark.ips do |x|
|
@@ -198,7 +210,7 @@ namespace :benchmarks do
|
|
198
210
|
desc 'benchmarks external requests to coverband_demo site'
|
199
211
|
task :coverband_demo do
|
200
212
|
# for local testing
|
201
|
-
# puts `ab -n
|
213
|
+
# puts `ab -n 500 -c 5 "http://127.0.0.1:3000/posts"`
|
202
214
|
puts `ab -n 2000 -c 10 "https://coverband-demo.herokuapp.com/posts"`
|
203
215
|
end
|
204
216
|
|
@@ -206,6 +218,7 @@ namespace :benchmarks do
|
|
206
218
|
task :coverband_demo_graph do
|
207
219
|
# for local testing
|
208
220
|
# puts `ab -n 200 -c 5 "http://127.0.0.1:3000/posts"`
|
221
|
+
#puts `ab -n 500 -c 10 -g tmp/ab_brench.tsv "http://127.0.0.1:3000/posts"`
|
209
222
|
puts `ab -n 2000 -c 10 -g tmp/ab_brench.tsv "https://coverband-demo.herokuapp.com/posts"`
|
210
223
|
puts `test/benchmarks/graph_bench.sh`
|
211
224
|
`open tmp/timeseries.jpg`
|
data/test/test_helper.rb
CHANGED
@@ -7,6 +7,7 @@ require 'mocha/setup'
|
|
7
7
|
require 'ostruct'
|
8
8
|
require 'json'
|
9
9
|
require 'redis'
|
10
|
+
require 'pry-byebug'
|
10
11
|
|
11
12
|
SimpleCov.start do
|
12
13
|
add_filter 'specs/ruby/1.9.1/gems/'
|
@@ -14,10 +15,12 @@ SimpleCov.start do
|
|
14
15
|
add_filter '/config/'
|
15
16
|
end
|
16
17
|
|
17
|
-
TEST_COVERAGE_FILE = '/tmp/fake_file.json'
|
18
|
+
TEST_COVERAGE_FILE = '/tmp/fake_file.json'
|
18
19
|
|
19
20
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
20
21
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
22
|
+
|
23
|
+
Mocha::Configuration.prevent(:stubbing_method_unnecessarily)
|
21
24
|
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
22
25
|
|
23
26
|
def test(name, &block)
|
@@ -37,6 +40,12 @@ def test(name, &block)
|
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
43
|
+
def mock_file_hash
|
44
|
+
mock_file = mock('mock_file')
|
45
|
+
mock_file.expects(:hexdigest).at_least_once.returns('abcd')
|
46
|
+
Digest::MD5.expects(:file).at_least_once.returns(mock_file)
|
47
|
+
end
|
48
|
+
|
40
49
|
def example_line
|
41
50
|
[0, 1, 2]
|
42
51
|
end
|
@@ -68,3 +77,9 @@ Coverband.configure do |config|
|
|
68
77
|
config.reporter = 'std_out'
|
69
78
|
config.store = Coverband::Adapters::RedisStore.new(Redis.new)
|
70
79
|
end
|
80
|
+
|
81
|
+
Coverband::Configuration.class_eval do
|
82
|
+
def test_env
|
83
|
+
true
|
84
|
+
end
|
85
|
+
end
|
@@ -6,23 +6,44 @@ class AdaptersBaseTest < Test::Unit::TestCase
|
|
6
6
|
def setup
|
7
7
|
@test_file_path = '/tmp/coverband_filestore_test_path.json'
|
8
8
|
@store = Coverband::Adapters::FileStore.new(@test_file_path)
|
9
|
+
mock_file_hash
|
9
10
|
end
|
10
11
|
|
11
12
|
def test_covered_merge
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
old_time = 1541958097
|
14
|
+
current_time = Time.now.to_i
|
15
|
+
old_data = {
|
16
|
+
'first_updated_at' => old_time,
|
17
|
+
'last_updated_at' => current_time,
|
18
|
+
'file_hash' => 'abcd',
|
19
|
+
'data' => [5, 7, nil]
|
20
|
+
}
|
21
|
+
old_report = { '/projects/coverband_demo/config/coverband.rb' => old_data,
|
22
|
+
'/projects/coverband_demo/config/initializers/assets.rb' => old_data,
|
23
|
+
'/projects/coverband_demo/config/initializers/cookies_serializer.rb' => old_data }
|
24
|
+
new_report = { '/projects/coverband_demo/config/coverband.rb' => [5, 7, nil],
|
25
|
+
'/projects/coverband_demo/config/initializers/filter_logging.rb' => [5, 7, nil],
|
26
|
+
'/projects/coverband_demo/config/initializers/wrap_parameters.rb' => [5, 7, nil],
|
27
|
+
'/projects/coverband_demo/app/controllers/application_controller.rb' => [5, 7, nil] }
|
28
|
+
expected_merge = {
|
29
|
+
'first_updated_at' => old_time,
|
30
|
+
'last_updated_at' => current_time,
|
31
|
+
'file_hash' => 'abcd',
|
32
|
+
'data' => [10, 14, nil]
|
33
|
+
}
|
34
|
+
new_data = {
|
35
|
+
'first_updated_at' => current_time,
|
36
|
+
'last_updated_at' => current_time,
|
37
|
+
'file_hash' => 'abcd',
|
38
|
+
'data' => [5, 7, nil]
|
39
|
+
}
|
19
40
|
expected_result = {
|
20
|
-
'/
|
21
|
-
'/
|
22
|
-
'/
|
23
|
-
'/
|
24
|
-
'/
|
25
|
-
'/
|
41
|
+
'/projects/coverband_demo/app/controllers/application_controller.rb' => new_data,
|
42
|
+
'/projects/coverband_demo/config/coverband.rb' => expected_merge,
|
43
|
+
'/projects/coverband_demo/config/initializers/assets.rb' => old_data,
|
44
|
+
'/projects/coverband_demo/config/initializers/cookies_serializer.rb' => old_data,
|
45
|
+
'/projects/coverband_demo/config/initializers/filter_logging.rb' => new_data,
|
46
|
+
'/projects/coverband_demo/config/initializers/wrap_parameters.rb' => new_data
|
26
47
|
}
|
27
48
|
assert_equal expected_result, @store.send(:merge_reports, new_report, old_report)
|
28
49
|
end
|
@@ -10,8 +10,8 @@ class AdaptersFileStoreTest < Test::Unit::TestCase
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_covered_lines_for_file
|
13
|
-
assert_equal @store.covered_lines_for_file('dog.rb')[
|
14
|
-
assert_equal @store.covered_lines_for_file('dog.rb')[
|
13
|
+
assert_equal @store.covered_lines_for_file('dog.rb')[0], 1
|
14
|
+
assert_equal @store.covered_lines_for_file('dog.rb')[1], 2
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_covered_lines_when_null
|
@@ -28,7 +28,8 @@ class AdaptersFileStoreTest < Test::Unit::TestCase
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def test_save_report
|
31
|
-
|
31
|
+
mock_file_hash
|
32
|
+
@store.send(:save_report, 'cat.rb' => [0, 1])
|
32
33
|
assert_equal @store.covered_lines_for_file('cat.rb')[1], 1
|
33
34
|
end
|
34
35
|
|
@@ -36,7 +37,10 @@ class AdaptersFileStoreTest < Test::Unit::TestCase
|
|
36
37
|
|
37
38
|
def test_data
|
38
39
|
{
|
39
|
-
'dog.rb' => {
|
40
|
+
'dog.rb' => { 'data' => [1, 2, nil],
|
41
|
+
'file_hash' => 'abcd',
|
42
|
+
'first_updated_at' => 1541968729,
|
43
|
+
'last_updated_at' => 1541968729 }
|
40
44
|
}
|
41
45
|
end
|
42
46
|
end
|
@@ -12,27 +12,30 @@ class RedisTest < Test::Unit::TestCase
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_coverage
|
15
|
+
mock_file_hash
|
15
16
|
expected = basic_coverage
|
16
17
|
@store.save_report(expected)
|
17
18
|
assert_equal expected, @store.coverage
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_coverage_increments
|
21
|
-
|
22
|
-
|
22
|
+
mock_file_hash
|
23
|
+
expected = basic_coverage.dup
|
24
|
+
@store.save_report(basic_coverage.dup)
|
23
25
|
assert_equal expected, @store.coverage
|
24
|
-
@store.save_report(
|
26
|
+
@store.save_report(basic_coverage.dup)
|
25
27
|
assert_equal [0, 2, 4], @store.coverage['app_path/dog.rb']
|
26
28
|
end
|
27
29
|
|
28
30
|
def test_covered_lines_for_file
|
31
|
+
mock_file_hash
|
29
32
|
expected = basic_coverage
|
30
33
|
@store.save_report(expected)
|
31
34
|
assert_equal example_line, @store.covered_lines_for_file('app_path/dog.rb')
|
32
35
|
end
|
33
36
|
|
34
37
|
def test_covered_lines_when_null
|
35
|
-
assert_equal
|
38
|
+
assert_equal [], @store.covered_lines_for_file('app_path/dog.rb')
|
36
39
|
end
|
37
40
|
|
38
41
|
def test_clear
|
@@ -42,15 +45,6 @@ class RedisTest < Test::Unit::TestCase
|
|
42
45
|
|
43
46
|
private
|
44
47
|
|
45
|
-
def combined_report
|
46
|
-
{
|
47
|
-
"#{BASE_KEY}.dog.rb" => {
|
48
|
-
new: example_hash,
|
49
|
-
existing: {}
|
50
|
-
}
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
48
|
def test_data
|
55
49
|
{
|
56
50
|
'/Users/danmayer/projects/cover_band_server/app.rb' => { 54 => 1, 55 => 2 },
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class BackgroundTest < Test::Unit::TestCase
|
6
|
+
def test_start
|
7
|
+
Thread.expects(:new).yields
|
8
|
+
Coverband::Background.expects(:loop).yields
|
9
|
+
Coverband::Collectors::Coverage.instance.expects(:report_coverage)
|
10
|
+
Coverband::Background.expects(:sleep).with(30)
|
11
|
+
Coverband::Background.expects(:at_exit).yields
|
12
|
+
Coverband::Collectors::Coverage.instance.expects(:report_coverage)
|
13
|
+
2.times { Coverband::Background.start }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -29,5 +29,29 @@ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.3.0')
|
|
29
29
|
assert_equal Coverband::Adapters::RedisStore, coverband.instance_variable_get('@store').class
|
30
30
|
end
|
31
31
|
|
32
|
+
test 'reports coverage in background when background reporting enabled' do
|
33
|
+
Coverband.configuration.stubs(:background_reporting_enabled).returns(true)
|
34
|
+
@coverband.reset_instance
|
35
|
+
Coverband::Background.expects(:start)
|
36
|
+
@coverband.report_coverage
|
37
|
+
end
|
38
|
+
|
39
|
+
test 'report_coverage raises errors in tests' do
|
40
|
+
Coverband.configuration.stubs(:background_reporting_enabled).returns(true)
|
41
|
+
@coverband.reset_instance
|
42
|
+
Coverband::Background.expects(:start).raises("Oh no")
|
43
|
+
assert_raise RuntimeError do
|
44
|
+
@coverband.report_coverage
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'report_coverage does not raise errors in non-test mode' do
|
49
|
+
Coverband.configuration.stubs(:background_reporting_enabled).returns(true)
|
50
|
+
Coverband.configuration.stubs(:test_env).returns(false)
|
51
|
+
@coverband.reset_instance
|
52
|
+
Coverband::Background.expects(:start).raises("Oh no")
|
53
|
+
@coverband.report_coverage
|
54
|
+
end
|
55
|
+
|
32
56
|
end
|
33
57
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class CoverbandTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
test 'Coverband#start kicks off background reporting if enabled and not in rack server' do
|
8
|
+
Coverband.configuration.stubs(:background_reporting_enabled).returns(:true)
|
9
|
+
Coverband::RackServerCheck.expects(:running?).returns(false)
|
10
|
+
Coverband::Background.expects(:start)
|
11
|
+
Coverband.start
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'Coverband#start delays background reporting if enabled and running in a rack server' do
|
15
|
+
Coverband.configuration.stubs(:background_reporting_enabled).returns(true)
|
16
|
+
Coverband::RackServerCheck.expects(:running?).returns(true)
|
17
|
+
Coverband::Background.expects(:start).never
|
18
|
+
Coverband.start
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'Coverband#start does not kick off background reporting if not enabled' do
|
22
|
+
Coverband.configuration.stubs(:background_reporting_enabled).returns(false)
|
23
|
+
Coverband::Background.expects(:start).never
|
24
|
+
::Coverband.start
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class RackServerCheckTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
test 'returns true when running in rack server' do
|
8
|
+
caller_locations = ['blah/lib/rack/server.rb'].map{ |path| OpenStruct.new(path: path, label: 'foo') }
|
9
|
+
Kernel.expects(:caller_locations).returns(caller_locations)
|
10
|
+
assert_true(Coverband::RackServerCheck.running?)
|
11
|
+
end
|
12
|
+
|
13
|
+
test 'returns false when not running in rack server' do
|
14
|
+
caller_locations = ['blah/lib/sidekiq/worker.rb'].map{ |path| OpenStruct.new(path: path, label: 'foo') }
|
15
|
+
Kernel.expects(:caller_locations).returns(caller_locations)
|
16
|
+
assert_false(Coverband::RackServerCheck.running?)
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'returns true if running within a rails server' do
|
20
|
+
caller_locations = [OpenStruct.new(path: '/lib/rails/commands/commands_tasks.rb', label: 'server')]
|
21
|
+
Kernel.expects(:caller_locations).returns(caller_locations)
|
22
|
+
assert_true(Coverband::RackServerCheck.running?)
|
23
|
+
end
|
24
|
+
end
|
@@ -103,8 +103,6 @@ class ReportsBaseTest < Test::Unit::TestCase
|
|
103
103
|
lines_hit = [1, 3, 6]
|
104
104
|
store.stubs(:coverage).returns(key => lines_hit)
|
105
105
|
expected = { key => [1, 3, 6] }
|
106
|
-
File.stubs(:exist?).returns(true)
|
107
|
-
File.stubs(:foreach).returns(['line 1', 'line2', 'line3', 'line4', 'line5', 'line6'])
|
108
106
|
|
109
107
|
assert_equal expected, Coverband::Reporters::Base.send(:get_current_scov_data_imp, store, roots)
|
110
108
|
end
|
@@ -11,15 +11,6 @@ class ReportsSimpleCovTest < Test::Unit::TestCase
|
|
11
11
|
@store.clear!
|
12
12
|
end
|
13
13
|
|
14
|
-
def combined_report
|
15
|
-
{
|
16
|
-
"#{BASE_KEY}.test/unit/dog.rb" => {
|
17
|
-
new: example_hash,
|
18
|
-
existing: {}
|
19
|
-
}
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
14
|
test 'generate scov report' do
|
24
15
|
Coverband.configure do |config|
|
25
16
|
config.reporter = 'scov'
|
@@ -28,13 +19,13 @@ class ReportsSimpleCovTest < Test::Unit::TestCase
|
|
28
19
|
config.ignore = ['notsomething.rb']
|
29
20
|
end
|
30
21
|
Coverband.configuration.logger.stubs('info')
|
22
|
+
mock_file_hash
|
31
23
|
@store.send(:save_report, basic_coverage)
|
32
24
|
|
33
25
|
SimpleCov.expects(:track_files)
|
34
26
|
SimpleCov.expects(:add_not_loaded_files).returns({})
|
35
27
|
SimpleCov::Result.any_instance.expects(:format!)
|
36
28
|
SimpleCov.stubs(:root)
|
37
|
-
|
38
29
|
Coverband::Reporters::SimpleCovReport.report(@store, open_report: false)
|
39
30
|
end
|
40
31
|
end
|
@@ -29,9 +29,7 @@ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.2.0')
|
|
29
29
|
|
30
30
|
test 'renders show content' do
|
31
31
|
Coverband.configuration.s3_bucket = 'coverage-bucket'
|
32
|
-
|
33
|
-
Aws::S3::Client.expects(:new).returns(s3)
|
34
|
-
s3.expects(:get_object).with(bucket: 'coverage-bucket', key: 'coverband/index.html').returns mock('response', body: mock('body', read: 'content'))
|
32
|
+
Coverband::Utils::S3Report.any_instance.expects(:retrieve).returns('content')
|
35
33
|
get '/show'
|
36
34
|
assert last_response.ok?
|
37
35
|
assert_equal 'content', last_response.body
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
2
|
+
require 'aws-sdk'
|
3
|
+
|
4
|
+
module Coverband
|
5
|
+
class S3ReportTest < Test::Unit::TestCase
|
6
|
+
def html_version
|
7
|
+
Gem::Specification.find_by_name('simplecov-html').version.version.to_s
|
8
|
+
rescue StandardError
|
9
|
+
'0.10.1'
|
10
|
+
end
|
11
|
+
|
12
|
+
test 'it writes the coverage report to s3' do
|
13
|
+
if defined?(Aws::S3::Resource)
|
14
|
+
# AWS v2
|
15
|
+
s3 = mock('s3_resource')
|
16
|
+
bucket = mock('bucket')
|
17
|
+
object = mock('object')
|
18
|
+
s3.expects(:bucket).with('coverage-bucket').returns(bucket)
|
19
|
+
bucket.expects(:object).with('coverband/index.html').returns(object)
|
20
|
+
File.expects(:read).at_least(0).returns("content ./assets/#{html_version}/")
|
21
|
+
object.expects(:put).with(body: 'content ')
|
22
|
+
Aws::S3::Resource.expects(:new).returns(s3)
|
23
|
+
else
|
24
|
+
# AWS v1
|
25
|
+
object = mock('object')
|
26
|
+
object.expects(:write).with('content ')
|
27
|
+
bucket = mock('bucket')
|
28
|
+
bucket.expects(:objects).returns('coverband/index.html' => object)
|
29
|
+
local_s3 = mock('s3_resource')
|
30
|
+
local_s3.expects(:buckets).returns('coverage-bucket' => bucket)
|
31
|
+
File.expects(:read).at_least(0).returns("content ./assets/#{html_version}/")
|
32
|
+
AWS::S3::Client.expects(:new).returns(nil)
|
33
|
+
AWS::S3.expects(:new).returns(local_s3)
|
34
|
+
end
|
35
|
+
|
36
|
+
s3_options = {
|
37
|
+
region: 'us-west-1',
|
38
|
+
access_key_id: '',
|
39
|
+
secret_access_key: ''
|
40
|
+
}
|
41
|
+
Coverband::Utils::S3Report.new('coverage-bucket', s3_options).persist!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
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: 3.0.
|
4
|
+
version: 3.0.1.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Mayer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: benchmark-ips
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +109,7 @@ dependencies:
|
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: redis
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -109,7 +123,7 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: test-unit
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - ">="
|
@@ -123,7 +137,7 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: m
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - ">="
|
@@ -151,7 +165,7 @@ dependencies:
|
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
|
-
name: byebug
|
168
|
+
name: pry-byebug
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
171
|
- - ">="
|
@@ -204,11 +218,12 @@ files:
|
|
204
218
|
- lib/coverband/configuration.rb
|
205
219
|
- lib/coverband/integrations/background.rb
|
206
220
|
- lib/coverband/integrations/middleware.rb
|
221
|
+
- lib/coverband/integrations/rack_server_check.rb
|
207
222
|
- lib/coverband/reporters/base.rb
|
208
223
|
- lib/coverband/reporters/console_report.rb
|
209
224
|
- lib/coverband/reporters/simple_cov_report.rb
|
210
225
|
- lib/coverband/reporters/web.rb
|
211
|
-
- lib/coverband/utils/
|
226
|
+
- lib/coverband/utils/s3_report.rb
|
212
227
|
- lib/coverband/utils/tasks.rb
|
213
228
|
- lib/coverband/version.rb
|
214
229
|
- test/benchmarks/.gitignore
|
@@ -220,16 +235,19 @@ files:
|
|
220
235
|
- test/unit/adapters_base_test.rb
|
221
236
|
- test/unit/adapters_file_store_test.rb
|
222
237
|
- test/unit/adapters_redis_store_test.rb
|
238
|
+
- test/unit/background_test.rb
|
223
239
|
- test/unit/collectors_coverage_test.rb
|
224
240
|
- test/unit/configuration_test.rb
|
241
|
+
- test/unit/coverband_test.rb
|
225
242
|
- test/unit/dog.rb
|
226
243
|
- test/unit/full_stack_test.rb
|
227
244
|
- test/unit/middleware_test.rb
|
245
|
+
- test/unit/rack_server_checkout_test.rb
|
228
246
|
- test/unit/reports_base_test.rb
|
229
247
|
- test/unit/reports_console_test.rb
|
230
248
|
- test/unit/reports_simple_cov_test.rb
|
231
249
|
- test/unit/reports_web_test.rb
|
232
|
-
- test/unit/
|
250
|
+
- test/unit/utils_s3_report_test.rb
|
233
251
|
homepage: https://github.com/danmayer/coverband
|
234
252
|
licenses:
|
235
253
|
- MIT
|
@@ -245,12 +263,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
245
263
|
version: '0'
|
246
264
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
265
|
requirements:
|
248
|
-
- - "
|
266
|
+
- - ">"
|
249
267
|
- !ruby/object:Gem::Version
|
250
|
-
version:
|
268
|
+
version: 1.3.1
|
251
269
|
requirements: []
|
252
270
|
rubyforge_project:
|
253
|
-
rubygems_version: 2.
|
271
|
+
rubygems_version: 2.5.1
|
254
272
|
signing_key:
|
255
273
|
specification_version: 4
|
256
274
|
summary: Rack middleware to help measure production code usage (LOC runtime usage)
|
@@ -264,13 +282,16 @@ test_files:
|
|
264
282
|
- test/unit/adapters_base_test.rb
|
265
283
|
- test/unit/adapters_file_store_test.rb
|
266
284
|
- test/unit/adapters_redis_store_test.rb
|
285
|
+
- test/unit/background_test.rb
|
267
286
|
- test/unit/collectors_coverage_test.rb
|
268
287
|
- test/unit/configuration_test.rb
|
288
|
+
- test/unit/coverband_test.rb
|
269
289
|
- test/unit/dog.rb
|
270
290
|
- test/unit/full_stack_test.rb
|
271
291
|
- test/unit/middleware_test.rb
|
292
|
+
- test/unit/rack_server_checkout_test.rb
|
272
293
|
- test/unit/reports_base_test.rb
|
273
294
|
- test/unit/reports_console_test.rb
|
274
295
|
- test/unit/reports_simple_cov_test.rb
|
275
296
|
- test/unit/reports_web_test.rb
|
276
|
-
- test/unit/
|
297
|
+
- test/unit/utils_s3_report_test.rb
|
@@ -1,59 +0,0 @@
|
|
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,30 +0,0 @@
|
|
1
|
-
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
2
|
-
require 'aws-sdk'
|
3
|
-
|
4
|
-
module Coverband
|
5
|
-
class S3ReportWriterTest < Test::Unit::TestCase
|
6
|
-
def html_version
|
7
|
-
Gem::Specification.find_by_name('simplecov-html').version.version.to_s
|
8
|
-
rescue StandardError
|
9
|
-
'0.10.1'
|
10
|
-
end
|
11
|
-
|
12
|
-
test 'it writes the coverage report to s3' do
|
13
|
-
s3 = mock('s3_resource')
|
14
|
-
bucket = mock('bucket')
|
15
|
-
object = mock('object')
|
16
|
-
s3.expects(:bucket).with('coverage-bucket').returns(bucket)
|
17
|
-
bucket.expects(:object).with('coverband/index.html').returns(object)
|
18
|
-
File.expects(:read).at_least(0).returns("content ./assets/#{html_version}/")
|
19
|
-
object.expects(:put).with(body: 'content ')
|
20
|
-
Aws::S3::Resource.expects(:new).returns(s3)
|
21
|
-
|
22
|
-
s3_writer_options = {
|
23
|
-
region: 'us-west-1',
|
24
|
-
access_key_id: '',
|
25
|
-
secret_access_key: ''
|
26
|
-
}
|
27
|
-
Coverband::Utils::S3ReportWriter.new('coverage-bucket', s3_writer_options).persist!
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|