simplecov 0.7.1 → 0.8.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.travis.yml +9 -2
  2. data/CHANGELOG.md +17 -2
  3. data/Gemfile +13 -2
  4. data/{LICENSE → MIT-LICENSE} +0 -0
  5. data/README.md +174 -117
  6. data/Rakefile +8 -3
  7. data/features/config_command_name.feature +12 -0
  8. data/features/config_merge_timeout.feature +3 -3
  9. data/features/config_profiles.feature +44 -0
  10. data/features/config_project_name.feature +2 -2
  11. data/features/cucumber_basic.feature +1 -1
  12. data/features/step_definitions/html_steps.rb +1 -1
  13. data/features/support/env.rb +23 -5
  14. data/gemfiles/multi_json_legacy.gemfile +12 -0
  15. data/gemfiles/multi_json_new.gemfile +12 -0
  16. data/lib/simplecov.rb +33 -25
  17. data/lib/simplecov/command_guesser.rb +6 -6
  18. data/lib/simplecov/configuration.rb +7 -2
  19. data/lib/simplecov/defaults.rb +9 -5
  20. data/lib/simplecov/file_list.rb +1 -1
  21. data/lib/simplecov/jruby16_fix.rb +43 -0
  22. data/lib/simplecov/no_defaults.rb +2 -0
  23. data/lib/simplecov/{adapters.rb → profiles.rb} +8 -8
  24. data/lib/simplecov/result.rb +10 -2
  25. data/lib/simplecov/source_file.rb +2 -3
  26. data/lib/simplecov/version.rb +1 -1
  27. data/simplecov.gemspec +8 -9
  28. data/test/faked_project/Gemfile +1 -1
  29. data/test/helper.rb +0 -1
  30. data/test/shoulda_macros.rb +0 -10
  31. data/test/test_1_8_fallbacks.rb +16 -18
  32. data/test/test_command_guesser.rb +13 -15
  33. data/test/test_deleted_source.rb +5 -7
  34. data/test/test_file_list.rb +15 -17
  35. data/test/test_filters.rb +56 -58
  36. data/test/test_merge_helpers.rb +73 -75
  37. data/test/test_result.rb +114 -116
  38. data/test/test_return_codes.rb +24 -26
  39. data/test/test_source_file.rb +75 -64
  40. data/test/test_source_file_line.rb +78 -82
  41. metadata +38 -86
  42. data/features/config_adapters.feature +0 -44
  43. data/gemfiles/multi_json-legacy.gemfile +0 -7
  44. data/gemfiles/multi_json-new.gemfile +0 -7
data/Rakefile CHANGED
@@ -21,7 +21,12 @@ Rake::TestTask.new(:test) do |test|
21
21
  test.warning = true
22
22
  end
23
23
 
24
- require 'cucumber/rake/task'
25
- Cucumber::Rake::Task.new
24
+ # Cucumber integration test suite is for impls that work with simplecov only - a.k.a. 1.9+
25
+ if '1.9+'.respond_to? :encoding
26
+ require 'cucumber/rake/task'
27
+ Cucumber::Rake::Task.new
28
+ task :default => [:test, :cucumber]
29
+ else
30
+ task :default => [:test]
31
+ end
26
32
 
27
- task :default => [:test, :cucumber]
@@ -31,3 +31,15 @@ Feature: Custom names for individual test suites
31
31
  | Dreck macht Speck |
32
32
  | I'm in UR Unitz |
33
33
 
34
+ Scenario: RSpec auto detection with spec/features
35
+ Given SimpleCov for RSpec is configured with:
36
+ """
37
+ require 'simplecov'
38
+ SimpleCov.start
39
+ """
40
+ And a file named "spec/features/foobar_spec.rb" with:
41
+ """
42
+ """
43
+ When I open the coverage report generated with `bundle exec rspec spec`
44
+ Then the report should be based upon:
45
+ | RSpec |
@@ -17,14 +17,14 @@ Feature:
17
17
  """
18
18
  require 'simplecov'
19
19
  SimpleCov.start do
20
- merge_timeout 1
20
+ merge_timeout 5
21
21
  end
22
22
  """
23
23
  Given SimpleCov for RSpec is configured with:
