rspec-core 2.0.0.beta.20 → 2.0.0.beta.22

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 (48) hide show
  1. data/.rspec +1 -1
  2. data/Gemfile +7 -6
  3. data/History.md +30 -0
  4. data/Rakefile +3 -43
  5. data/bin/rspec +2 -1
  6. data/features/configuration/{options_file.feature → read_options_from_file.feature} +29 -25
  7. data/features/example_groups/shared_example_group.feature +10 -6
  8. data/features/hooks/before_and_after_hooks.feature +38 -0
  9. data/lib/autotest/rspec2.rb +10 -2
  10. data/lib/rspec/core.rb +8 -0
  11. data/lib/rspec/core/configuration.rb +16 -10
  12. data/lib/rspec/core/configuration_options.rb +7 -3
  13. data/lib/rspec/core/example.rb +7 -0
  14. data/lib/rspec/core/example_group.rb +15 -2
  15. data/lib/rspec/core/extensions/module_eval_with_args.rb +9 -29
  16. data/lib/rspec/core/extensions/object.rb +0 -2
  17. data/lib/rspec/core/formatters/base_formatter.rb +8 -6
  18. data/lib/rspec/core/formatters/base_text_formatter.rb +18 -10
  19. data/lib/rspec/core/formatters/documentation_formatter.rb +9 -9
  20. data/lib/rspec/core/option_parser.rb +0 -4
  21. data/lib/rspec/core/rake_task.rb +85 -39
  22. data/lib/rspec/core/reporter.rb +18 -5
  23. data/lib/rspec/core/runner.rb +8 -18
  24. data/lib/rspec/core/shared_example_group.rb +2 -1
  25. data/lib/rspec/core/version.rb +1 -1
  26. data/rspec-core.gemspec +33 -233
  27. data/spec/autotest/failed_results_re_spec.rb +1 -2
  28. data/spec/autotest/rspec_spec.rb +62 -42
  29. data/spec/rspec/core/configuration_options_spec.rb +12 -29
  30. data/spec/rspec/core/configuration_spec.rb +8 -8
  31. data/spec/rspec/core/example_group_spec.rb +38 -7
  32. data/spec/rspec/core/example_spec.rb +16 -1
  33. data/spec/rspec/core/formatters/base_formatter_spec.rb +6 -0
  34. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +125 -10
  35. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +36 -0
  36. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +282 -0
  37. data/spec/rspec/core/formatters/html_formatted-1.9.1.html +22 -2
  38. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +280 -0
  39. data/spec/rspec/core/formatters/text_mate_formatted-1.9.1.html +280 -0
  40. data/spec/rspec/core/rake_task_spec.rb +128 -0
  41. data/spec/rspec/core/reporter_spec.rb +36 -0
  42. data/spec/rspec/core/runner_spec.rb +0 -18
  43. data/spec/rspec/core/shared_example_group_spec.rb +22 -2
  44. data/spec/rspec/core/world_spec.rb +13 -15
  45. data/spec/spec_helper.rb +2 -1
  46. metadata +110 -13
  47. data/VERSION +0 -1
  48. data/lib/rspec/autorun.rb +0 -2
@@ -11,42 +11,22 @@ module RSpec
11
11
  # If there are no args and the block doesn't expect any, there's no
12
12
  # need to fake module_exec with our hack below.
13
13
  # Notes:
14
- # * lambda { }.arity # => -1
15
- # * lambda { || }.arity # => 0
16
- # * lambda { |*a| }.arity # -1
14
+ # * lambda { }.arity # => -1
15
+ # * lambda { || }.arity # => 0
16
+ # * lambda { |*a| }.arity # => -1
17
17
  return module_eval(&block) if block.arity < 1 && args.size.zero?
18
18
 
19
+ orig_singleton_methods = singleton_methods
19
20
  instance_eval_with_args(*args, &block)
20
21
 
21
22
  # The only difference between instance_eval and module_eval is static method defs.
22
23
  # * `def foo` in instance_eval defines a singleton method on the instance
23
24
  # * `def foo` in class/module_eval defines an instance method for the class/module
