rspec-core 2.11.1 → 2.12.0

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 (116) hide show
  1. data/Changelog.md +59 -0
  2. data/README.md +22 -0
  3. data/features/command_line/example_name_option.feature +5 -5
  4. data/features/command_line/exit_status.feature +6 -6
  5. data/features/command_line/format_option.feature +2 -2
  6. data/features/command_line/line_number_appended_to_path.feature +2 -2
  7. data/features/command_line/line_number_option.feature +2 -2
  8. data/features/command_line/pattern_option.feature +2 -2
  9. data/features/command_line/rake_task.feature +62 -8
  10. data/features/command_line/ruby.feature +1 -1
  11. data/features/command_line/tag.feature +1 -1
  12. data/features/configuration/alias_example_to.feature +2 -2
  13. data/features/configuration/custom_settings.feature +3 -3
  14. data/features/configuration/default_path.feature +3 -3
  15. data/features/configuration/fail_fast.feature +5 -5
  16. data/features/configuration/read_options_from_file.feature +4 -4
  17. data/features/example_groups/basic_structure.feature +2 -2
  18. data/features/example_groups/shared_context.feature +3 -3
  19. data/features/example_groups/shared_examples.feature +25 -7
  20. data/features/expectation_framework_integration/configure_expectation_framework.feature +6 -6
  21. data/features/filtering/exclusion_filters.feature +5 -5
  22. data/features/filtering/if_and_unless.feature +5 -5
  23. data/features/filtering/inclusion_filters.feature +5 -5
  24. data/features/filtering/run_all_when_everything_filtered.feature +3 -3
  25. data/features/formatters/custom_formatter.feature +2 -2
  26. data/features/formatters/json_formatter.feature +30 -0
  27. data/features/formatters/text_formatter.feature +5 -5
  28. data/features/helper_methods/arbitrary_methods.feature +2 -2
  29. data/features/helper_methods/let.feature +2 -2
  30. data/features/helper_methods/modules.feature +6 -6
  31. data/features/hooks/around_hooks.feature +11 -11
  32. data/features/hooks/before_and_after_hooks.feature +15 -11
  33. data/features/hooks/filtering.feature +6 -6
  34. data/features/metadata/current_example.feature +1 -1
  35. data/features/metadata/described_class.feature +1 -1
  36. data/features/metadata/user_defined.feature +4 -4
  37. data/features/mock_framework_integration/use_any_framework.feature +6 -6
  38. data/features/mock_framework_integration/use_flexmock.feature +5 -5
  39. data/features/mock_framework_integration/use_mocha.feature +5 -5
  40. data/features/mock_framework_integration/use_rr.feature +5 -5
  41. data/features/mock_framework_integration/use_rspec.feature +5 -5
  42. data/features/pending/pending_examples.feature +11 -11
  43. data/features/spec_files/arbitrary_file_suffix.feature +1 -1
  44. data/features/step_definitions/additional_cli_steps.rb +2 -0
  45. data/features/subject/attribute_of_subject.feature +5 -5
  46. data/features/subject/explicit_subject.feature +5 -5
  47. data/features/subject/implicit_receiver.feature +2 -2
  48. data/features/subject/implicit_subject.feature +3 -3
  49. data/lib/autotest/rspec2.rb +1 -1
  50. data/lib/rspec/core.rb +53 -32
  51. data/lib/rspec/core/configuration.rb +123 -15
  52. data/lib/rspec/core/configuration_options.rb +17 -2
  53. data/lib/rspec/core/example.rb +5 -4
  54. data/lib/rspec/core/example_group.rb +19 -9
  55. data/lib/rspec/core/extensions/ordered.rb +12 -6
  56. data/lib/rspec/core/formatters.rb +55 -0
  57. data/lib/rspec/core/formatters/base_formatter.rb +43 -38
  58. data/lib/rspec/core/formatters/base_text_formatter.rb +9 -5
  59. data/lib/rspec/core/formatters/documentation_formatter.rb +1 -1
  60. data/lib/rspec/core/formatters/helpers.rb +30 -5
  61. data/lib/rspec/core/formatters/html_formatter.rb +58 -368
  62. data/lib/rspec/core/formatters/html_printer.rb +407 -0
  63. data/lib/rspec/core/formatters/json_formatter.rb +73 -0
  64. data/lib/rspec/core/formatters/snippet_extractor.rb +3 -1
  65. data/lib/rspec/core/hooks.rb +4 -4
  66. data/lib/rspec/core/metadata.rb +14 -6
  67. data/lib/rspec/core/mocking/with_mocha.rb +25 -2
  68. data/lib/rspec/core/mocking/with_rspec.rb +6 -2
  69. data/lib/rspec/core/option_parser.rb +28 -7
  70. data/lib/rspec/core/project_initializer.rb +0 -1
  71. data/lib/rspec/core/rake_task.rb +49 -38
  72. data/lib/rspec/core/reporter.rb +2 -2
  73. data/lib/rspec/core/shared_example_group.rb +89 -41
  74. data/lib/rspec/core/subject.rb +6 -2
  75. data/lib/rspec/core/version.rb +1 -1
  76. data/lib/rspec/core/world.rb +2 -2
  77. data/spec/autotest/rspec_spec.rb +6 -1
  78. data/spec/command_line/order_spec.rb +67 -0
  79. data/spec/rspec/core/configuration_options_spec.rb +45 -38
  80. data/spec/rspec/core/configuration_spec.rb +219 -44
  81. data/spec/rspec/core/deprecations_spec.rb +9 -0
  82. data/spec/rspec/core/drb_command_line_spec.rb +1 -7
  83. data/spec/rspec/core/drb_options_spec.rb +1 -1
  84. data/spec/rspec/core/dsl_spec.rb +17 -9
  85. data/spec/rspec/core/example_group_spec.rb +51 -5
  86. data/spec/rspec/core/example_spec.rb +39 -7
  87. data/spec/rspec/core/filter_manager_spec.rb +20 -30
  88. data/spec/rspec/core/formatters/base_formatter_spec.rb +29 -1
  89. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +6 -2
  90. data/spec/rspec/core/formatters/helpers_spec.rb +12 -0
  91. data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +462 -0
  92. data/spec/rspec/core/formatters/html_formatted-1.9.2-jruby.html +410 -0
  93. data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +462 -0
  94. data/spec/rspec/core/formatters/html_formatter_spec.rb +11 -3
  95. data/spec/rspec/core/formatters/json_formatter_spec.rb +110 -0
  96. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +8 -0
  97. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-rbx.html +462 -0
  98. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2-jruby.html +410 -0
  99. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-rbx.html +462 -0
  100. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +11 -3
  101. data/spec/rspec/core/hooks_filtering_spec.rb +6 -6
  102. data/spec/rspec/core/metadata_spec.rb +29 -0
  103. data/spec/rspec/core/option_parser_spec.rb +42 -0
  104. data/spec/rspec/core/project_initializer_spec.rb +2 -2
  105. data/spec/rspec/core/rake_task_spec.rb +60 -17
  106. data/spec/rspec/core/reporter_spec.rb +17 -0
  107. data/spec/rspec/core/runner_spec.rb +1 -0
  108. data/spec/rspec/core/shared_example_group_spec.rb +17 -5
  109. data/spec/rspec/core/subject_spec.rb +11 -0
  110. data/spec/spec_helper.rb +32 -2
  111. data/spec/support/config_options_helper.rb +1 -10
  112. data/spec/support/helper_methods.rb +13 -0
  113. data/spec/support/isolated_directory.rb +10 -0
  114. data/spec/support/isolated_home_directory.rb +16 -0
  115. metadata +145 -148
  116. data/lib/rspec/core/extensions.rb +0 -4