24
24
  """
25
25
  require 'simplecov'
26
26
  SimpleCov.start do
27
- merge_timeout 1
27
+ merge_timeout 5
28
28
  end
29
29
  """
30
30
 
@@ -32,7 +32,7 @@ Feature:
32
32
  Then the report should be based upon:
33
33
  | Unit Tests |
34
34
 
35
- When I wait for 2 seconds
35
+ When I wait for 5 seconds
36
36
  And I open the coverage report generated with `bundle exec rspec spec`
37
37
  Then the report should be based upon:
38
38
  | RSpec |
@@ -0,0 +1,44 @@
1
+ @test_unit @config @profiles
2
+ Feature:
3
+
4
+ In order to re-use SimpleCov settings across projects,
5
+ profiles can be defined that hold configuration settings
6
+ that can be loaded at once.
7
+
8
+ Background:
9
+ Given SimpleCov for Test/Unit is configured with:
10
+ """
11
+ require 'simplecov'
12
+ """
13
+
14
+ Scenario: Defining and using a custom profile
15
+ Given a file named ".simplecov" with:
16
+ """
17
+ SimpleCov.profiles.define 'custom_command' do
18
+ command_name "Profile Command"
19
+ end
20
+
21
+ SimpleCov.start do
22
+ load_profile 'test_frameworks'
23
+ load_profile 'custom_command'
24
+ end
25
+ """
26
+
27
+ When I open the coverage report generated with `bundle exec rake test`
28
+ Then I should see "4 files in total."
29
+ And I should see "using Profile Command" within "#footer"
30
+
31
+ Scenario: Using existing profile in custom profile and supplying profile to start command
32
+ Given a file named ".simplecov" with:
33
+ """
34
+ SimpleCov.profiles.define 'my_profile' do
35
+ load_profile 'test_frameworks'
36
+ command_name "My Profile"
37
+ end
38
+
39
+ SimpleCov.start 'my_profile'
40
+ """
41
+
42
+ When I open the coverage report generated with `bundle exec rake test`
43
+ Then I should see "4 files in total."
44
+ And I should see "using My Profile" within "#footer"
@@ -14,7 +14,7 @@ Feature:
14
14
  """
15
15
 
16
16
  When I open the coverage report generated with `bundle exec rake test`
17
- Then I should see "Code coverage for Project"
17
+ Then I should see "Code coverage for Project" within "title"
18
18
 
19
19
  Scenario: Custom name
20
20
  Given SimpleCov for Test/Unit is configured with:
@@ -24,4 +24,4 @@ Feature:
24
24
  """
25
25
 
26
26
  When I open the coverage report generated with `bundle exec rake test`
27
- Then I should see "Code coverage for Superfancy 2.0"
27
+ Then I should see "Code coverage for Superfancy 2.0" within "title"
@@ -19,7 +19,7 @@ Feature:
19
19
  And I should see the source files:
20
20
  | name | coverage |
21
21
  | lib/faked_project.rb | 100.0 % |
22
- | lib/faked_project/some_class.rb | 80.0 % |
22
+ | lib/faked_project/some_class.rb | 80.0 % |
23
23
  | lib/faked_project/framework_specific.rb | 75.0 % |
24
24
  | lib/faked_project/meta_magic.rb | 100.0 % |
25
25
  | features/step_definitions/my_steps.rb | 100.0 % |
@@ -35,7 +35,7 @@ Then /^I should see the source files:$/ do |table|
35
35
  expected_files.length.should == available_source_files.count
36
36
 
37
37
  # Find all filenames and their coverage present in coverage report
38
- files = available_source_files.map {|f| {"name" => f.find('h3').text, "coverage" => f.find('.header span').text} }
38
+ files = available_source_files.map {|f| {"name" => f.find('h3').text, "coverage" => f.find('h4 > span').text} }
39
39
 
40
40
  files.sort_by {|hsh| hsh["name"] }.should == expected_files.sort_by {|hsh| hsh["name"] }
41
41
  end
@@ -1,26 +1,44 @@
1
- unless RUBY_VERSION =~ /1\.9/
2
- $stderr.puts "Sorry, Cucumber features are only meant to run on Ruby 1.9 for now :("
1
+ unless '1.9'.respond_to?(:encoding)
2
+ $stderr.puts "Sorry, Cucumber features are only meant to run on Ruby 1.9+ :("
3
3
  exit 0