24
- # Here we deal with this difference by defining instance methods on the
25
- # class/module and removing the singleton definitions.
26
- singleton_class = class << self; self; end
27
- extract_static_instance_method_defs_from(block).each do |m_name, m_def|
28
- define_method(m_name, &m_def)
29
- singleton_class.send(:remove_method, m_name)
30
- end
31
- end
32
-
33
- private
34
-
35
- def extract_static_instance_method_defs_from(block)
36
- klass = Class.new do
37
- # swallow any missing class method errors;
38
- # we only care to capture the raw method definitions here.
39
- def self.method_missing(*a); end
40
-
41
- # skip any dynamic method definitions
42
- def self.define_method(*a); end
43
-
44
- # run the block so our instance methods get defined
45
- class_eval(&block)
46
- end
47
-
48
- instance = klass.new
49
- klass.instance_methods(false).inject({}) { |h, m| h[m] = instance.method(m); h }
25
+ # Here we deal with this difference by defining an instance method for
26
+ # each new singleton method.
27
+ # This has the side effect of duplicating methods (all new class methods will
28
+ # become instance methods and vice versa), but I don't see a way around it...
29
+ (singleton_methods - orig_singleton_methods).each { |m| define_method(m, &method(m)) }
50
30
  end
51
31
  end
52
32
  end
@@ -6,8 +6,6 @@ module RSpec
6
6
  args.last.update :caller => caller(1)
7
7
  RSpec::Core::ExampleGroup.describe(*args, &example_group_block)
8
8
  end
9
-
10
- alias :context :describe
11
9
  end
12
10
  end
13
11
  end
@@ -38,6 +38,11 @@ module RSpec
38
38
  @example_group = example_group
39
39
  end
40
40
 
41
+ # This method is invoked at the end of the execution of each example group.
42
+ # +example_group+ is the example_group.
43
+ def example_group_finished(example_group)
44
+ end
45
+
41
46
  def add_example_group(example_group)
42
47
  RSpec.deprecate("add_example_group", "example_group_started")
43
48
  example_group_started(example_group)
@@ -93,10 +98,7 @@ module RSpec
93
98
  def format_backtrace(backtrace, example)
94
99
  return "" unless backtrace
95
100
  return backtrace if example.metadata[:full_backtrace] == true
96
-
97
- cleansed = backtrace.select { |line| backtrace_line(line) }
98
- # Kick the describe stack info off the list, just keep the line the problem happened on from that file
99
- # cleansed = [cleansed.detect { |line| line.split(':').first == example.metadata[:caller].split(':').first }] if cleansed.size > 1
101
+ cleansed = backtrace.map { |line| backtrace_line(line) }.compact
100
102
  cleansed.empty? ? backtrace : cleansed
101
103
  end
102
104
 
@@ -108,8 +110,8 @@ module RSpec
108
110
 
109
111
  def backtrace_line(line)
110
112
  return nil if configuration.cleaned_from_backtrace?(line)
111
- line.sub!(File.expand_path("."), ".")
112
- line.sub!(/\A([^:]+:\d+)$/, '\\1')
113
+ line = line.sub(File.expand_path("."), ".")
114
+ line = line.sub(/\A([^:]+:\d+)$/, '\\1')
113
115
  return nil if line == '-e:1'
114
116
  line
115
117
  end
@@ -22,10 +22,18 @@ module RSpec
22
22
  output.puts "#{padding}Expected pending '#{example.metadata[:execution_result][:pending_message]}' to fail. No Error was raised."
23
23
  else
24
24
  output.puts "#{short_padding}#{index.next}) #{example.full_description}"
25
- output.puts "#{padding}Failure/Error: #{read_failed_line(exception, example).strip}"
25
+ output.puts "#{padding}#{red("Failure/Error:")} #{red(read_failed_line(exception, example).strip)}"
26
26
  exception.message.split("\n").each do |line|
27
27
  output.puts "#{padding}#{red(line)}"
28
28
  end
29
+
30
+ example.example_group.ancestors.push(example.example_group).each do |group|
31
+ if group.metadata[:shared_group_name]
32
+ output.puts "#{padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
33
+ "#{backtrace_line(group.metadata[:example_group][:location])}"
34
+ break
35
+ end
36
+ end
29
37
  end
30
38
 
31
39
  format_backtrace(exception.backtrace, example).each do |backtrace_info|
@@ -48,18 +56,18 @@ module RSpec
48
56
 
49
57
  def dump_summary(duration, example_count, failure_count, pending_count)