@@ -405,17 +405,21 @@ MESSAGE
405
405
  @backtrace_clean_patterns = true_or_false ? [] : DEFAULT_BACKTRACE_PATTERNS
406
406
  end
407
407
 
408
- def color
409
- return false unless output_to_tty?
408
+ def color(output=output_stream)
409
+ # rspec's built-in formatters all call this with the output argument,
410
+ # but defaulting to output_stream for backward compatibility with
411
+ # formatters in extension libs
412
+ return false unless output_to_tty?(output)
410
413
  value_for(:color, @color)
411
414
  end
412
415
 
413
416
  def color=(bool)
414
417
  if bool
415
- @color = true
416
418
  if RSpec.windows_os? and not ENV['ANSICON']
417
- warn "You must use ANSICON 1.31 or later (http://adoxa.110mb.com/ansicon/) to use colour on Windows"
419
+ warn "You must use ANSICON 1.31 or later (http://adoxa.3eeweb.com/ansicon/) to use colour on Windows"
418
420
  @color = false
421
+ else
422
+ @color = true
419
423
  end
420
424
  end
421
425
  end
@@ -500,7 +504,7 @@ EOM
500
504
  # @private
501
505
  def files_or_directories_to_run=(*files)
502
506
  files = files.flatten
503
- files << default_path if command == 'rspec' && default_path && files.empty?
507
+ files << default_path if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty?
504
508
  self.files_to_run = get_files_to_run(files)