4
4
  end
5
5
 
6
6
  require 'bundler'
7
7
  Bundler.setup
8
8
  require 'aruba/cucumber'
9
+ require 'aruba/jruby' if RUBY_ENGINE == 'jruby'
9
10
  require 'capybara/cucumber'
11
+ require 'phantomjs/poltergeist'
10
12
 
11
13
  # Fake rack app for capybara that just returns the latest coverage report from aruba temp project dir
12
- Capybara.app = lambda {|env|
14
+ Capybara.app = lambda { |env|
15
+ request_path = env['REQUEST_PATH'] || '/'
16
+ request_path = '/index.html' if request_path == '/'
17
+
13
18
  [200, {'Content-Type' => 'text/html'},
14
- [File.read(File.join(File.dirname(__FILE__), '../../tmp/aruba/project', 'coverage/index.html'))]]
19
+ [File.read(File.join(File.dirname(__FILE__), '../../tmp/aruba/project/coverage', request_path))]]
15
20
  }
16
21
 
22
+ Capybara.default_driver = Capybara.javascript_driver = :poltergeist
23
+
17
24
  Before do
18
- @aruba_timeout_seconds = 20
25
+ # JRuby takes it's time... See https://github.com/cucumber/aruba/issues/134
26
+ @aruba_timeout_seconds = RUBY_ENGINE == 'jruby' ? 60 : 20
27
+
19
28
  this_dir = File.dirname(__FILE__)
29
+
20
30
  # Clean up and create blank state for fake project
21
31
  in_current_dir do
22
32
  FileUtils.rm_rf 'project'
23
33
  FileUtils.cp_r File.join(this_dir, '../../test/faked_project/'), 'project'
24
34
  end
35
+
25
36
  step 'I cd to "project"'
26
37
  end
38
+
39
+ # Workaround for https://github.com/cucumber/aruba/pull/125
40
+ Aruba.configure do |config|
41
+ config.before_cmd do
42
+ set_env('JRUBY_OPTS', '-X-C --1.9')
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "aruba", "~> 0.5.1"
6
+ gem "capybara", "~> 2.0"
7
+ gem "poltergeist", "~> 1.1.0"
8
+ gem "phantomjs", "~> 1.8.1"
9
+ gem "cucumber", ">= 1.1.0"
10
+ gem "multi_json", "~> 1.0.0"
11
+
12
+ gemspec :path=>"../"
@@ -0,0 +1,12 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "aruba", "~> 0.5.1"
6
+ gem "capybara", "~> 2.0"
7
+ gem "poltergeist", "~> 1.1.0"
8
+ gem "phantomjs", "~> 1.8.1"
9
+ gem "cucumber", ">= 1.1.0"
10
+ gem "multi_json", ">= 1.3.4"
11
+
12
+ gemspec :path=>"../"
data/lib/simplecov.rb CHANGED
@@ -2,18 +2,15 @@
2
2
  # Code coverage for ruby 1.9. Please check out README for a full introduction.
3
3
  #
4
4
  module SimpleCov
5
- # Indicates invalid coverage data
6
- class CoverageDataError < StandardError; end;
7
-
8
5
  class << self
9
- attr_accessor :running#, :result # TODO: Remove result?
6
+ attr_accessor :running
10
7
 
11
8
  #
12
9
  # Sets up SimpleCov to run against your project.
13
- # You can optionally specify an adapter to use as well as configuration with a block:
10
+ # You can optionally specify a profile to use as well as configuration with a block:
14
11
  # SimpleCov.start
15
12
  # OR
16
- # SimpleCov.start 'rails' # using rails adapter
13
+ # SimpleCov.start 'rails' # using rails profile
17
14
  # OR
18
15
  # SimpleCov.start do
19
16
  # add_filter 'test'
@@ -25,15 +22,17 @@ module SimpleCov
25
22
  #
26
23
  # Please check out the RDoc for SimpleCov::Configuration to find about available config options
27
24
  #
