coverband 4.2.0 → 4.2.2
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 -8
- data/CODE_OF_CONDUCT.md +76 -0
- data/Gemfile +3 -1
- data/Gemfile.rails4 +1 -0
- data/README.md +72 -43
- data/Rakefile +14 -3
- data/changes.md +66 -11
- data/coverband.gemspec +2 -5
- data/lib/coverband/adapters/base.rb +64 -45
- data/lib/coverband/adapters/file_store.rb +15 -9
- data/lib/coverband/adapters/hash_redis_store.rb +182 -0
- data/lib/coverband/adapters/redis_store.rb +33 -11
- data/lib/coverband/at_exit.rb +2 -11
- data/lib/coverband/collectors/coverage.rb +34 -40
- data/lib/coverband/collectors/delta.rb +34 -28
- data/lib/coverband/collectors/view_tracker.rb +124 -0
- data/lib/coverband/configuration.rb +96 -32
- data/lib/coverband/integrations/background.rb +9 -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 +40 -16
- data/lib/coverband/reporters/console_report.rb +1 -0
- data/lib/coverband/reporters/html_report.rb +21 -27
- data/lib/coverband/reporters/web.rb +19 -21
- data/lib/coverband/utils/absolute_file_converter.rb +47 -0
- data/lib/coverband/utils/file_hasher.rb +16 -0
- data/lib/coverband/utils/file_list.rb +16 -5
- data/lib/coverband/utils/html_formatter.rb +37 -8
- data/lib/coverband/utils/lines_classifier.rb +5 -0
- data/lib/coverband/utils/railtie.rb +20 -9
- data/lib/coverband/utils/relative_file_converter.rb +41 -0
- data/lib/coverband/utils/result.rb +1 -37
- data/lib/coverband/utils/results.rb +51 -0
- data/lib/coverband/utils/s3_report.rb +2 -2
- data/lib/coverband/utils/source_file.rb +31 -8
- data/lib/coverband/utils/tasks.rb +10 -10
- data/lib/coverband/version.rb +5 -1
- data/lib/coverband.rb +39 -22
- data/public/application.css +6 -6
- data/public/application.js +27 -0
- data/test/benchmarks/benchmark.rake +167 -73
- data/test/benchmarks/init_rails.rake +10 -0
- data/test/coverband/adapters/base_test.rb +73 -42
- data/test/coverband/adapters/file_store_test.rb +48 -37
- data/test/coverband/adapters/hash_redis_store_test.rb +190 -0
- data/test/coverband/adapters/redis_store_test.rb +92 -59
- data/test/coverband/at_exit_test.rb +0 -2
- data/test/coverband/collectors/coverage_test.rb +62 -10
- data/test/coverband/collectors/delta_test.rb +36 -6
- data/test/coverband/collectors/view_tracker_test.rb +77 -0
- 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 +6 -6
- data/test/coverband/integrations/test_resque_job.rb +3 -1
- data/test/coverband/reporters/base_test.rb +2 -79
- data/test/coverband/reporters/console_test.rb +2 -6
- data/test/coverband/reporters/html_test.rb +58 -19
- data/test/coverband/reporters/web_test.rb +0 -10
- data/test/coverband/utils/absolute_file_converter_test.rb +56 -0
- data/test/coverband/utils/file_groups_test.rb +11 -5
- data/test/coverband/utils/file_hasher_test.rb +29 -0
- data/test/coverband/utils/file_list_test.rb +5 -5
- data/test/coverband/utils/html_formatter_test.rb +43 -0
- data/test/coverband/utils/relative_file_converter_test.rb +39 -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 +48 -0
- data/test/integration/full_stack_test.rb +17 -16
- 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 +45 -8
- 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 +6 -18
- data/views/nav.erb +35 -0
- data/views/source_file.erb +13 -4
- data/views/source_file_loader.erb +1 -1
- data/views/view_tracker.erb +37 -0
- metadata +59 -25
- data/lib/coverband/utils/file_path_helper.rb +0 -57
- data/test/coverband/integrations/middleware_test.rb +0 -96
- data/test/integration/rails_full_stack_test.rb +0 -95
|
@@ -9,7 +9,7 @@ require File.expand_path('../../test_helper', File.dirname(__FILE__))
|
|
|
9
9
|
describe Coverband::Utils::FileList do
|
|
10
10
|
subject do
|
|
11
11
|
original_result = {
|
|
12
|
-
source_fixture('sample.rb') => [nil, 1, 1, 1, nil, nil, 1, 1, nil, nil],
|
|
12
|
+
source_fixture('sample.rb') => {'first_updated_at' => Time.at(0), 'data' => [nil, 1, 1, 1, nil, nil, 1, 1, nil, nil]},
|
|
13
13
|
source_fixture('app/models/user.rb') => [nil, 1, 1, 1, nil, nil, 1, 0, nil, nil],
|
|
14
14
|
source_fixture('app/controllers/sample_controller.rb') => [nil, 2, 2, 0, nil, nil, 0, nil, nil, nil]
|
|
15
15
|
}
|
|
@@ -44,11 +44,11 @@ describe Coverband::Utils::FileList do
|
|
|
44
44
|
assert_equal [50.0, 80.0, 100.0], subject.covered_percentages
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
it 'has the correct least covered file' do
|
|
48
|
-
assert subject.least_covered_file.match(/sample_controller.rb/)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
47
|
it 'has the correct covered strength' do
|
|
52
48
|
assert_equal 0.9285714285714286, subject.covered_strength
|
|
53
49
|
end
|
|
50
|
+
|
|
51
|
+
it 'has correct first_seen_at' do
|
|
52
|
+
assert_equal Time.at(0), subject.first_seen_at
|
|
53
|
+
end
|
|
54
54
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../test_helper', File.dirname(__FILE__))
|
|
4
|
+
|
|
5
|
+
class HTMLFormatterTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
super
|
|
8
|
+
@redis = Redis.new
|
|
9
|
+
@store = Coverband::Adapters::RedisStore.new(@redis, redis_namespace: 'coverband_test')
|
|
10
|
+
@store.clear!
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test 'generate dynamic content hosted html report' do
|
|
14
|
+
Coverband.configure do |config|
|
|
15
|
+
config.store = @store
|
|
16
|
+
config.ignore = ['notsomething.rb']
|
|
17
|
+
end
|
|
18
|
+
mock_file_hash
|
|
19
|
+
@store.send(:save_report, basic_coverage_full_path)
|
|
20
|
+
|
|
21
|
+
notice = nil
|
|
22
|
+
base_path = '/coverage'
|
|
23
|
+
filtered_report_files = Coverband::Reporters::Base.report(@store, {})
|
|
24
|
+
html = Coverband::Utils::HTMLFormatter.new(filtered_report_files,
|
|
25
|
+
base_path: base_path,
|
|
26
|
+
notice: notice).format_dynamic_html!
|
|
27
|
+
assert_match 'loading source data', html
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test 'generate static HTML report file' do
|
|
31
|
+
Coverband.configure do |config|
|
|
32
|
+
config.store = @store
|
|
33
|
+
config.ignore = ['notsomething.rb']
|
|
34
|
+
end
|
|
35
|
+
mock_file_hash
|
|
36
|
+
@store.send(:save_report, basic_coverage_full_path)
|
|
37
|
+
|
|
38
|
+
filtered_report_files = Coverband::Reporters::Base.report(@store, {})
|
|
39
|
+
Coverband::Utils::HTMLFormatter.new(filtered_report_files).format_static_html!
|
|
40
|
+
html = File.read("#{Coverband.configuration.root}/coverage/index.html")
|
|
41
|
+
assert_match 'Coverage first seen', html
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../test_helper', File.dirname(__FILE__))
|
|
4
|
+
|
|
5
|
+
module Coverband
|
|
6
|
+
module Utils
|
|
7
|
+
class RelativeFileConverterTest < ::Minitest::Test
|
|
8
|
+
def test_convert
|
|
9
|
+
converter = RelativeFileConverter.new(['/bar/tmp/'])
|
|
10
|
+
assert_equal('./gracie.rb', converter.convert('/bar/tmp/gracie.rb'))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_convert_without_leading_forward_slash
|
|
14
|
+
converter = RelativeFileConverter.new(['/foo/bar'])
|
|
15
|
+
assert_equal('./file.rb', converter.convert('/foo/bar/file.rb'))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_multiple_roots
|
|
19
|
+
converter = RelativeFileConverter.new(['/bar/tmp/', '/foo/bar/'])
|
|
20
|
+
assert_equal('./josie.rb', converter.convert('/foo/bar/josie.rb'))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_no_match
|
|
24
|
+
converter = RelativeFileConverter.new(['/bar/tmp/', '/foo/bar/'])
|
|
25
|
+
assert_equal('/foo/josie.rb', converter.convert('/foo/josie.rb'))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_middle_path_match
|
|
29
|
+
converter = RelativeFileConverter.new(['/bar/tmp/', '/foo/bar/'])
|
|
30
|
+
assert_equal('/tmp/foo/bar/josie.rb', converter.convert('/tmp/foo/bar/josie.rb'))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_already_relative_file
|
|
34
|
+
converter = RelativeFileConverter.new(['/bar/tmp/', '/foo/bar/'])
|
|
35
|
+
assert_equal('./foo/bar/josie.rb', converter.convert('./foo/bar/josie.rb'))
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -48,57 +48,16 @@ describe 'result' do
|
|
|
48
48
|
assert_equal [80.0, 80.0, 100.0], subject.covered_percentages
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
:least_covered_file,
|
|
58
|
-
:covered_strength,
|
|
59
|
-
:covered_lines,
|
|
60
|
-
:missed_lines,
|
|
61
|
-
:total_lines].each do |msg|
|
|
51
|
+
%i[covered_percent
|
|
52
|
+
covered_percentages
|
|
53
|
+
covered_strength
|
|
54
|
+
covered_lines
|
|
55
|
+
missed_lines
|
|
56
|
+
total_lines].each do |msg|
|
|
62
57
|
it "responds to #{msg}" do
|
|
63
58
|
assert(subject.respond_to?(msg))
|
|
64
59
|
end
|
|
65
60
|
end
|
|
66
|
-
|
|
67
|
-
describe 'dumped with to_hash' do
|
|
68
|
-
it 'is a hash' do
|
|
69
|
-
assert subject.to_hash.is_a?(Hash)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
describe 'loaded back with from_hash' do
|
|
73
|
-
let(:dumped_result) do
|
|
74
|
-
Coverband::Utils::Result.from_hash(subject.to_hash)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it 'has 3 source files' do
|
|
78
|
-
assert_equal subject.source_files.count, dumped_result.source_files.count
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it 'has the same covered_percent' do
|
|
82
|
-
assert_equal subject.covered_percent, dumped_result.covered_percent
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it 'has the same covered_percentages' do
|
|
86
|
-
assert_equal subject.covered_percentages, dumped_result.covered_percentages
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it 'has the same timestamp' do
|
|
90
|
-
assert_equal subject.created_at.to_i, dumped_result.created_at.to_i
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it 'has the same command_name' do
|
|
94
|
-
assert_equal subject.command_name, dumped_result.command_name
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it 'has the same original_result' do
|
|
98
|
-
assert_equal subject.original_result, dumped_result.original_result
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
61
|
end
|
|
103
62
|
end
|
|
104
63
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../test_helper', File.dirname(__FILE__))
|
|
4
|
+
|
|
5
|
+
describe 'results' do
|
|
6
|
+
describe 'with a (mocked) Coverage.result' do
|
|
7
|
+
let(:source_file) { Coverband::Utils::SourceFile.new(source_fixture('app/models/user.rb'), run_lines) }
|
|
8
|
+
let(:eager_lines) { [nil, 1, 1, 0, nil, nil, 1, 0, nil, nil] }
|
|
9
|
+
let(:run_lines) { [nil, nil, nil, 1, nil, nil, nil,nil, nil, nil] }
|
|
10
|
+
let(:original_result) do
|
|
11
|
+
orig = {
|
|
12
|
+
Coverband::MERGED_TYPE => {source_fixture('app/models/user.rb') => eager_lines},
|
|
13
|
+
}
|
|
14
|
+
orig.merge!({Coverband::EAGER_TYPE => {source_fixture('app/models/user.rb') => eager_lines}}) if eager_lines
|
|
15
|
+
orig.merge!({Coverband::RUNTIME_TYPE => {source_fixture('app/models/user.rb') => run_lines}}) if run_lines
|
|
16
|
+
orig
|
|
17
|
+
end
|
|
18
|
+
subject { Coverband::Utils::Results.new(original_result) }
|
|
19
|
+
|
|
20
|
+
describe 'runtime relevant lines is supported' do
|
|
21
|
+
it 'has correct runtime relevant coverage' do
|
|
22
|
+
assert_equal 50.0, subject.runtime_relevant_coverage(source_file)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'has correct runtime relevant lines' do
|
|
26
|
+
assert_equal 2, subject.runtime_relavent_lines(source_file)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'runtime relevant lines when no runtime coverage exists' do
|
|
31
|
+
let(:run_lines) { nil }
|
|
32
|
+
|
|
33
|
+
it 'has correct runtime relevant lines' do
|
|
34
|
+
assert_equal 0.0, subject.runtime_relevant_coverage(source_file)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'has correct runtime relevant lines' do
|
|
38
|
+
assert_equal 2, subject.runtime_relavent_lines(source_file)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'runtime relevant lines when no eager coverage exists' do
|
|
43
|
+
let(:eager_lines) { nil }
|
|
44
|
+
|
|
45
|
+
it 'has correct runtime relevant lines' do
|
|
46
|
+
assert_equal 100.0, subject.runtime_relevant_coverage(source_file)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'has correct runtime relevant lines' do
|
|
50
|
+
assert_equal 1, subject.runtime_relavent_lines(source_file)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -146,4 +146,54 @@ describe Coverband::Utils::SourceFile do
|
|
|
146
146
|
assert_equal 0.0, subject.covered_percent
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
|
+
|
|
150
|
+
describe 'correctly identifies gems' do
|
|
151
|
+
COVERAGE_FOR_SKIPPED_AND_EXECUTED_RB = [nil, nil, 1, 1, 0, 1, 1, nil].freeze
|
|
152
|
+
|
|
153
|
+
describe 'the word gem in a path' do
|
|
154
|
+
subject do
|
|
155
|
+
Coverband::Utils::SourceFile.new('lib/rubocop/cop/gemspec/required_ruby_version.rb', COVERAGE_FOR_SKIPPED_AND_EXECUTED_RB)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'allows the word gem in path' do
|
|
159
|
+
assert_equal nil, subject.gem?
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
describe 'a folder gem in the path' do
|
|
164
|
+
subject do
|
|
165
|
+
Coverband::Utils::SourceFile.new('/var/gems/rubocop-0.67.0/lib/rubocop/cop/gemspec/required_ruby_version.rb', COVERAGE_FOR_SKIPPED_AND_EXECUTED_RB)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'allows the word gem in path' do
|
|
169
|
+
assert subject.gem?
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe 'correctly reports gem name' do
|
|
175
|
+
COVERAGE_FOR_SKIPPED_AND_EXECUTED_RB = [nil, nil, 1, 1, 0, 1, 1, nil].freeze
|
|
176
|
+
|
|
177
|
+
describe 'the word gem in a path' do
|
|
178
|
+
subject do
|
|
179
|
+
Coverband::Utils::SourceFile.new('lib/rubocop/cop/gemspec/required_ruby_version.rb', COVERAGE_FOR_SKIPPED_AND_EXECUTED_RB)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'allows the word gem in path' do
|
|
183
|
+
assert_equal nil, subject.gem_name
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
describe 'a folder gem in the path' do
|
|
188
|
+
subject do
|
|
189
|
+
Coverband::Utils::SourceFile.new('/var/gems/rubocop-0.67.0/lib/rubocop/cop/gemspec/required_ruby_version.rb', COVERAGE_FOR_SKIPPED_AND_EXECUTED_RB)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'allows the word gem in path' do
|
|
193
|
+
assert_equal 'rubocop-0.67.0', subject.gem_name
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
|
|
149
199
|
end
|
data/test/dog.rb.erb
ADDED
|
@@ -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,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../rails_test_helper', File.dirname(__FILE__))
|
|
4
|
+
require 'rails'
|
|
5
|
+
require 'pundit'
|
|
6
|
+
|
|
7
|
+
class RailsRakeFullStackTest < Minitest::Test
|
|
8
|
+
def setup
|
|
9
|
+
super
|
|
10
|
+
Coverband.configuration.reset
|
|
11
|
+
Coverband.configure("./test/rails#{Rails::VERSION::MAJOR}_dummy/config/coverband.rb")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'rake tasks shows coverage properly within eager_loading' do
|
|
15
|
+
store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
16
|
+
store.clear!
|
|
17
|
+
system("COVERBAND_CONFIG=./test/rails#{Rails::VERSION::MAJOR}_dummy/config/coverband.rb bundle exec rake -f test/rails#{Rails::VERSION::MAJOR}_dummy/Rakefile middleware")
|
|
18
|
+
store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
19
|
+
store.type = :eager_loading
|
|
20
|
+
pundit_file = store.coverage.keys.grep(/pundit.rb/).first
|
|
21
|
+
refute_nil pundit_file
|
|
22
|
+
pundit_coverage = store.coverage[pundit_file]
|
|
23
|
+
refute_nil pundit_coverage
|
|
24
|
+
assert_includes pundit_coverage['data'], 1
|
|
25
|
+
|
|
26
|
+
store.type = Coverband::RUNTIME_TYPE
|
|
27
|
+
if ENV['SIMULATE_ONESHOT']
|
|
28
|
+
pundit_coverage = store.get_coverage_report[Coverband::RUNTIME_TYPE][pundit_file]
|
|
29
|
+
assert pundit_coverage['data'].compact.all? { |el| el == 0 }
|
|
30
|
+
else
|
|
31
|
+
pundit_coverage = store.coverage[pundit_file]
|
|
32
|
+
assert_nil pundit_coverage
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
test "ignored rake tasks don't add coverage" do
|
|
37
|
+
store.clear!
|
|
38
|
+
store.instance_variable_set(:@redis_namespace, 'coverband_test')
|
|
39
|
+
store.send(:save_report, basic_coverage_full_path)
|
|
40
|
+
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`
|
|
41
|
+
assert_nil output.match(/Coverband: Reported coverage via thread/)
|
|
42
|
+
coverage_report = store.get_coverage_report
|
|
43
|
+
empty_hash = {}
|
|
44
|
+
assert_equal empty_hash, coverage_report[Coverband::RUNTIME_TYPE]
|
|
45
|
+
assert_equal empty_hash, coverage_report[:eager_loading]
|
|
46
|
+
assert_equal empty_hash, coverage_report[:merged]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -6,52 +6,53 @@ 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 =
|
|
19
|
-
config.root_paths = ["#{File.expand_path('../', File.dirname(__FILE__))}/"]
|
|
16
|
+
config.background_reporting_enabled = true
|
|
20
17
|
config.track_gems = true
|
|
21
18
|
end
|
|
22
19
|
Coverband.configuration.store.clear!
|
|
23
20
|
Coverband.start
|
|
21
|
+
Coverband::Collectors::Coverage.instance.eager_loading!
|
|
22
|
+
@rack_file = require_unique_file 'fake_app/basic_rack.rb'
|
|
23
|
+
Coverband.report_coverage
|
|
24
24
|
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
25
|
end
|
|
30
26
|
|
|
31
27
|
test 'call app' do
|
|
32
28
|
request = Rack::MockRequest.env_for('/anything.json')
|
|
33
|
-
middleware = Coverband::
|
|
29
|
+
middleware = Coverband::BackgroundMiddleware.new(fake_app_with_lines)
|
|
34
30
|
results = middleware.call(request)
|
|
35
31
|
assert_equal 'Hello Rack!', results.last
|
|
36
|
-
|
|
32
|
+
Coverband.report_coverage
|
|
37
33
|
expected = [nil, nil, 0, nil, 0, 0, 1, nil, nil]
|
|
38
|
-
assert_equal expected, Coverband.configuration.store.coverage[
|
|
34
|
+
assert_equal expected, Coverband.configuration.store.coverage[@rack_file]['data']
|
|
39
35
|
|
|
40
36
|
# additional calls increase count by 1
|
|
41
37
|
middleware.call(request)
|
|
42
|
-
|
|
38
|
+
Coverband.report_coverage
|
|
43
39
|
expected = [nil, nil, 0, nil, 0, 0, 2, nil, nil]
|
|
44
|
-
assert_equal expected, Coverband.configuration.store.coverage[
|
|
40
|
+
assert_equal expected, Coverband.configuration.store.coverage[@rack_file]['data']
|
|
41
|
+
|
|
42
|
+
# class coverage
|
|
43
|
+
Coverband.eager_loading_coverage!
|
|
44
|
+
Coverband.configuration.store.coverage[@rack_file]['data']
|
|
45
|
+
expected = [nil, nil, 1, nil, 1, 1, 0, nil, nil]
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
test 'call app with gem tracking' do
|
|
48
49
|
require 'rainbow'
|
|
49
50
|
Rainbow('this text is red').red
|
|
50
51
|
request = Rack::MockRequest.env_for('/anything.json')
|
|
51
|
-
middleware = Coverband::
|
|
52
|
+
middleware = Coverband::BackgroundMiddleware.new(fake_app_with_lines)
|
|
52
53
|
results = middleware.call(request)
|
|
53
54
|
assert_equal 'Hello Rack!', results.last
|
|
54
|
-
|
|
55
|
+
Coverband.report_coverage
|
|
55
56
|
assert Coverband.configuration.store.coverage.keys.any? { |key| key.end_with?('rainbow/global.rb') }
|
|
56
57
|
end
|
|
57
58
|
|
|
@@ -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
|
-
|