505
509
  end
506
510
 
@@ -777,10 +781,29 @@ EOM
777
781
 
778
782
  # @private
779
783
  def load_spec_files
780
- files_to_run.uniq.map {|f| load File.expand_path(f) }
784
+ files_to_run.uniq.each {|f| load File.expand_path(f) }
781
785
  raise_if_rspec_1_is_loaded
782
786
  end
783
787
 
788
+ # @private
789
+ DEFAULT_FORMATTER = lambda { |string| string }
790
+
791
+ # Formats the docstring output using the block provided.
792
+ #
793
+ # @example
794
+ # # This will strip the descriptions of both examples and example groups.
795
+ # RSpec.configure do |config|
796
+ # config.format_docstrings { |s| s.strip }
797
+ # end
798
+ def format_docstrings(&block)
799
+ @format_docstrings_block = block_given? ? block : DEFAULT_FORMATTER
800
+ end
801
+
802
+ # @private
803
+ def format_docstrings_block
804
+ @format_docstrings_block ||= DEFAULT_FORMATTER
805
+ end
806
+
784
807
  # @api
785
808
  #
786
809
  # Sets the seed value and sets `order='rand'`
@@ -799,6 +822,79 @@ EOM
799
822
  order.to_s.match(/rand/)
800
823
  end
801
824
 
825
+ # @private
826
+ DEFAULT_ORDERING = lambda { |list| list }
827
+
828
+ # @private
829
+ RANDOM_ORDERING = lambda do |list|
830
+ Kernel.srand RSpec.configuration.seed
831
+ list.sort_by { Kernel.rand(list.size) }
832
+ end
833
+
834
+ # Sets a strategy by which to order examples.
835
+ #
836
+ # @example
837
+ # RSpec.configure do |config|
838
+ # config.order_examples do |examples|
839
+ # examples.reverse
840
+ # end
841
+ # end
842
+ #
843
+ # @see #order_groups
844
+ # @see #order_groups_and_examples
845
+ # @see #order=
846
+ # @see #seed=
847
+ def order_examples(&block)
848
+ @example_ordering_block = block
849
+ @order = "custom" unless built_in_orderer?(block)
850
+ end
851
+
852
+ # @private
853
+ def example_ordering_block
854
+ @example_ordering_block ||= DEFAULT_ORDERING
855
+ end
856
+
857
+ # Sets a strategy by which to order groups.
858
+ #
859
+ # @example
860
+ # RSpec.configure do |config|
861
+ # config.order_groups do |groups|
862
+ # groups.reverse
863
+ # end
864
+ # end
865
+ #
866
+ # @see #order_examples
867
+ # @see #order_groups_and_examples
868
+ # @see #order=
869
+ # @see #seed=
870
+ def order_groups(&block)
871
+ @group_ordering_block = block
872
+ @order = "custom" unless built_in_orderer?(block)
873
+ end
874
+
875
+ # @private
876
+ def group_ordering_block
877
+ @group_ordering_block ||= DEFAULT_ORDERING
878
+ end
879
+
880
+ # Sets a strategy by which to order groups and examples.
881
+ #
882
+ # @example
883
+ # RSpec.configure do |config|
884
+ # config.order_groups_and_examples do |groups_or_examples|
885
+ # groups_or_examples.reverse
886
+ # end
887
+ # end
888
+ #
889
+ # @see #order_groups
890
+ # @see #order_examples
891
+ # @see #order=
892
+ # @see #seed=
893
+ def order_groups_and_examples(&block)
894
+ order_groups(&block)
895
+ order_examples(&block)
896
+ end
897
+
802
898
  private
