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.
- checksums.yaml +4 -4
- data/.rubocop.yml +29 -9
- data/.travis.yml +10 -1
- data/Gemfile +3 -1
- data/Gemfile.rails4 +1 -0
- data/README.md +40 -15
- data/Rakefile +14 -3
- data/changes.md +47 -12
- data/coverband.gemspec +3 -1
- data/lib/coverband/adapters/base.rb +60 -36
- data/lib/coverband/adapters/file_store.rb +8 -8
- data/lib/coverband/adapters/redis_store.rb +18 -10
- data/lib/coverband/at_exit.rb +2 -11
- data/lib/coverband/collectors/coverage.rb +32 -36
- data/lib/coverband/collectors/delta.rb +34 -28
- data/lib/coverband/configuration.rb +76 -32
- data/lib/coverband/integrations/background.rb +8 -4
- data/lib/coverband/integrations/{middleware.rb → background_middleware.rb} +2 -6
- data/lib/coverband/integrations/bundler.rb +8 -0
- data/lib/coverband/integrations/report_middleware.rb +15 -0
- data/lib/coverband/integrations/resque.rb +3 -5
- data/lib/coverband/reporters/base.rb +39 -14
- data/lib/coverband/reporters/html_report.rb +21 -27
- data/lib/coverband/reporters/web.rb +13 -21
- data/lib/coverband/utils/file_list.rb +16 -5
- data/lib/coverband/utils/file_path_helper.rb +14 -3
- data/lib/coverband/utils/html_formatter.rb +25 -8
- data/lib/coverband/utils/lines_classifier.rb +5 -0
- data/lib/coverband/utils/railtie.rb +11 -12
- data/lib/coverband/utils/result.rb +1 -37
- data/lib/coverband/utils/results.rb +51 -0
- data/lib/coverband/utils/source_file.rb +31 -6
- data/lib/coverband/utils/tasks.rb +9 -10
- data/lib/coverband/version.rb +1 -1
- data/lib/coverband.rb +32 -21
- data/public/application.js +27 -0
- data/test/benchmarks/benchmark.rake +144 -26
- data/test/coverband/adapters/base_test.rb +73 -42
- data/test/coverband/adapters/file_store_test.rb +48 -37
- data/test/coverband/adapters/redis_store_test.rb +41 -10
- data/test/coverband/at_exit_test.rb +0 -2
- data/test/coverband/collectors/coverage_test.rb +57 -9
- data/test/coverband/collectors/delta_test.rb +36 -6
- data/test/coverband/configuration_test.rb +47 -7
- data/test/coverband/coverband_test.rb +14 -2
- data/test/coverband/integrations/background_middleware_test.rb +44 -0
- data/test/coverband/integrations/background_test.rb +1 -3
- data/test/coverband/integrations/report_middleware_test.rb +44 -0
- data/test/coverband/integrations/resque_worker_test.rb +4 -3
- data/test/coverband/integrations/test_resque_job.rb +3 -1
- data/test/coverband/reporters/base_test.rb +4 -4
- data/test/coverband/reporters/console_test.rb +1 -2
- data/test/coverband/reporters/html_test.rb +58 -19
- data/test/coverband/reporters/web_test.rb +0 -10
- data/test/coverband/utils/file_groups_test.rb +11 -5
- data/test/coverband/utils/file_list_test.rb +5 -5
- data/test/coverband/utils/html_formatter_test.rb +43 -0
- data/test/coverband/utils/result_test.rb +6 -47
- data/test/coverband/utils/results_test.rb +54 -0
- data/test/coverband/utils/s3_report_test.rb +2 -0
- data/test/coverband/utils/source_file_test.rb +50 -0
- data/test/dog.rb.erb +12 -0
- data/test/forked/rails_full_stack_test.rb +106 -0
- data/test/forked/rails_rake_full_stack_test.rb +40 -0
- data/test/integration/full_stack_test.rb +17 -15
- data/test/rails4_dummy/Rakefile +6 -0
- data/test/rails4_dummy/config/application.rb +8 -9
- data/test/rails4_dummy/config/coverband.rb +5 -3
- data/test/rails5_dummy/Rakefile +6 -0
- data/test/rails5_dummy/config/application.rb +6 -10
- data/test/rails5_dummy/config/coverband.rb +4 -2
- data/test/rails_test_helper.rb +22 -5
- data/test/test_helper.rb +42 -4
- data/test/unique_files.rb +17 -9
- data/views/file_list.erb +2 -2
- data/views/gem_list.erb +10 -1
- data/views/layout.erb +10 -3
- data/views/source_file.erb +13 -4
- data/views/source_file_loader.erb +1 -1
- metadata +52 -9
- data/test/coverband/integrations/middleware_test.rb +0 -96
- data/test/integration/rails_full_stack_test.rb +0 -95
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../rails_test_helper', File.dirname(__FILE__))
|
|
4
|
+
|
|
5
|
+
class RailsFullStackTest < Minitest::Test
|
|
6
|
+
include Capybara::DSL
|
|
7
|
+
include Capybara::Minitest::Assertions
|
|
8
|
+
|
|
9
|
+
def setup
|
|
10
|
+
super
|
|
11
|
+
rails_setup
|
|
12
|
+
# preload first coverage hit
|
|
13
|
+
Coverband.report_coverage
|
|
14
|
+
require 'rainbow'
|
|
15
|
+
Rainbow('this text is red').red
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def teardown
|
|
19
|
+
super
|
|
20
|
+
Capybara.reset_sessions!
|
|
21
|
+
Capybara.use_default_driver
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# We have to combine everything in one test
|
|
25
|
+
# because we can only initialize rails once per test
|
|
26
|
+
# run. Possibly fork test runs to avoid this problem in future?
|
|
27
|
+
unless ENV['COVERBAND_MEMORY_TEST']
|
|
28
|
+
test 'this is how we do it' do
|
|
29
|
+
visit '/dummy/show'
|
|
30
|
+
Coverband.report_coverage
|
|
31
|
+
assert_content('I am no dummy')
|
|
32
|
+
visit '/coverage'
|
|
33
|
+
within page.find('a', text: /dummy_controller.rb/).find(:xpath, '../..') do
|
|
34
|
+
assert_selector('td', text: '100.0 %')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Test gems are reporting coverage
|
|
38
|
+
assert_content('Gems')
|
|
39
|
+
assert page.html.match('rainbow/wrapper.rb')
|
|
40
|
+
|
|
41
|
+
# Test eager load data stored separately
|
|
42
|
+
dummy_controller = "./test/rails#{Rails::VERSION::MAJOR}_dummy/app/controllers/dummy_controller.rb"
|
|
43
|
+
store.type = :eager_loading
|
|
44
|
+
eager_expected = [1, 1, 0, nil, nil]
|
|
45
|
+
results = store.coverage[dummy_controller]['data']
|
|
46
|
+
assert_equal(eager_expected, results)
|
|
47
|
+
|
|
48
|
+
store.type = Coverband::RUNTIME_TYPE
|
|
49
|
+
runtime_expected = [0, 0, 1, nil, nil]
|
|
50
|
+
results = store.coverage[dummy_controller]['data']
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
###
|
|
55
|
+
# as we run it in single test mode via the benchmarks.
|
|
56
|
+
# Add new tests below this test
|
|
57
|
+
###
|
|
58
|
+
if ENV['COVERBAND_MEMORY_TEST']
|
|
59
|
+
test 'memory usage' do
|
|
60
|
+
return unless ENV['COVERBAND_MEMORY_TEST']
|
|
61
|
+
|
|
62
|
+
# we don't want this to run during our standard test suite
|
|
63
|
+
# as the below profiler changes the runtime
|
|
64
|
+
# and shold only be included for isolated processes
|
|
65
|
+
begin
|
|
66
|
+
require 'memory_profiler'
|
|
67
|
+
|
|
68
|
+
# warmup
|
|
69
|
+
3.times do
|
|
70
|
+
visit '/dummy/show'
|
|
71
|
+
assert_content('I am no dummy')
|
|
72
|
+
Coverband.report_coverage
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
previous_out = $stdout
|
|
76
|
+
capture = StringIO.new
|
|
77
|
+
$stdout = capture
|
|
78
|
+
|
|
79
|
+
MemoryProfiler.report do
|
|
80
|
+
15.times do
|
|
81
|
+
visit '/dummy/show'
|
|
82
|
+
assert_content('I am no dummy')
|
|
83
|
+
Coverband.report_coverage
|
|
84
|
+
###
|
|
85
|
+
# Set to nil not {} as it is easier to verify that no memory is retained when nil gets released
|
|
86
|
+
# don't use Coverband::Collectors::Delta.reset which sets to {}
|
|
87
|
+
#
|
|
88
|
+
# we clear this as this one variable is expected to retain memory and is a false positive
|
|
89
|
+
###
|
|
90
|
+
Coverband::Collectors::Delta.class_variable_set(:@@previous_coverage, nil)
|
|
91
|
+
# needed to test older versions to discover when we had the regression
|
|
92
|
+
# Coverband::Collectors::Coverage.instance.send(:add_previous_results, nil)
|
|
93
|
+
end
|
|
94
|
+
end.pretty_print
|
|
95
|
+
data = $stdout.string
|
|
96
|
+
$stdout = previous_out
|
|
97
|
+
if data.match(/retained objects by gem(.*)retained objects by file/m)[0]&.match(/coverband/)
|
|
98
|
+
puts data
|
|
99
|
+
raise 'leaking memory!!!'
|
|
100
|
+
end
|
|
101
|
+
ensure
|
|
102
|
+
$stdout = previous_out
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require File.expand_path('../rails_test_helper', File.dirname(__FILE__))
|
|
2
|
+
require 'rails'
|
|
3
|
+
|
|
4
|
+
class RailsRakeFullStackTest < Minitest::Test
|
|
5
|
+
|
|
6
|
+
test 'rake tasks shows coverage properly within eager_loading' do
|
|
7
|
+
store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
8
|
+
store.clear!
|
|
9
|
+
system("COVERBAND_CONFIG=./test/rails#{Rails::VERSION::MAJOR}_dummy/config/coverband.rb bundle exec rake -f test/rails#{Rails::VERSION::MAJOR}_dummy/Rakefile middleware")
|
|
10
|
+
store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
11
|
+
store.type = :eager_loading
|
|
12
|
+
pundit_file = store.coverage.keys.grep(/pundit.rb/).first
|
|
13
|
+
refute_nil pundit_file
|
|
14
|
+
pundit_coverage = store.coverage[pundit_file]
|
|
15
|
+
refute_nil pundit_coverage
|
|
16
|
+
assert_includes pundit_coverage['data'], 1
|
|
17
|
+
|
|
18
|
+
store.type = Coverband::RUNTIME_TYPE
|
|
19
|
+
if ENV['SIMULATE_ONESHOT']
|
|
20
|
+
pundit_coverage = store.get_coverage_report[Coverband::RUNTIME_TYPE][pundit_file]
|
|
21
|
+
assert pundit_coverage['data'].compact.all? { |el| el == 0}
|
|
22
|
+
else
|
|
23
|
+
pundit_coverage = store.coverage[pundit_file]
|
|
24
|
+
assert_nil pundit_coverage
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
test "ignored rake tasks don't add coverage" do
|
|
29
|
+
store.clear!
|
|
30
|
+
store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
31
|
+
store.send(:save_report, basic_coverage_full_path)
|
|
32
|
+
output = `COVERBAND_CONFIG=./test/rails#{Rails::VERSION::MAJOR}_dummy/config/coverband.rb bundle exec rake -f test/rails#{Rails::VERSION::MAJOR}_dummy/Rakefile coverband:clear`
|
|
33
|
+
assert_nil output.match(/Coverband: Reported coverage via thread/)
|
|
34
|
+
coverage_report = store.get_coverage_report
|
|
35
|
+
empty_hash = {}
|
|
36
|
+
assert_equal empty_hash, coverage_report[Coverband::RUNTIME_TYPE]
|
|
37
|
+
assert_equal empty_hash, coverage_report[:eager_loading]
|
|
38
|
+
assert_equal empty_hash, coverage_report[:merged]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -6,52 +6,54 @@ require 'rack'
|
|
|
6
6
|
class FullStackTest < Minitest::Test
|
|
7
7
|
REDIS_STORAGE_FORMAT_VERSION = Coverband::Adapters::RedisStore::REDIS_STORAGE_FORMAT_VERSION
|
|
8
8
|
TEST_RACK_APP = '../fake_app/basic_rack.rb'
|
|
9
|
-
RELATIVE_FILE = './fake_app/basic_rack.rb'
|
|
10
9
|
|
|
11
10
|
def setup
|
|
12
11
|
super
|
|
13
12
|
Coverband::Collectors::Coverage.instance.reset_instance
|
|
14
13
|
Coverband.configure do |config|
|
|
15
|
-
config.
|
|
16
|
-
config.store = Coverband::Adapters::RedisStore.new(Redis.new)
|
|
14
|
+
config.store = Coverband::Adapters::RedisStore.new(Redis.new(), redis_namespace: 'coverband_test')
|
|
17
15
|
config.s3_bucket = nil
|
|
18
|
-
config.background_reporting_enabled =
|
|
16
|
+
config.background_reporting_enabled = true
|
|
19
17
|
config.root_paths = ["#{File.expand_path('../', File.dirname(__FILE__))}/"]
|
|
20
18
|
config.track_gems = true
|
|
21
19
|
end
|
|
22
20
|
Coverband.configuration.store.clear!
|
|
23
21
|
Coverband.start
|
|
22
|
+
Coverband::Collectors::Coverage.instance.eager_loading!
|
|
23
|
+
@rack_file = require_unique_file 'fake_app/basic_rack.rb'
|
|
24
|
+
Coverband.report_coverage
|
|
24
25
|
Coverband::Collectors::Coverage.instance.runtime!
|
|
25
|
-
@rack_file = File.expand_path(TEST_RACK_APP, File.dirname(__FILE__))
|
|
26
|
-
require @rack_file
|
|
27
|
-
# preload first coverage hit
|
|
28
|
-
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
|
29
26
|
end
|
|
30
27
|
|
|
31
28
|
test 'call app' do
|
|
32
29
|
request = Rack::MockRequest.env_for('/anything.json')
|
|
33
|
-
middleware = Coverband::
|
|
30
|
+
middleware = Coverband::BackgroundMiddleware.new(fake_app_with_lines)
|
|
34
31
|
results = middleware.call(request)
|
|
35
32
|
assert_equal 'Hello Rack!', results.last
|
|
36
|
-
|
|
33
|
+
Coverband.report_coverage
|
|
37
34
|
expected = [nil, nil, 0, nil, 0, 0, 1, nil, nil]
|
|
38
|
-
assert_equal expected, Coverband.configuration.store.coverage[
|
|
35
|
+
assert_equal expected, Coverband.configuration.store.coverage[@rack_file]['data']
|
|
39
36
|
|
|
40
37
|
# additional calls increase count by 1
|
|
41
38
|
middleware.call(request)
|
|
42
|
-
|
|
39
|
+
Coverband.report_coverage
|
|
43
40
|
expected = [nil, nil, 0, nil, 0, 0, 2, nil, nil]
|
|
44
|
-
assert_equal expected, Coverband.configuration.store.coverage[
|
|
41
|
+
assert_equal expected, Coverband.configuration.store.coverage[@rack_file]['data']
|
|
42
|
+
|
|
43
|
+
# class coverage
|
|
44
|
+
Coverband.eager_loading_coverage!
|
|
45
|
+
Coverband.configuration.store.coverage[@rack_file]['data']
|
|
46
|
+
expected = [nil, nil, 1, nil, 1, 1, 0, nil, nil]
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
test 'call app with gem tracking' do
|
|
48
50
|
require 'rainbow'
|
|
49
51
|
Rainbow('this text is red').red
|
|
50
52
|
request = Rack::MockRequest.env_for('/anything.json')
|
|
51
|
-
middleware = Coverband::
|
|
53
|
+
middleware = Coverband::BackgroundMiddleware.new(fake_app_with_lines)
|
|
52
54
|
results = middleware.call(request)
|
|
53
55
|
assert_equal 'Hello Rack!', results.last
|
|
54
|
-
|
|
56
|
+
Coverband.report_coverage
|
|
55
57
|
assert Coverband.configuration.store.coverage.keys.any? { |key| key.end_with?('rainbow/global.rb') }
|
|
56
58
|
end
|
|
57
59
|
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('boot', __dir__)
|
|
4
|
+
|
|
5
|
+
require 'rails'
|
|
6
|
+
require 'action_controller/railtie'
|
|
7
|
+
require 'coverband'
|
|
8
|
+
Bundler.require(*Rails.groups)
|
|
2
9
|
|
|
3
|
-
require "rails"
|
|
4
|
-
require "action_controller/railtie"
|
|
5
10
|
module Rails4Dummy
|
|
6
11
|
class Application < Rails::Application
|
|
7
|
-
# Coverband needs to be setup before any of the initializers to capture usage of them
|
|
8
|
-
Coverband.configure(File.open("#{Rails.root}/config/coverband.rb"))
|
|
9
|
-
config.middleware.use Coverband::Middleware
|
|
10
|
-
config.before_initialize do
|
|
11
|
-
Coverband.start
|
|
12
|
-
end
|
|
13
12
|
config.eager_load = true
|
|
14
13
|
end
|
|
15
14
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
Coverband.configure do |config|
|
|
2
2
|
config.root = Dir.pwd
|
|
3
|
-
config.store = Coverband::Adapters::RedisStore.new(Redis.new(url: ENV['REDIS_URL'])) if defined? Redis
|
|
3
|
+
config.store = Coverband::Adapters::RedisStore.new(Redis.new(url: ENV['REDIS_URL']), redis_namespace: 'coverband_test') if defined? Redis
|
|
4
4
|
config.ignore = %w[vendor .erb$ .slim$]
|
|
5
5
|
config.root_paths = []
|
|
6
|
-
config.logger
|
|
6
|
+
config.logger = Rails.logger
|
|
7
7
|
config.verbose = true
|
|
8
|
-
config.background_reporting_enabled =
|
|
8
|
+
config.background_reporting_enabled = true
|
|
9
9
|
config.track_gems = true
|
|
10
10
|
config.gem_details = true
|
|
11
|
+
config.use_oneshot_lines_coverage = true if ENV['ONESHOT']
|
|
12
|
+
config.simulate_oneshot_lines_coverage = true if ENV['SIMULATE_ONESHOT']
|
|
11
13
|
end
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails'
|
|
4
|
+
require 'action_controller/railtie'
|
|
3
5
|
require 'coverband'
|
|
6
|
+
Bundler.require(*Rails.groups)
|
|
4
7
|
|
|
5
|
-
module
|
|
8
|
+
module Rails5Dummy
|
|
6
9
|
class Application < Rails::Application
|
|
7
|
-
# Coverband needs to be setup before any of the initializers to capture usage of them
|
|
8
|
-
Coverband.configure(File.open("#{Rails.root}/config/coverband.rb"))
|
|
9
|
-
config.middleware.use Coverband::Middleware
|
|
10
|
-
config.before_initialize do
|
|
11
|
-
Coverband.start
|
|
12
|
-
end
|
|
13
10
|
config.eager_load = true
|
|
14
11
|
end
|
|
15
12
|
end
|
|
16
|
-
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
Coverband.configure do |config|
|
|
2
2
|
config.root = Dir.pwd
|
|
3
|
-
config.store = Coverband::Adapters::RedisStore.new(Redis.new(url: ENV['REDIS_URL'])) if defined? Redis
|
|
3
|
+
config.store = Coverband::Adapters::RedisStore.new(Redis.new(url: ENV['REDIS_URL']), redis_namespace: 'coverband_test') if defined? Redis
|
|
4
4
|
config.ignore = %w[vendor .erb$ .slim$]
|
|
5
5
|
config.root_paths = []
|
|
6
6
|
config.logger = Rails.logger
|
|
7
7
|
config.verbose = true
|
|
8
|
-
config.background_reporting_enabled =
|
|
8
|
+
config.background_reporting_enabled = true
|
|
9
9
|
config.track_gems = true
|
|
10
10
|
config.gem_details = true
|
|
11
|
+
config.use_oneshot_lines_coverage = true if ENV['ONESHOT']
|
|
12
|
+
config.simulate_oneshot_lines_coverage = true if ENV['SIMULATE_ONESHOT']
|
|
11
13
|
end
|
data/test/rails_test_helper.rb
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'minitest'
|
|
4
|
+
require 'minitest/fork_executor'
|
|
5
|
+
|
|
6
|
+
# Forked executor includes autorun which does not work with qrush/m
|
|
7
|
+
# https://github.com/qrush/m/issues/26
|
|
8
|
+
# https://github.com/seattlerb/minitest/blob/master/lib/minitest/autorun.rb
|
|
9
|
+
if defined?(M)
|
|
10
|
+
Minitest.class_eval do
|
|
11
|
+
def self.autorun
|
|
12
|
+
puts 'No autorunning'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Minitest.parallel_executor = Minitest::ForkExecutor.new
|
|
1
18
|
require File.expand_path('./test_helper', File.dirname(__FILE__))
|
|
2
19
|
require 'capybara'
|
|
3
20
|
require 'capybara/minitest'
|
|
4
21
|
def rails_setup
|
|
5
|
-
ENV[
|
|
22
|
+
ENV['RAILS_ENV'] = 'test'
|
|
6
23
|
require 'rails'
|
|
7
|
-
#coverband must be required after rails
|
|
8
|
-
load 'coverband/utils/railtie.rb'
|
|
24
|
+
# coverband must be required after rails
|
|
9
25
|
Coverband.configure("./test/rails#{Rails::VERSION::MAJOR}_dummy/config/coverband.rb")
|
|
26
|
+
load 'coverband/utils/railtie.rb'
|
|
27
|
+
|
|
10
28
|
require_relative "../test/rails#{Rails::VERSION::MAJOR}_dummy/config/environment"
|
|
11
29
|
require 'capybara/rails'
|
|
12
|
-
#Our coverage report is wrapped in display:none as of now
|
|
30
|
+
# Our coverage report is wrapped in display:none as of now
|
|
13
31
|
Capybara.ignore_hidden_elements = false
|
|
14
32
|
require 'mocha/minitest'
|
|
15
33
|
end
|
|
16
|
-
|
data/test/test_helper.rb
CHANGED
|
@@ -7,8 +7,8 @@ original_verbosity = $VERBOSE
|
|
|
7
7
|
$VERBOSE = nil
|
|
8
8
|
require 'rubygems'
|
|
9
9
|
require 'aws-sdk-s3'
|
|
10
|
-
require 'coveralls'
|
|
11
10
|
require 'simplecov'
|
|
11
|
+
require 'coveralls'
|
|
12
12
|
require 'minitest/autorun'
|
|
13
13
|
require 'mocha/minitest'
|
|
14
14
|
require 'ostruct'
|
|
@@ -19,17 +19,29 @@ require 'pry-byebug'
|
|
|
19
19
|
require_relative 'unique_files'
|
|
20
20
|
$VERBOSE = original_verbosity
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
unless ENV['ONESHOT'] || ENV['SIMULATE_ONESHOT']
|
|
23
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
|
24
|
+
SimpleCov.start do
|
|
25
|
+
add_filter 'test/forked'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Coveralls.wear!
|
|
29
|
+
end
|
|
30
|
+
|
|
23
31
|
|
|
24
32
|
module Coverband
|
|
25
33
|
module Test
|
|
26
34
|
def self.reset
|
|
27
|
-
|
|
35
|
+
Coverband.configuration.redis_namespace = 'coverband_test'
|
|
36
|
+
Coverband.configuration.store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
37
|
+
Coverband.configuration.store.class.class_variable_set(:@@path_cache, {})
|
|
38
|
+
[:eager_loading, :runtime].each do |type|
|
|
28
39
|
Coverband.configuration.store.type = type
|
|
29
40
|
Coverband.configuration.store.clear!
|
|
30
41
|
end
|
|
31
42
|
Coverband.configuration.reset
|
|
32
43
|
Coverband::Collectors::Coverage.instance.reset_instance
|
|
44
|
+
Coverband.configuration.redis_namespace = 'coverband_test'
|
|
33
45
|
Coverband::Background.stop
|
|
34
46
|
end
|
|
35
47
|
|
|
@@ -60,6 +72,7 @@ def test(name, &block)
|
|
|
60
72
|
false
|
|
61
73
|
end
|
|
62
74
|
raise "#{test_name} is already defined in #{self}" if defined
|
|
75
|
+
|
|
63
76
|
if block_given?
|
|
64
77
|
define_method(test_name, &block)
|
|
65
78
|
else
|
|
@@ -83,16 +96,41 @@ def basic_coverage
|
|
|
83
96
|
{ 'app_path/dog.rb' => example_line }
|
|
84
97
|
end
|
|
85
98
|
|
|
99
|
+
def basic_coverage_full_path
|
|
100
|
+
{ basic_coverage_file_full_path => example_line }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def basic_source_fixture_coverage
|
|
104
|
+
{ source_fixture('sample.rb') => example_line }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def basic_coverage_file_full_path
|
|
108
|
+
"#{test_root}/dog.rb"
|
|
109
|
+
end
|
|
110
|
+
|
|
86
111
|
def source_fixture(filename)
|
|
87
112
|
File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', filename))
|
|
88
113
|
end
|
|
89
114
|
|
|
115
|
+
def fixtures_root
|
|
116
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
|
117
|
+
end
|
|
118
|
+
|
|
90
119
|
def test_root
|
|
91
120
|
File.expand_path(File.join(File.dirname(__FILE__)))
|
|
92
121
|
end
|
|
93
122
|
|
|
123
|
+
###
|
|
124
|
+
# This handles an issue where the store is setup in tests prior to being able to set the namespace
|
|
125
|
+
###
|
|
94
126
|
def store
|
|
95
|
-
Coverband.configuration.store
|
|
127
|
+
if Coverband.configuration.store.redis_namespace=='coverband_test'
|
|
128
|
+
Coverband.configuration.store
|
|
129
|
+
else
|
|
130
|
+
Coverband.configuration.redis_namespace = 'coverband_test'
|
|
131
|
+
Coverband.configuration.instance_variable_set(:@store, nil)
|
|
132
|
+
Coverband.configuration.store
|
|
133
|
+
end
|
|
96
134
|
end
|
|
97
135
|
|
|
98
136
|
# Taken from http://stackoverflow.com/questions/4459330/how-do-i-temporarily-redirect-stderr-in-ruby
|
data/test/unique_files.rb
CHANGED
|
@@ -2,22 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
require 'securerandom'
|
|
4
4
|
require 'fileutils'
|
|
5
|
+
require 'erb'
|
|
6
|
+
require 'ostruct'
|
|
5
7
|
|
|
6
|
-
UNIQUE_FILES_DIR =
|
|
8
|
+
UNIQUE_FILES_DIR = './test/unique_files'
|
|
7
9
|
|
|
8
|
-
def require_unique_file(file = 'dog.rb')
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
def require_unique_file(file = 'dog.rb', variables = {})
|
|
11
|
+
uuid = SecureRandom.uuid
|
|
12
|
+
dir = "#{UNIQUE_FILES_DIR}/#{uuid}"
|
|
13
|
+
file_name = file.sub('.erb', '')
|
|
14
|
+
temp_file = "#{dir}/#{file_name}"
|
|
15
|
+
FileUtils.mkdir_p(Pathname.new(temp_file).dirname.to_s)
|
|
16
|
+
file_contents = File.read("./test/#{file}")
|
|
17
|
+
file_contents = ERB.new(file_contents).result(OpenStruct.new(variables).instance_eval { binding }) if variables.any?
|
|
18
|
+
File.open(temp_file, 'w') { |w| w.write(file_contents) }
|
|
13
19
|
require temp_file
|
|
14
|
-
temp_file
|
|
20
|
+
Coverband::Utils::FilePathHelper.full_path_to_relative(File.expand_path(temp_file))
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
def remove_unique_files
|
|
18
24
|
FileUtils.rm_r(UNIQUE_FILES_DIR) if File.exist?(UNIQUE_FILES_DIR)
|
|
19
25
|
end
|
|
20
26
|
|
|
21
|
-
Minitest
|
|
22
|
-
|
|
27
|
+
if defined?(Minitest)
|
|
28
|
+
Minitest.after_run do
|
|
29
|
+
remove_unique_files
|
|
30
|
+
end
|
|
23
31
|
end
|
data/views/file_list.erb
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
<%= link_to_source_file(source_file) %>
|
|
40
40
|
</td>
|
|
41
41
|
<td class="<%= coverage_css_class(source_file.covered_percent) %> strong"><%= source_file.covered_percent.round(2).to_s %> %</td>
|
|
42
|
-
<% runtime_percentage = result.
|
|
42
|
+
<% runtime_percentage = result.runtime_relevant_coverage(source_file) %>
|
|
43
43
|
<td class="<%= "#{coverage_css_class(runtime_percentage)}" %> strong">
|
|
44
44
|
<%= "#{runtime_percentage || '0'} %" %>
|
|
45
45
|
</td>
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
<td><%= source_file.covered_lines.count + source_file.missed_lines.count %></td>
|
|
48
48
|
<td><%= source_file.covered_lines.count %></td>
|
|
49
49
|
<td>
|
|
50
|
-
<%= result.file_with_type(source_file, Coverband::RUNTIME_TYPE)
|
|
50
|
+
<%= result.file_with_type(source_file, Coverband::RUNTIME_TYPE)&.covered_lines_count || 0 %>
|
|
51
51
|
</td>
|
|
52
52
|
<td><%= source_file.missed_lines.count %></td>
|
|
53
53
|
<td><%= source_file.covered_strength %></td>
|
data/views/gem_list.erb
CHANGED
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
<tr>
|
|
21
21
|
<th>Gem</th>
|
|
22
22
|
<th>% covered</th>
|
|
23
|
+
<th>% runtime</th>
|
|
23
24
|
<th>Relevant Lines</th>
|
|
24
25
|
<th>Lines covered</th>
|
|
26
|
+
<th>Lines runtime</th>
|
|
25
27
|
<th>Lines missed</th>
|
|
26
28
|
<th>Avg. Hits / Line</th>
|
|
27
29
|
</tr>
|
|
@@ -37,10 +39,17 @@
|
|
|
37
39
|
<% end %>
|
|
38
40
|
</td>
|
|
39
41
|
<td class="<%= coverage_css_class(source_file.covered_percent) %> strong"><%= source_file.covered_percent.round(2).to_s %> %</td>
|
|
42
|
+
<% runtime_percentage = result.group_file_list_with_type(title, source_file, Coverband::RUNTIME_TYPE)&.formatted_covered_percent %>
|
|
43
|
+
<td class="<%= "#{coverage_css_class(runtime_percentage)}" %> strong">
|
|
44
|
+
<%= "#{runtime_percentage || '0'} %" %>
|
|
45
|
+
</td>
|
|
40
46
|
<td><%= source_file.covered_lines + source_file.missed_lines %></td>
|
|
41
47
|
<td><%= source_file.covered_lines %></td>
|
|
48
|
+
<td>
|
|
49
|
+
<%= result.group_file_list_with_type(title, source_file, Coverband::RUNTIME_TYPE)&.covered_lines || 0 %>
|
|
50
|
+
</td>
|
|
42
51
|
<td><%= source_file.missed_lines %></td>
|
|
43
|
-
<td><%= source_file.covered_strength %></td>
|
|
52
|
+
<td><%= source_file.covered_strength.round(1) %></td>
|
|
44
53
|
</tr>
|
|
45
54
|
<% end %>
|
|
46
55
|
</tbody>
|
data/views/layout.erb
CHANGED
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
<div id="header">
|
|
19
19
|
<a href='<%= base_path %>'>Coverband Admin</a>
|
|
20
20
|
<a href='<%= base_path %>settings'>Info</a>
|
|
21
|
-
<%= button("#{base_path}collect_coverage", 'force coverage collection') %>
|
|
22
|
-
<%= button("#{base_path}reload_files", 'reload Coverband files') %>
|
|
23
21
|
<% if Coverband.configuration.web_enable_clear %>
|
|
24
22
|
<%= button("#{base_path}clear", 'clear coverage report', delete: true) %>
|
|
25
23
|
<% end %>
|
|
@@ -31,6 +29,11 @@
|
|
|
31
29
|
<div class="notice"><%= notice %></div>
|
|
32
30
|
<% end %>
|
|
33
31
|
<div class="timestamp">Generated <%= timeago(Time.now) %></div>
|
|
32
|
+
<br/>
|
|
33
|
+
<div class="timestamp">
|
|
34
|
+
Coverage Recording Started: <%= timeago(result.source_files.first_seen_at) %>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
34
37
|
<ul class="group_tabs"></ul>
|
|
35
38
|
|
|
36
39
|
<div id="content">
|
|
@@ -48,7 +51,11 @@
|
|
|
48
51
|
<div class="source_files">
|
|
49
52
|
<% result.source_files.each do |source_file| %>
|
|
50
53
|
<% if (!source_file.gem? || (view_gems? && gem_details? && source_file.gem? )) %>
|
|
51
|
-
|
|
54
|
+
<% if static_html? %>
|
|
55
|
+
<%= formatted_source_file(result, source_file) %>
|
|
56
|
+
<% else %>
|
|
57
|
+
<%= formatted_source_file_loader(result, source_file) %>
|
|
58
|
+
<% end %>
|
|
52
59
|
<% end %>
|
|
53
60
|
<% end %>
|
|
54
61
|
</div>
|
data/views/source_file.erb
CHANGED
|
@@ -2,14 +2,23 @@
|
|
|
2
2
|
<div class="header">
|
|
3
3
|
<h3><%= shortened_filename source_file %></h3>
|
|
4
4
|
<h4>
|
|
5
|
-
<span class="<%= coverage_css_class(source_file.covered_percent) %>"
|
|
6
|
-
|
|
5
|
+
<span class="<%= coverage_css_class(source_file.covered_percent) %>">
|
|
6
|
+
<%= source_file.covered_percent.round(2).to_s %> %
|
|
7
|
+
</span>
|
|
8
|
+
covered,
|
|
9
|
+
|
|
10
|
+
<span class="<%= coverage_css_class(source_file.covered_percent) %>">
|
|
11
|
+
<%= result.runtime_relevant_coverage(source_file) %> %
|
|
12
|
+
</span>
|
|
13
|
+
runtime covered
|
|
14
|
+
|
|
7
15
|
<% if Coverband.configuration.web_enable_clear %>
|
|
8
16
|
<%= button("#{base_path}clear_file?filename=#{source_file.relative_path}", 'clear file coverage') %>
|
|
9
17
|
<% end %>
|
|
10
18
|
</h4>
|
|
11
19
|
<div>
|
|
12
20
|
<b><%= source_file.lines_of_code %></b> relevant lines.
|
|
21
|
+
<b><%= result.runtime_relavent_lines(source_file) %></b> runtime relevant lines.
|
|
13
22
|
<span class="green"><b><%= source_file.covered_lines.count %></b> lines covered</span> and
|
|
14
23
|
<span class="red"><b><%= source_file.missed_lines.count %></b> lines missed.</span>
|
|
15
24
|
</div>
|
|
@@ -25,9 +34,9 @@
|
|
|
25
34
|
<li class="<%= line.status %>" data-hits="<%= line.coverage ? line.coverage : '' %>" data-linenumber="<%= line.number %>">
|
|
26
35
|
<% if line.covered? %><span class="hits">
|
|
27
36
|
load:
|
|
28
|
-
<%= result.file_with_type(source_file, Coverband::EAGER_TYPE)
|
|
37
|
+
<%= result.file_with_type(source_file, Coverband::EAGER_TYPE)&.line_coverage(index) || 0 %>,
|
|
29
38
|
runtime:
|
|
30
|
-
<%= result.file_with_type(source_file, Coverband::RUNTIME_TYPE)
|
|
39
|
+
<%= result.file_with_type(source_file, Coverband::RUNTIME_TYPE)&.line_coverage(index) || 0 %>
|
|
31
40
|
all: <%= line.coverage %>
|
|
32
41
|
</span><% end %>
|
|
33
42
|
<% if line.skipped? %><span class="hits">skipped</span><% end %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="source_table" id="<%= id source_file %>" data-loader-url="<%= base_path %>load_file_details?filename=<%= source_file.filename %>">
|
|
2
2
|
<div class='loader'>
|
|
3
|
-
loading...
|
|
3
|
+
loading source data...
|
|
4
4
|
<br/>
|
|
5
5
|
<img src="<%= assets_path('loading.gif') %>" alt="loading"/>
|
|
6
6
|
</div>
|