50
58
  super(duration, example_count, failure_count, pending_count)
59
+ # Don't print out profiled info if there are failures, it just clutters the output
60
+ dump_profile if profile_examples? && failure_count == 0
51
61
  output.puts "\nFinished in #{format_seconds(duration)} seconds\n"
52
-
53
62
  output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
63
+ end
54
64
 
55
- # Don't print out profiled info if there are failures, it just clutters the output
56
- if profile_examples? && failure_count == 0
57
- sorted_examples = examples.sort_by { |example| example.execution_result[:run_time] }.reverse.first(10)
58
- output.puts "\nTop #{sorted_examples.size} slowest examples:\n"
59
- sorted_examples.each do |example|
60
- output.puts " (#{format_seconds(example.execution_result[:run_time])} seconds) #{example}"
61
- output.puts grey(" # #{format_caller(example.metadata[:location])}")
62
- end
65
+ def dump_profile
66
+ sorted_examples = examples.sort_by { |example| example.execution_result[:run_time] }.reverse.first(10)
67
+ output.puts "\nTop #{sorted_examples.size} slowest examples:\n"
68
+ sorted_examples.each do |example|
69
+ output.puts " #{example.full_description}"
70
+ output.puts grey(" #{red(format_seconds(example.execution_result[:run_time]))} #{red("seconds")} #{format_caller(example.metadata[:location])}")
63
71
  end
64
72
  end
65
73
 
@@ -6,20 +6,20 @@ module RSpec
6
6
 
7
7
  def initialize(output)
8
8
  super(output)
9
- @previous_nested_example_groups = []
9
+ @group_level = 0
10
10
  end
11
11
 
12
12
  def example_group_started(example_group)
13
13
  super(example_group)
14
14
 
15
- example_group_chain.each_with_index do |nested_example_group, i|
16
- unless nested_example_group == @previous_nested_example_groups[i]
17
- output.puts if i == 0
18
- output.puts "#{' ' * i}#{nested_example_group.description}"
19
- end
20
- end
15
+ output.puts if @group_level == 0
16
+ output.puts "#{' ' * @group_level}#{example_group.description}"
21
17
 
22
- @previous_nested_example_groups = example_group_chain
18
+ @group_level += 1
19
+ end
20
+
21
+ def example_group_finished(example_group)
22
+ @group_level -= 1
23
23
  end
24
24
 
25
25
  def example_passed(example)
@@ -55,7 +55,7 @@ module RSpec
55
55
  end
56
56
 
57
57
  def current_indentation
58
- ' ' * @previous_nested_example_groups.size
58
+ ' ' * @group_level
59
59
  end
60
60
 
61
61
  def example_group_chain
@@ -64,10 +64,6 @@ module RSpec::Core
64
64
  options[:line_number] = o
65
65
  end
66
66
 
67
- parser.on('-o', '--options PATH', 'Read configuration options from a file path. (Defaults to .rspec)') do |o|
68
- options[:options_file] = o || local_options_file
69
- end
70
-
71
67
  parser.on('-p', '--profile', 'Enable profiling of examples with output of the top 10 slowest examples') do |o|
72
68
  options[:profile_examples] = o
73
69
  end
@@ -8,57 +8,94 @@ module RSpec
8
8
 
9
9
  class RakeTask < ::Rake::TaskLib
10
10
 
11
- # Name of task. (default is :spec)
11
+ # Name of task.
12
+ #
13
+ # default:
14
+ # :spec
12
15
  attr_accessor :name
13
16
 
14
- # If true, requests that the specs be run with the warning flag set.
15
- # E.g. warning=true implies "ruby -w" used to run the specs. Defaults to false.
16
- attr_accessor :warning
17
-
18
- # Glob pattern to match files. (default is 'spec/**/*_spec.rb')
17
+ # Glob pattern to match files.
18
+ #
19
+ # default:
20
+ # 'spec/**/*_spec.rb'
19
21
  attr_accessor :pattern
20
22
 
21
- # Array of commandline options to pass to RSpec. Defaults to [].
22
- attr_accessor :spec_opts
23
-
24
- # The options to pass to ruby. Defaults to blank
25
- attr_accessor :ruby_opts
23
+ # Deprecated. Use ruby_opts="-w" instead.
24
+ # When true, requests that the specs be run with the warning flag set.
25
+ # e.g. "ruby -w"
26
+ #
27
+ # default:
28
+ # false
29
+ attr_reader :warning
30
+
31
+ def warning=(true_or_false)
32
+ RSpec.deprecate("warning", 'ruby_opts="-w"')
33
+ @warning = true_or_false
34
+ end
26
35
 
