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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +29 -9
  3. data/.travis.yml +10 -1
  4. data/Gemfile +3 -1
  5. data/Gemfile.rails4 +1 -0
  6. data/README.md +40 -15
  7. data/Rakefile +14 -3
  8. data/changes.md +47 -12
  9. data/coverband.gemspec +3 -1
  10. data/lib/coverband/adapters/base.rb +60 -36
  11. data/lib/coverband/adapters/file_store.rb +8 -8
  12. data/lib/coverband/adapters/redis_store.rb +18 -10
  13. data/lib/coverband/at_exit.rb +2 -11
  14. data/lib/coverband/collectors/coverage.rb +32 -36
  15. data/lib/coverband/collectors/delta.rb +34 -28
  16. data/lib/coverband/configuration.rb +76 -32
  17. data/lib/coverband/integrations/background.rb +8 -4
  18. data/lib/coverband/integrations/{middleware.rb → background_middleware.rb} +2 -6
  19. data/lib/coverband/integrations/bundler.rb +8 -0
  20. data/lib/coverband/integrations/report_middleware.rb +15 -0
  21. data/lib/coverband/integrations/resque.rb +3 -5
  22. data/lib/coverband/reporters/base.rb +39 -14
  23. data/lib/coverband/reporters/html_report.rb +21 -27
  24. data/lib/coverband/reporters/web.rb +13 -21
  25. data/lib/coverband/utils/file_list.rb +16 -5
  26. data/lib/coverband/utils/file_path_helper.rb +14 -3
  27. data/lib/coverband/utils/html_formatter.rb +25 -8
  28. data/lib/coverband/utils/lines_classifier.rb +5 -0
  29. data/lib/coverband/utils/railtie.rb +11 -12
  30. data/lib/coverband/utils/result.rb +1 -37
  31. data/lib/coverband/utils/results.rb +51 -0
  32. data/lib/coverband/utils/source_file.rb +31 -6
  33. data/lib/coverband/utils/tasks.rb +9 -10
  34. data/lib/coverband/version.rb +1 -1
  35. data/lib/coverband.rb +32 -21
  36. data/public/application.js +27 -0
  37. data/test/benchmarks/benchmark.rake +144 -26
  38. data/test/coverband/adapters/base_test.rb +73 -42
  39. data/test/coverband/adapters/file_store_test.rb +48 -37
  40. data/test/coverband/adapters/redis_store_test.rb +41 -10
  41. data/test/coverband/at_exit_test.rb +0 -2
  42. data/test/coverband/collectors/coverage_test.rb +57 -9
  43. data/test/coverband/collectors/delta_test.rb +36 -6
  44. data/test/coverband/configuration_test.rb +47 -7
  45. data/test/coverband/coverband_test.rb +14 -2
  46. data/test/coverband/integrations/background_middleware_test.rb +44 -0
  47. data/test/coverband/integrations/background_test.rb +1 -3
  48. data/test/coverband/integrations/report_middleware_test.rb +44 -0
  49. data/test/coverband/integrations/resque_worker_test.rb +4 -3
  50. data/test/coverband/integrations/test_resque_job.rb +3 -1
  51. data/test/coverband/reporters/base_test.rb +4 -4
  52. data/test/coverband/reporters/console_test.rb +1 -2
  53. data/test/coverband/reporters/html_test.rb +58 -19
  54. data/test/coverband/reporters/web_test.rb +0 -10
  55. data/test/coverband/utils/file_groups_test.rb +11 -5
  56. data/test/coverband/utils/file_list_test.rb +5 -5
  57. data/test/coverband/utils/html_formatter_test.rb +43 -0
  58. data/test/coverband/utils/result_test.rb +6 -47
  59. data/test/coverband/utils/results_test.rb +54 -0
  60. data/test/coverband/utils/s3_report_test.rb +2 -0
  61. data/test/coverband/utils/source_file_test.rb +50 -0
  62. data/test/dog.rb.erb +12 -0
  63. data/test/forked/rails_full_stack_test.rb +106 -0
  64. data/test/forked/rails_rake_full_stack_test.rb +40 -0
  65. data/test/integration/full_stack_test.rb +17 -15
  66. data/test/rails4_dummy/Rakefile +6 -0
  67. data/test/rails4_dummy/config/application.rb +8 -9
  68. data/test/rails4_dummy/config/coverband.rb +5 -3
  69. data/test/rails5_dummy/Rakefile +6 -0
  70. data/test/rails5_dummy/config/application.rb +6 -10
  71. data/test/rails5_dummy/config/coverband.rb +4 -2
  72. data/test/rails_test_helper.rb +22 -5
  73. data/test/test_helper.rb +42 -4
  74. data/test/unique_files.rb +17 -9
  75. data/views/file_list.erb +2 -2
  76. data/views/gem_list.erb +10 -1
  77. data/views/layout.erb +10 -3
  78. data/views/source_file.erb +13 -4
  79. data/views/source_file_loader.erb +1 -1
  80. metadata +52 -9
  81. data/test/coverband/integrations/middleware_test.rb +0 -96
  82. 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.reporting_frequency = 100.0
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 = false
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::Middleware.new(fake_app_with_lines)
30
+ middleware = Coverband::BackgroundMiddleware.new(fake_app_with_lines)
34
31
  results = middleware.call(request)