28
- def start(adapter=nil, &block)
29
- return false unless SimpleCov.usable?
30
-
31
- require 'coverage'
32
- load_adapter(adapter) unless adapter.nil?
33
- Coverage.start
34
- configure(&block) if block_given?
35
- @result = nil
36
- self.running = true
25
+ def start(profile=nil, &block)
26
+ if SimpleCov.usable?
27
+ load_profile(profile) if profile
28
+ configure(&block) if block_given?
29
+ @result = nil
30
+ self.running = true
31
+ Coverage.start
32
+ else
33
+ warn "WARNING: SimpleCov is activated, but you're not running Ruby 1.9+ - no coverage analysis will happen"
34
+ false
35
+ end
37
36
  end
38
37
 
39
38
  #
@@ -90,22 +89,31 @@ module SimpleCov
90
89
  end
91
90
 
92
91
  #
93
- # Applies the adapter of given name on SimpleCov configuration
92
+ # Applies the profile of given name on SimpleCov configuration
94
93
  #
94
+ def load_profile(name)
95
+ profiles.load(name)
96
+ end
97
+
95
98
  def load_adapter(name)
96
- adapters.load(name)
99
+ warn "method load_adapter is deprecated. use load_profile instead"
100
+ load_profile(name)
97
101
  end
98
102
 
99
103
  #
100
- # Checks whether we're on a proper version of ruby (1.9+) and returns false if this is not the case,
101
- # also printing an appropriate warning
104
+ # Checks whether we're on a proper version of Ruby (likely 1.9+) which
105
+ # provides coverage support
102
106
  #
103
107
  def usable?
104
- unless "1.9".respond_to?(:encoding)
105
- warn "WARNING: SimpleCov is activated, but you're not running Ruby 1.9+ - no coverage analysis will happen"
106
- return false
108
+ return @usable if defined? @usable and !@usable.nil?
109
+
110
+ @usable = begin
111
+ require 'coverage'
112
+ require 'simplecov/jruby16_fix'
113
+ true
114
+ rescue LoadError
115
+ false
107
116
  end
108
- true
109
117
  end
110
118
  end
111
119
  end
@@ -115,7 +123,7 @@ require 'simplecov/configuration'
115
123
  SimpleCov.send :extend, SimpleCov::Configuration
116
124
  require 'simplecov/exit_codes'
117
125
  require 'simplecov/json'
118
- require 'simplecov/adapters'
126
+ require 'simplecov/profiles'
119
127
  require 'simplecov/source_file'
120
128
  require 'simplecov/file_list'
121
129
  require 'simplecov/result'
@@ -128,7 +136,7 @@ require 'simplecov/command_guesser'
128
136
  require 'simplecov/version'
129
137
 
130
138
  # Load default config
131
- require 'simplecov/defaults'
139
+ require 'simplecov/defaults' unless ENV['SIMPLECOV_NO_DEFAULTS']
132
140
 
133
141
  # Load Rails integration (only for Rails 3, see #113)
134
142
  require 'simplecov/railtie' if defined? Rails::Railtie
@@ -18,16 +18,16 @@ module SimpleCov::CommandGuesser
18
18
 
19
19
  def from_command_line_options
20
20
  case original_run_command
21
- when /#{'test/functional/'}/
21
+ when /test\/functional\//, /test\/{.*?functional.*?}\//
22
22
  "Functional Tests"
23
- when /#{'test/integration/'}/
23
+ when /test\/integration\//
24
24
  "Integration Tests"
25
- when /#{'test/'}/
25
+ when /test\//
26
26
  "Unit Tests"
27
- when /cucumber/, /features/
28
- "Cucumber Features"
29
27
  when /spec/
30
28
  "RSpec"
29
+ when /cucumber/, /features/
30
+ "Cucumber Features"
31
31
  else
32
32
  nil
33
33
  end
@@ -46,4 +46,4 @@ module SimpleCov::CommandGuesser
46
46
  end
47
47
  end
48
48
  end
49
- end
49
+ end
@@ -94,10 +94,15 @@ module SimpleCov::Configuration
94
94
  end
95
95
 
96
96
  #
97
- # Returns the hash of available adapters
97
+ # Returns the hash of available profiles
98
98
  #
99
+ def profiles
100
+ @profiles ||= SimpleCov::Profiles.new
101
+ end
102
+
99
103
  def adapters