803
899
 
804
900
  def get_files_to_run(paths)
@@ -806,12 +902,12 @@ EOM
806
902
  paths.map do |path|
807
903
  path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
808
904
  File.directory?(path) ? gather_directories(path, patterns) : extract_location(path)
809
- end.flatten
905
+ end.flatten.sort
810
906
  end
811
907
 
812
908
  def gather_directories(path, patterns)
813
909
  patterns.map do |pattern|
814
- pattern =~ /^#{path}/ ? Dir[pattern.strip] : Dir["#{path}/{#{pattern.strip}}"]
910
+ pattern =~ /^#{path}/ ? Dir[pattern.strip].sort : Dir["#{path}/{#{pattern.strip}}"].sort
815
911
  end
816
912
  end
817
913
 
@@ -856,12 +952,8 @@ MESSAGE
856
952
  end
857
953
  end
858
954
 
859
- def output_to_tty?
860
- begin
861
- output_stream.tty? || tty?
862
- rescue NoMethodError
863
- false
864
- end
955
+ def output_to_tty?(output=output_stream)
956
+ tty? || (output.respond_to?(:tty?) && output.tty?)
865
957
  end
866
958
 
867
959
  def built_in_formatter(key)
@@ -878,6 +970,9 @@ MESSAGE
878
970
  when 'p', 'progress'
879
971
  require 'rspec/core/formatters/progress_formatter'
880
972
  RSpec::Core::Formatters::ProgressFormatter
973
+ when 'j', 'json'
974
+ require 'rspec/core/formatters/json_formatter'
975
+ RSpec::Core::Formatters::JsonFormatter
881
976
  end
882
977
  end
883
978
 
@@ -923,7 +1018,9 @@ MESSAGE
923
1018
  end
924
1019
 
925
1020
  def order_and_seed_from_seed(value)
1021
+ order_groups_and_examples(&RANDOM_ORDERING)
926
1022
  @order, @seed = 'rand', value.to_i
1023
+ [@order, @seed]
927
1024
  end
928
1025
 
929
1026
  def set_order_and_seed(hash)
@@ -935,10 +1032,21 @@ MESSAGE
935
1032
  order, seed = type.to_s.split(':')
936
1033
  @order = order
937
1034
  @seed = seed = seed.to_i if seed
938
- @order, @seed = nil, nil if order == 'default'
1035
+
1036
+ if randomize?
1037
+ order_groups_and_examples(&RANDOM_ORDERING)
1038
+ elsif order == 'default'
1039
+ @order, @seed = nil, nil
1040
+ order_groups_and_examples(&DEFAULT_ORDERING)
1041
+ end
1042
+
939
1043
  return order, seed
940
1044
  end
941
1045
 
1046
+ def built_in_orderer?(block)
1047
+ [DEFAULT_ORDERING, RANDOM_ORDERING].include?(block)
1048
+ end
1049
+
942
1050
  end
943
1051
  end
944
1052
  end
@@ -9,6 +9,13 @@ module RSpec
9
9
 
10
10
  def initialize(args)
11
11
  @args = args
12
+ if args.include?("--default_path")
13
+ args[args.index("--default_path")] = "--default-path"
14
+ end
15
+
16
+ if args.include?("--line_number")
17
+ args[args.index("--line_number")] = "--line-number"
18
+ end
12
19
  end
13
20
 
14
21
  def configure(config)
@@ -71,7 +78,7 @@ module RSpec
71
78
  end
72
79
 
73
80
  def file_options
74
- custom_options_file ? [custom_options] : [global_options, local_options]
81
+ custom_options_file ? [custom_options] : [global_options, project_options, local_options]
75
82
  end