35
32
  assert_equal 'Hello Rack!', results.last
36
- sleep(0.2)
33
+ Coverband.report_coverage
37
34
  expected = [nil, nil, 0, nil, 0, 0, 1, nil, nil]
38
- assert_equal expected, Coverband.configuration.store.coverage[RELATIVE_FILE]['data']
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
- sleep(0.2)
39
+ Coverband.report_coverage
43
40
  expected = [nil, nil, 0, nil, 0, 0, 2, nil, nil]
44
- assert_equal expected, Coverband.configuration.store.coverage[RELATIVE_FILE]['data']
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::Middleware.new(fake_app_with_lines)
53
+ middleware = Coverband::BackgroundMiddleware.new(fake_app_with_lines)
52
54
  results = middleware.call(request)
53
55
  assert_equal 'Hello Rack!', results.last
54
- sleep(0.1)
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
 
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative 'config/application'
5
+
6
+ Rails.application.load_tasks
@@ -1,15 +1,14 @@
1
- require File.expand_path('../boot', __FILE__)
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 = Rails.logger
6
+ config.logger = Rails.logger
7
7
  config.verbose = true
8
- config.background_reporting_enabled = false
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
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative 'config/application'
5
+
6
+ Rails.application.load_tasks
@@ -1,16 +1,12 @@
1
- require "rails"
2
- require "action_controller/railtie"
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 Dummy
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 = false
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,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["RAILS_ENV"] = "test"
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
- Coveralls.wear!
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
- [:eager_loading, nil].each do |type|
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 = "./test/unique_files"
8
+ UNIQUE_FILES_DIR = './test/unique_files'
7
9
 
8
- def require_unique_file(file = 'dog.rb')
9
- dir = "#{UNIQUE_FILES_DIR}/#{SecureRandom.uuid}"
10
- FileUtils.mkdir_p(dir)
11
- temp_file = "#{dir}/#{file}"
12
- File.open(temp_file, 'w'){ |w| w.write(File.read("./test/#{file}")) }
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.after_run do
22
- remove_unique_files
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.file_with_type(source_file, Coverband::RUNTIME_TYPE).try(:covered_percent).try(:round, 2) %>
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).try(:covered_lines).try(:count) || 0 %>
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> &nbsp;
20
20
  <a href='<%= base_path %>settings'>Info</a> &nbsp;
21
- <%= button("#{base_path}collect_coverage", 'force coverage collection') %> &nbsp;
22
- <%= button("#{base_path}reload_files", 'reload Coverband files') %> &nbsp;
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
- <%= formatted_source_file_loader(result, source_file) %>
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>
@@ -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) %>"><%= source_file.covered_percent.round(2).to_s %> %</span>
6
- covered
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') %> &nbsp;
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).try(:lines).try(:[], index).try(:coverage) || 0 %>,
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).try(:lines).try(:[], index).try(:coverage) || 0 %>
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>