27
36
  # Whether or not to fail Rake when an error occurs (typically when examples fail).
28
- # Defaults to true.
37
+ #
38
+ # default:
39
+ # true
29
40
  attr_accessor :fail_on_error
30
41
 
31
42
  # A message to print to stderr when there are failures.
32
43
  attr_accessor :failure_message
33
44
 
34
- # Use verbose output. If this is set to true, the task will print
35
- # the executed spec command to stdout. Defaults to false.
45
+ # Use verbose output. If this is set to true, the task will print the
46
+ # executed spec command to stdout.
47
+ #
48
+ # default:
49
+ # false
36
50
  attr_accessor :verbose
37
51
 
38
- # Use rcov for code coverage? defaults to false
52
+ # Use rcov for code coverage?
53
+ #
54
+ # default:
55
+ # false
39
56
  attr_accessor :rcov
40
57
 
41
- # Path to rcov. You can set this to 'bundle exec rcov' if you bundle rcov.
58
+ # Path to rcov.
59
+ #
60
+ # defaults:
61
+ # 'rcov'
42
62
  attr_accessor :rcov_path
43
63
 
44
- # The options to pass to rcov. Defaults to blank
64
+ # Command line options to pass to rcov.
65
+ #
66
+ # default:
67
+ # nil
45
68
  attr_accessor :rcov_opts
46
69
 
70
+ # Command line options to pass to ruby.
71
+ #
72
+ # default:
73
+ # nil
74
+ attr_accessor :ruby_opts
75
+
76
+ # Command line options to pass to rspec.
77
+ #
78
+ # default:
79
+ # nil
80
+ attr_accessor :rspec_opts
81
+
82
+ # Deprecated. Use rspec_opts instead.
83
+ def spec_opts=(opts)
84
+ RSpec.deprecate("spec_opts","rspec_opts")
85
+ @rspec_opts = opts
86
+ end
87
+
47
88
  def initialize(*args)
48
89
  @name = args.shift || :spec
49
- @pattern, @rcov_path, @rcov_opts, @ruby_opts = nil, nil, nil, nil
90
+ @pattern, @rcov_path, @rcov_opts, @ruby_opts, @rspec_opts = nil, nil, nil, nil, nil
50
91
  @warning, @rcov = false, false
51
92
  @fail_on_error = true
52
- @spec_opts = []
53
93
 
54
94
  yield self if block_given?
95
+
55
96
  @rcov_path ||= 'rcov'
56
97
  @pattern ||= './spec/**/*_spec.rb'
57
- define
58
- end
59
98
 
60
- def define # :nodoc:
61
- actual_name = Hash === name ? name.keys.first : name
62
99
  desc("Run RSpec code examples") unless ::Rake.application.last_comment
63
100
 
64
101
  task name do
@@ -67,47 +104,56 @@ module RSpec
67
104
  puts "No examples matching #{pattern} could be found"
68
105
  else
69
106
  puts spec_command.inspect if verbose
70
- unless ruby("-S #{spec_command}")
107
+ unless ruby(spec_command)
71
108
  STDERR.puts failure_message if failure_message
72
109
  raise("#{spec_command} failed") if fail_on_error
73
110
  end
74
111
  end
75
112
  end
76
113
  end
77
-
78
- self
79
114
  end
80
115
 
81
116
  def files_to_run # :nodoc:
82
- FileList[ pattern ].to_a
117
+ FileList[ pattern ].map { |f| %["#{f}"] }
83
118
  end
84
119
 
85
120
  private
86
121
 
87
122
  def spec_command
88
123
  @spec_command ||= begin