76
83
 
77
84
  def env_options
@@ -90,6 +97,10 @@ module RSpec
90
97
  @local_options ||= options_from(local_options_file)
91
98
  end
92
99
 
100
+ def project_options
101
+ @project_options ||= options_from(project_options_file)
102
+ end
103
+
93
104
  def global_options
94
105
  @global_options ||= options_from(global_options_file)
95
106
  end
@@ -112,10 +123,14 @@ module RSpec
112
123
  command_line_options[:custom_options_file]
113
124
  end
114
125
 
115
- def local_options_file
126
+ def project_options_file
116
127
  ".rspec"
117
128
  end
118
129
 
130
+ def local_options_file
131
+ ".rspec-local"
132
+ end
133
+
119
134
  def global_options_file
120
135
  begin
121
136
  File.join(File.expand_path("~"), ".rspec")
@@ -49,7 +49,8 @@ module RSpec
49
49
  # there is one, otherwise returns a message including the location of the
50
50
  # example.
51
51
  def description
52
- metadata[:description].to_s.empty? ? "example at #{location}" : metadata[:description]
52
+ description = metadata[:description].to_s.empty? ? "example at #{location}" : metadata[:description]
53
+ RSpec.configuration.format_docstrings_block.call(description)
53
54
  end
54
55
 
55
56
  # @attr_reader
@@ -260,7 +261,7 @@ An error occurred #{context}
260
261
 
261
262
  def start(reporter)
262
263
  reporter.example_started(self)
263
- record :started_at => Time.now
264
+ record :started_at => RSpec::Core::Time.now
264
265
  end
265
266
 
266
267
  # @private
@@ -290,8 +291,8 @@ An error occurred #{context}
290
291
  end
291
292
 
292
293
  def record_finished(status, results={})
293
- finished_at = Time.now
294
- record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - execution_result[:started_at]))
294
+ finished_at = RSpec::Core::Time.now
295
+ record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - execution_result[:started_at]).to_f)
295
296
  end
296
297
 
297
298
  def run_before_each
@@ -22,6 +22,7 @@ module RSpec
22
22
  include Subject::ExampleMethods
23
23
  include Pending
24
24
  include Let
25
+ include SharedExampleGroup
25
26
 
26
27
  # @private
27
28
  def self.world
@@ -43,7 +44,12 @@ module RSpec
43
44
  end
44
45
  end
45
46
 
46
- delegate_to_metadata :description, :described_class, :file_path
47
+ def description
48
+ description = metadata[:example_group][:description]
49
+ RSpec.configuration.format_docstrings_block.call(description)
50
+ end
51
+
52
+ delegate_to_metadata :described_class, :file_path
47
53
  alias_method :display_name, :description
48
54
  # @private
49
55
  alias_method :describes, :described_class
@@ -241,7 +247,7 @@ module RSpec
241
247
 
242
248
  # @private
243
249
  def self.children
244
- @children ||= [].extend(Extensions::Ordered)
250
+ @children ||= [].extend(Extensions::Ordered::ExampleGroups)
245
251
  end
246
252
 
247
253
  # @private
@@ -249,9 +255,9 @@ module RSpec
249
255
  @_descendants ||= [self] + children.inject([]) {|list, c| list + c.descendants}
250
256
  end
251
257
 
252
- # @private
253
- def self.ancestors
254
- @_ancestors ||= super().select {|a| a < RSpec::Core::ExampleGroup}
258
+ ## @private
259
+ def self.parent_groups
260
+ @parent_groups ||= ancestors.select {|a| a < RSpec::Core::ExampleGroup}
255
261
  end
256
262
 
257
263
  # @private
@@ -308,9 +314,12 @@ module RSpec
308
314
  # @private
309
315
  def self.run_before_all_hooks(example_group_instance)
310
316
  return if descendant_filtered_examples.empty?