100
- @adapters ||= SimpleCov::Adapters.new
104
+ warn "method adapters is deprecated. use profiles instead"
105
+ profiles
101
106
  end
102
107
 
103
108
  #
@@ -1,22 +1,22 @@
1
1
  # Load default formatter gem
2
2
  require 'simplecov-html'
3
3
 
4
- SimpleCov.adapters.define 'root_filter' do
4
+ SimpleCov.profiles.define 'root_filter' do
5
5
  # Exclude all files outside of simplecov root
6
6
  add_filter do |src|
7
7
  !(src.filename =~ /^#{SimpleCov.root}/)
8
8
  end
9
9
  end
10
10
 
11
- SimpleCov.adapters.define 'test_frameworks' do
11
+ SimpleCov.profiles.define 'test_frameworks' do
12
12
  add_filter '/test/'
13
13
  add_filter '/features/'
14
14
  add_filter '/spec/'
15
15
  add_filter '/autotest/'
16
16
  end
17
17
 
18
- SimpleCov.adapters.define 'rails' do
19
- load_adapter 'test_frameworks'
18
+ SimpleCov.profiles.define 'rails' do
19
+ load_profile 'test_frameworks'
20
20
 
21
21
  add_filter '/config/'
22
22
  add_filter '/db/'
@@ -34,7 +34,7 @@ end
34
34
  SimpleCov.configure do
35
35
  formatter SimpleCov::Formatter::HTMLFormatter
36
36
  # Exclude files outside of SimpleCov.root
37
- load_adapter 'root_filter'
37
+ load_profile 'root_filter'
38
38
  end
39
39
 
40
40
  # Gotta stash this a-s-a-p, see the CommandGuesser class and i.e. #110 for further info
@@ -81,6 +81,10 @@ at_exit do
81
81
  exit @exit_status if @exit_status # Force exit with stored status (see github issue #5)
82
82
  end
83
83
 
84
+ # Autoload config from ~/.simplecov if present
85
+ global_config_path = File.join(File.expand_path("~"), '.simplecov')
86
+ load global_config_path if File.exist?(global_config_path)
87
+
84
88
  # Autoload config from .simplecov if present
85
89
  config_path = File.join(SimpleCov.root, '.simplecov')
86
90
  load config_path if File.exist?(config_path)
@@ -39,6 +39,6 @@ class SimpleCov::FileList < Array
39
39
  # Computes the strength (hits / line) based upon lines covered and lines missed
40
40
  def covered_strength
41
41
  return 0 if empty? or lines_of_code == 0
42
- map {|f| f.covered_strength }.inject(&:+) / size
42
+ map {|f| f.covered_strength }.inject(&:+).to_f / size
43
43
  end
44
44
  end
@@ -0,0 +1,43 @@
1
+ if defined?(JRUBY_VERSION) && JRUBY_VERSION.to_f < 1.7
2
+ require 'jruby'
3
+ java_import 'org.jruby.ast.NodeType'
4
+
5
+ # Coverage for JRuby < 1.7.0 does not work correctly
6
+ #
7
+ # - does not distinguish lines that cannot be executed
8
+ # - does (partial) coverage for files loaded before `Coverage.start`.
9
+ # - does not expand a path like `lib/../spec` to `spec`.
10
+ #
11
+ # This monkey patches Coverage to address those issues
12
+ module Coverage
13
+ class << self
14
+ alias __broken_result__ result
15
+
16
+ def result
17
+ fixed = {}
18
+ __broken_result__.each do |path, executed_lines|
19
+ covered_lines = executed_lines.dup
20
+
21
+ process = lambda do |node|
22
+ if node.node_type == NodeType::NEWLINENODE
23
+ pos = node.position
24
+ covered_lines[pos.line] ||= 0
25
+ end
26
+ node.child_nodes.each(&process)
27
+ end
28
+
29
+ begin
30
+ process[JRuby.parse(File.read(path), path)]
31
+ rescue => e
32
+ end
33
+
34
+ if (first = covered_lines.detect { |x| x }) && first > 0
35
+ fixed[File.expand_path(path)] = covered_lines
36
+ end
37
+ end
38
+
39
+ fixed
40
+ end
41
+ end
42
+ end
43
+ end