89
- cmd_parts = %w[-Ilib -Ispec]
90
- cmd_parts << "-w" if warning
91
- cmd_parts.unshift runner_options
92
- cmd_parts.unshift runner
93
- cmd_parts.unshift bundler
94
- cmd_parts += files_to_run.map { |fn| %["#{fn}"] }
95
- cmd_parts << spec_opts.join(" ")
96
- cmd_parts.join(" ")
124
+ cmd_parts = [ruby_opts]
125
+ cmd_parts << "-w" if warning?
126
+ cmd_parts << "-S"
127
+ cmd_parts << "bundle exec" if bundler?
128
+ cmd_parts << runner
129
+ cmd_parts << runner_options
130
+ cmd_parts << files_to_run
131
+ cmd_parts.flatten.compact.reject(&blank).join(" ")
97
132
  end
98
133
  end
99
134
 
135
+ private
136
+
100
137
  def runner
101
- rcov ? rcov_path : RUBY
138
+ rcov ? rcov_path : 'rspec'
102
139
  end
103
140
 
104
141
  def runner_options
105
- rcov ? [rcov_opts] : [ruby_opts]
142
+ rcov ? [rcov_opts] : [rspec_opts]
106
143
  end
107
144
 
108
- def bundler
109
- File.exist?("./Gemfile") ? "bundle exec " : ""
145
+ def bundler?
146
+ File.exist?("./Gemfile")
110
147
  end
148
+
149
+ def warning?
150
+ warning
151
+ end
152
+
153
+ def blank
154
+ lambda {|s| s == ""}
155
+ end
156
+
111
157
  end
112
158
 
113
159
  end
@@ -2,13 +2,20 @@ module RSpec::Core
2
2
  class Reporter
3
3
  def initialize(*formatters)
4
4
  @formatters = formatters
5
- @failure_count = @pending_count = 0
5
+ @example_count = @failure_count = @pending_count = 0
6
6
  end
7
7
 
8
8
  def report(count)
9
9
  start(count)
10
10
  begin
11
11
  yield self
12
+ ensure
13
+ conclude
14
+ end
15
+ end
16
+
17
+ def conclude
18
+ begin
12
19
  stop
13
20
  notify :start_dump
14
21
  notify :dump_pending
@@ -19,10 +26,11 @@ module RSpec::Core
19
26
  end
20
27
  end
21
28
 
22
- def start(example_count)
23
- @example_count = example_count
29
+ alias_method :abort, :conclude
30
+
31
+ def start(expected_example_count)
24
32
  @start = Time.now
25
- notify :start, example_count
33
+ notify :start, expected_example_count
26
34
  end
27
35
 
28
36
  def message(message)
@@ -33,7 +41,12 @@ module RSpec::Core
33
41
  notify :example_group_started, group
34
42
  end
35
43
 
44
+ def example_group_finished(group)
45
+ notify :example_group_finished, group
46
+ end
47
+
36
48
  def example_started(example)
49
+ @example_count += 1
37
50
  notify :example_started, example
38
51
  end
39
52
 
@@ -52,7 +65,7 @@ module RSpec::Core
52
65
  end
53
66
 
54
67
  def stop
55
- @duration = Time.now - @start
68
+ @duration = Time.now - @start if @start
56
69
  notify :stop
57
70
  end
58
71
 
@@ -4,30 +4,20 @@ module RSpec
4
4
  module Core
5
5
  class Runner
6
6
 
7
- def self.autorun
8
- return if autorun_disabled? || installed_at_exit? || running_in_drb?
9
- @installed_at_exit = true
10
- at_exit { run(ARGV, $stderr, $stdout) ? exit(0) : exit(1) }
11
- end
12
-
13
- def self.autorun_disabled?
14
- @autorun_disabled ||= false
15
- end
16
-
17
7
  def self.disable_autorun!
18
- @autorun_disabled = true
8
+ RSpec.deprecate("disable_autorun!")
19
9
  end
20
10
 
21
- def self.installed_at_exit?
22
- @installed_at_exit ||= false
23
- end
24
-
25
- def self.running_in_drb?
26
- (DRb.current_server rescue false) &&
27
- !!((DRb.current_server.uri) =~ /druby\:\/\/127.0.0.1\:/)
11
+ def self.trap_interrupt
12
+ trap('INT') do
13
+ exit!(1) if RSpec.wants_to_quit
14
+ RSpec.wants_to_quit = true
15
+ STDERR.puts "\nExiting... Interrupt again to exit immediately."
16
+ end
28
17
  end
29
18
 
30
19
  def self.run(args, err, out)
20
+ trap_interrupt
31
21
  options = ConfigurationOptions.new(args)
32
22
  options.parse_options
33
23