311
- assign_before_all_ivars(superclass.before_all_ivars, example_group_instance)
312
- run_hook(:before, :all, example_group_instance)
313
- store_before_all_ivars(example_group_instance)
317
+ begin
318
+ assign_before_all_ivars(superclass.before_all_ivars, example_group_instance)
319
+ run_hook(:before, :all, example_group_instance)
320
+ ensure
321
+ store_before_all_ivars(example_group_instance)
322
+ end
314
323
  end
315
324
 
316
325
  # @private
@@ -361,6 +370,7 @@ An error occurred in an after(:all) hook.
361
370
  results_for_descendants = children.ordered.map {|child| child.run(reporter)}.all?
362
371
  result_for_this_group && results_for_descendants
363
372
  rescue Exception => ex
373
+ RSpec.wants_to_quit = true if fail_fast?
364
374
  fail_filtered_examples(ex, reporter)
365
375
  ensure
366
376
  run_after_all_hooks(new)
@@ -417,7 +427,7 @@ An error occurred in an after(:all) hook.
417
427
 
418
428
  # @private
419
429
  def self.top_level_description
420
- ancestors.last.description
430
+ parent_groups.last.description
421
431
  end
422
432
 
423
433
  # @private
@@ -7,12 +7,18 @@ module RSpec
7
7
  # strategies like randomization.
8
8
  module Ordered
9
9
  # @private
10
- def ordered
11
- if RSpec.configuration.randomize?
12
- Kernel.srand RSpec.configuration.seed
13
- sort_by { Kernel.rand size }
14
- else
15
- self
10
+ module ExampleGroups
11
+ # @private
12
+ def ordered
13
+ RSpec.configuration.group_ordering_block.call(self)
14
+ end
15
+ end
16
+
17
+ # @private
18
+ module Examples
19
+ # @private
20
+ def ordered
21
+ RSpec.configuration.example_ordering_block.call(self)
16
22
  end
17
23
  end
18
24
  end
@@ -0,0 +1,55 @@
1
+ # ## Built-in Formatters
2
+ #
3
+ # * progress (default) - prints dots for passing examples, `F` for failures, `*` for pending
4
+ # * documentation - prints the docstrings passed to `describe` and `it` methods (and their aliases)
5
+ # * html
6
+ # * textmate - html plus links to editor
7
+ # * json - useful for archiving data for subsequent analysis
8
+ #
9
+ # The progress formatter is the default, but you can choose any one or more of
10
+ # the other formatters by passing with the `--format` (or `-f` for short)
11
+ # command-line option, e.g.
12
+ #
13
+ # rspec --format documentation
14
+ #
15
+ # You can also send the output of multiple formatters to different streams, e.g.
16
+ #
17
+ # rspec --format documentation --format html --out results.html
18
+ #
19
+ # This example sends the output of the documentation formatter to `STDOUT`, and
20
+ # the output of the html formatter to results.html.
21
+ #
22
+ # ## Custom Formatters
23
+ #
24
+ # You can tell RSpec to use a custom formatter by passing its path and name to
25
+ # the `rspec` commmand. For example, if you define MyCustomFormatter in
26
+ # path/to/my_custom_formatter.rb, you would type this command:
27
+ #
28
+ # rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter
29
+ #
30
+ # The reporter calls every formatter with this protocol:
31
+ #
32
+ # * `start(expected_example_count)`
33
+ # * zero or more of the following
34
+ # * `example_group_started(group)`
35
+ # * `example_started(example)`
36
+ # * `example_passed(example)`
37
+ # * `example_failed(example)`
38
+ # * `example_pending(example)`
39
+ # * `message(string)`
40
+ # * `stop`
41
+ # * `start_dump`
42
+ # * `dump_pending`
43
+ # * `dump_failures`
44
+ # * `dump_summary(duration, example_count, failure_count, pending_count)`
45
+ # * `seed(value)`
46
+ # * `close`
47
+ #
48
+ # You can either implement all of those methods or subclass
49
+ # `RSpec::Core::Formatters::BaseTextFormatter` and override the methods you want
50
+ # to enhance.
51
+ #
52
+ # @see RSpec::Core::Formatters::BaseTextFormatter
53
+ # @see RSpec::Core::Reporter
54
+ module RSpec::Core::Formatters
55
+ end