rspec 0.8.2 → 0.9.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 (245) hide show
  1. data/CHANGES +125 -9
  2. data/EXAMPLES.rd +50 -27
  3. data/README +14 -1
  4. data/Rakefile +95 -42
  5. data/UPGRADE +31 -0
  6. data/bin/spec +0 -1
  7. data/bin/spec_translator +6 -0
  8. data/examples/auto_spec_description_example.rb +19 -0
  9. data/examples/{setup_teardown_example.rb → before_and_after_example.rb} +6 -6
  10. data/examples/behave_as_example.rb +45 -0
  11. data/examples/custom_expectation_matchers.rb +13 -12
  12. data/examples/dynamic_spec.rb +2 -2
  13. data/examples/file_accessor_spec.rb +2 -2
  14. data/examples/greeter_spec.rb +3 -3
  15. data/examples/helper_method_example.rb +2 -2
  16. data/examples/io_processor_spec.rb +4 -4
  17. data/examples/legacy_spec.rb +10 -0
  18. data/examples/mocking_example.rb +5 -5
  19. data/examples/multi_threaded_behaviour_runner.rb +25 -0
  20. data/examples/partial_mock_example.rb +4 -4
  21. data/examples/predicate_example.rb +4 -4
  22. data/examples/priority.txt +1 -0
  23. data/examples/shared_behaviours_example.rb +31 -0
  24. data/examples/stack_spec.rb +52 -69
  25. data/examples/stubbing_example.rb +10 -10
  26. data/examples/test_case_adapter_example.rb +26 -0
  27. data/examples/test_case_spec.rb +6 -6
  28. data/lib/spec.rb +9 -4
  29. data/lib/spec/dsl.rb +10 -0
  30. data/lib/spec/dsl/behaviour.rb +189 -0
  31. data/lib/spec/dsl/behaviour_callbacks.rb +43 -0
  32. data/lib/spec/dsl/behaviour_eval.rb +170 -0
  33. data/lib/spec/dsl/behaviour_factory.rb +32 -0
  34. data/lib/spec/dsl/composite_proc_builder.rb +28 -0
  35. data/lib/spec/dsl/configuration.rb +38 -0
  36. data/lib/spec/dsl/description.rb +34 -0
  37. data/lib/spec/dsl/example.rb +114 -0
  38. data/lib/spec/dsl/example_matcher.rb +28 -0
  39. data/lib/spec/{runner/spec_should_raise_handler.rb → dsl/example_should_raise_handler.rb} +4 -4
  40. data/lib/spec/expectations.rb +0 -3
  41. data/lib/spec/expectations/differs/default.rb +0 -1
  42. data/lib/spec/expectations/extensions.rb +0 -1
  43. data/lib/spec/expectations/extensions/object.rb +10 -53
  44. data/lib/spec/expectations/handler.rb +14 -18
  45. data/lib/spec/extensions.rb +1 -0
  46. data/lib/spec/extensions/object.rb +6 -0
  47. data/lib/spec/matchers.rb +19 -21
  48. data/lib/spec/matchers/be.rb +40 -11
  49. data/lib/spec/matchers/be_close.rb +2 -2
  50. data/lib/spec/matchers/operator_matcher.rb +52 -0
  51. data/lib/spec/matchers/respond_to.rb +21 -11
  52. data/lib/spec/mocks.rb +5 -28
  53. data/lib/spec/mocks/argument_constraint_matchers.rb +12 -0
  54. data/lib/spec/mocks/argument_expectation.rb +7 -4
  55. data/lib/spec/mocks/methods.rb +11 -16
  56. data/lib/spec/mocks/mock.rb +6 -3
  57. data/lib/spec/mocks/{mock_handler.rb → proxy.rb} +4 -7
  58. data/lib/spec/mocks/space.rb +28 -0
  59. data/lib/spec/mocks/spec_methods.rb +30 -0
  60. data/lib/spec/rake/spectask.rb +23 -21
  61. data/lib/spec/rake/verify_rcov.rb +1 -0
  62. data/lib/spec/runner.rb +88 -35
  63. data/lib/spec/runner/backtrace_tweaker.rb +2 -1
  64. data/lib/spec/runner/behaviour_runner.rb +102 -0
  65. data/lib/spec/runner/command_line.rb +5 -17
  66. data/lib/spec/runner/drb_command_line.rb +2 -2
  67. data/lib/spec/runner/extensions/kernel.rb +22 -9
  68. data/lib/spec/runner/formatter.rb +4 -0
  69. data/lib/spec/runner/formatter/base_formatter.rb +63 -0
  70. data/lib/spec/runner/formatter/base_text_formatter.rb +22 -52
  71. data/lib/spec/runner/formatter/failing_behaviours_formatter.rb +25 -0
  72. data/lib/spec/runner/formatter/failing_examples_formatter.rb +22 -0
  73. data/lib/spec/runner/formatter/html_formatter.rb +74 -29
  74. data/lib/spec/runner/formatter/progress_bar_formatter.rb +6 -8
  75. data/lib/spec/runner/formatter/rdoc_formatter.rb +6 -6
  76. data/lib/spec/runner/formatter/snippet_extractor.rb +52 -0
  77. data/lib/spec/runner/formatter/specdoc_formatter.rb +6 -6
  78. data/lib/spec/runner/heckle_runner.rb +8 -7
  79. data/lib/spec/runner/option_parser.rb +136 -55
  80. data/lib/spec/runner/options.rb +26 -0
  81. data/lib/spec/runner/reporter.rb +38 -31
  82. data/lib/spec/runner/spec_parser.rb +22 -13
  83. data/lib/spec/test_case_adapter.rb +10 -0
  84. data/lib/spec/translator.rb +103 -86
  85. data/lib/spec/version.rb +7 -15
  86. data/plugins/mock_frameworks/flexmock.rb +27 -0
  87. data/plugins/mock_frameworks/mocha.rb +21 -0
  88. data/plugins/mock_frameworks/rspec.rb +18 -0
  89. data/spec/spec/dsl/behaviour_eval_spec.rb +49 -0
  90. data/spec/spec/dsl/behaviour_factory_spec.rb +30 -0
  91. data/spec/spec/dsl/behaviour_spec.rb +508 -0
  92. data/spec/spec/dsl/composite_proc_builder_spec.rb +57 -0
  93. data/spec/spec/dsl/configuration_spec.rb +43 -0
  94. data/spec/spec/dsl/description_spec.rb +51 -0
  95. data/spec/spec/dsl/example_class_spec.rb +24 -0
  96. data/spec/spec/dsl/example_instance_spec.rb +140 -0
  97. data/spec/spec/dsl/example_should_raise_spec.rb +137 -0
  98. data/spec/spec/dsl/predicate_matcher_spec.rb +21 -0
  99. data/spec/spec/dsl/shared_behaviour_spec.rb +186 -0
  100. data/spec/spec/expectations/differs/default_spec.rb +12 -12
  101. data/spec/spec/expectations/extensions/object_spec.rb +10 -10
  102. data/spec/spec/expectations/fail_with_spec.rb +20 -20
  103. data/spec/spec/matchers/be_close_spec.rb +37 -31
  104. data/spec/spec/matchers/be_spec.rb +50 -41
  105. data/spec/spec/matchers/change_spec.rb +54 -54
  106. data/spec/spec/matchers/description_generation_spec.rb +43 -31
  107. data/spec/spec/matchers/eql_spec.rb +24 -37
  108. data/spec/spec/matchers/equal_spec.rb +24 -37
  109. data/spec/spec/matchers/exist_spec.rb +48 -0
  110. data/spec/spec/matchers/handler_spec.rb +36 -23
  111. data/spec/spec/matchers/has_spec.rb +8 -8
  112. data/spec/spec/matchers/have_spec.rb +38 -38
  113. data/spec/spec/matchers/include_spec.rb +6 -6
  114. data/spec/spec/matchers/match_spec.rb +8 -8
  115. data/spec/spec/matchers/matcher_methods_spec.rb +24 -31
  116. data/spec/spec/matchers/raise_error_spec.rb +34 -34
  117. data/spec/spec/matchers/respond_to_spec.rb +32 -8
  118. data/spec/spec/matchers/satisfy_spec.rb +6 -6
  119. data/spec/spec/matchers/should_===_spec.rb +38 -0
  120. data/spec/spec/matchers/should_==_spec.rb +37 -0
  121. data/spec/spec/matchers/should_=~_spec.rb +36 -0
  122. data/spec/spec/matchers/throw_symbol_spec.rb +47 -55
  123. data/spec/spec/mocks/any_number_of_times_spec.rb +16 -21
  124. data/spec/spec/mocks/argument_expectation_spec.rb +3 -3
  125. data/spec/spec/mocks/at_least_spec.rb +30 -30
  126. data/spec/spec/mocks/at_most_spec.rb +53 -57
  127. data/spec/spec/mocks/bug_report_10260_spec.rb +8 -0
  128. data/spec/spec/mocks/bug_report_7611_spec.rb +3 -3
  129. data/spec/spec/mocks/bug_report_7805_spec.rb +3 -3
  130. data/spec/spec/mocks/bug_report_8165_spec.rb +5 -5
  131. data/spec/spec/mocks/bug_report_8302_spec.rb +5 -5
  132. data/spec/spec/mocks/failing_mock_argument_constraints_spec.rb +26 -27
  133. data/spec/spec/mocks/mock_ordering_spec.rb +19 -15
  134. data/spec/spec/mocks/mock_space_spec.rb +54 -0
  135. data/spec/spec/mocks/mock_spec.rb +111 -141
  136. data/spec/spec/mocks/multiple_return_value_spec.rb +48 -48
  137. data/spec/spec/mocks/null_object_mock_spec.rb +10 -10
  138. data/spec/spec/mocks/once_counts_spec.rb +32 -35
  139. data/spec/spec/mocks/options_hash_spec.rb +12 -10
  140. data/spec/spec/mocks/partial_mock_spec.rb +15 -15
  141. data/spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb +24 -22
  142. data/spec/spec/mocks/passing_mock_argument_constraints_spec.rb +19 -19
  143. data/spec/spec/mocks/precise_counts_spec.rb +28 -32
  144. data/spec/spec/mocks/record_messages_spec.rb +10 -10
  145. data/spec/spec/mocks/stub_spec.rb +45 -45
  146. data/spec/spec/mocks/twice_counts_spec.rb +21 -21
  147. data/spec/spec/package/bin_spec_spec.rb +12 -0
  148. data/spec/spec/runner/behaviour_runner_spec.rb +114 -0
  149. data/spec/spec/runner/command_line_spec.rb +8 -8
  150. data/spec/spec/runner/context_matching_spec.rb +14 -15
  151. data/spec/spec/runner/drb_command_line_spec.rb +12 -12
  152. data/spec/spec/runner/execution_context_spec.rb +8 -29
  153. data/spec/spec/runner/extensions/kernel_spec.rb +36 -0
  154. data/spec/spec/runner/formatter/failing_behaviours_formatter_spec.rb +27 -0
  155. data/spec/spec/runner/formatter/failing_examples_formatter_spec.rb +28 -0
  156. data/spec/spec/runner/formatter/html_formatter_spec.rb +9 -8
  157. data/spec/spec/runner/formatter/progress_bar_formatter_dry_run_spec.rb +6 -6
  158. data/spec/spec/runner/formatter/progress_bar_formatter_failure_dump_spec.rb +10 -10
  159. data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +22 -27
  160. data/spec/spec/runner/formatter/rdoc_formatter_dry_run_spec.rb +6 -5
  161. data/spec/spec/runner/formatter/rdoc_formatter_spec.rb +17 -17
  162. data/spec/spec/runner/formatter/snippet_extractor_spec.rb +11 -0
  163. data/spec/spec/runner/formatter/specdoc_formatter_dry_run_spec.rb +6 -6
  164. data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +17 -17
  165. data/spec/spec/runner/heckle_runner_spec.rb +21 -21
  166. data/spec/spec/runner/heckler_spec.rb +5 -5
  167. data/spec/spec/runner/noisy_backtrace_tweaker_spec.rb +12 -12
  168. data/spec/spec/runner/object_ext_spec.rb +3 -3
  169. data/spec/spec/runner/option_parser_spec.rb +171 -102
  170. data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +21 -12
  171. data/spec/spec/runner/reporter_spec.rb +106 -97
  172. data/spec/spec/runner/spec_matcher_spec.rb +46 -51
  173. data/spec/spec/runner/spec_parser_spec.rb +72 -16
  174. data/spec/spec/spec_classes.rb +12 -3
  175. data/spec/spec/translator_spec.rb +165 -36
  176. metadata +66 -76
  177. data/RELEASE-PLAN +0 -117
  178. data/examples/auto_spec_name_generation_example.rb +0 -18
  179. data/lib/spec/callback.rb +0 -11
  180. data/lib/spec/callback/callback_container.rb +0 -60
  181. data/lib/spec/callback/extensions/module.rb +0 -24
  182. data/lib/spec/callback/extensions/object.rb +0 -37
  183. data/lib/spec/deprecated.rb +0 -3
  184. data/lib/spec/expectations/extensions/proc.rb +0 -57
  185. data/lib/spec/expectations/should.rb +0 -5
  186. data/lib/spec/expectations/should/base.rb +0 -64
  187. data/lib/spec/expectations/should/change.rb +0 -69
  188. data/lib/spec/expectations/should/have.rb +0 -128
  189. data/lib/spec/expectations/should/not.rb +0 -74
  190. data/lib/spec/expectations/should/should.rb +0 -81
  191. data/lib/spec/expectations/sugar.rb +0 -47
  192. data/lib/spec/runner/context.rb +0 -154
  193. data/lib/spec/runner/context_eval.rb +0 -142
  194. data/lib/spec/runner/context_runner.rb +0 -55
  195. data/lib/spec/runner/execution_context.rb +0 -17
  196. data/lib/spec/runner/spec_matcher.rb +0 -25
  197. data/lib/spec/runner/specification.rb +0 -114
  198. data/spec/spec/callback/callback_container_spec.rb +0 -27
  199. data/spec/spec/callback/module_spec.rb +0 -37
  200. data/spec/spec/callback/object_spec.rb +0 -90
  201. data/spec/spec/callback/object_with_class_callback_spec.rb +0 -19
  202. data/spec/spec/expectations/should/should_==_spec.rb +0 -19
  203. data/spec/spec/expectations/should/should_=~_spec.rb +0 -13
  204. data/spec/spec/expectations/should/should_be_a_kind_of_spec.rb +0 -21
  205. data/spec/spec/expectations/should/should_be_an_instance_of_spec.rb +0 -30
  206. data/spec/spec/expectations/should/should_be_arbitrary_predicate_spec.rb +0 -81
  207. data/spec/spec/expectations/should/should_be_close_spec.rb +0 -18
  208. data/spec/spec/expectations/should/should_be_comparison_operator_spec.rb +0 -44
  209. data/spec/spec/expectations/should/should_be_false_spec.rb +0 -39
  210. data/spec/spec/expectations/should/should_be_spec.rb +0 -11
  211. data/spec/spec/expectations/should/should_be_true_spec.rb +0 -27
  212. data/spec/spec/expectations/should/should_change_spec.rb +0 -184
  213. data/spec/spec/expectations/should/should_eql_spec.rb +0 -11
  214. data/spec/spec/expectations/should/should_equal_spec.rb +0 -11
  215. data/spec/spec/expectations/should/should_have_at_least_spec.rb +0 -53
  216. data/spec/spec/expectations/should/should_have_at_most_spec.rb +0 -45
  217. data/spec/spec/expectations/should/should_have_key_spec.rb +0 -21
  218. data/spec/spec/expectations/should/should_have_spec.rb +0 -64
  219. data/spec/spec/expectations/should/should_include_spec.rb +0 -59
  220. data/spec/spec/expectations/should/should_match_spec.rb +0 -25
  221. data/spec/spec/expectations/should/should_not_==_spec.rb +0 -15
  222. data/spec/spec/expectations/should/should_not_be_a_kind_of_spec.rb +0 -21
  223. data/spec/spec/expectations/should/should_not_be_an_instance_of_spec.rb +0 -11
  224. data/spec/spec/expectations/should/should_not_be_arbitrary_predicate_spec.rb +0 -68
  225. data/spec/spec/expectations/should/should_not_be_spec.rb +0 -11
  226. data/spec/spec/expectations/should/should_not_change_spec.rb +0 -24
  227. data/spec/spec/expectations/should/should_not_eql_spec.rb +0 -11
  228. data/spec/spec/expectations/should/should_not_equal_spec.rb +0 -11
  229. data/spec/spec/expectations/should/should_not_have_key_spec.rb +0 -15
  230. data/spec/spec/expectations/should/should_not_include_spec.rb +0 -58
  231. data/spec/spec/expectations/should/should_not_match_spec.rb +0 -11
  232. data/spec/spec/expectations/should/should_not_raise_spec.rb +0 -75
  233. data/spec/spec/expectations/should/should_not_respond_to_spec.rb +0 -15
  234. data/spec/spec/expectations/should/should_not_throw_spec.rb +0 -35
  235. data/spec/spec/expectations/should/should_raise_spec.rb +0 -66
  236. data/spec/spec/expectations/should/should_respond_to_spec.rb +0 -15
  237. data/spec/spec/expectations/should/should_satisfy_spec.rb +0 -35
  238. data/spec/spec/expectations/should/should_throw_spec.rb +0 -27
  239. data/spec/spec/runner/context_runner_spec.rb +0 -100
  240. data/spec/spec/runner/context_spec.rb +0 -405
  241. data/spec/spec/runner/kernel_ext_spec.rb +0 -16
  242. data/spec/spec/runner/spec_name_generation_spec.rb +0 -102
  243. data/spec/spec/runner/specification_class_spec.rb +0 -72
  244. data/spec/spec/runner/specification_instance_spec.rb +0 -160
  245. data/spec/spec/runner/specification_should_raise_spec.rb +0 -136
@@ -10,24 +10,12 @@ module Spec
10
10
  # +warn_if_no_files+ tells whether or not a warning (the help message)
11
11
  # should be printed to +err+ in case no files are specified.
12
12
  def self.run(argv, err, out, exit=true, warn_if_no_files=true)
13
- old_context_runner = defined?($context_runner) ? $context_runner : nil
14
- $context_runner = OptionParser.new.create_context_runner(argv, err, out, warn_if_no_files)
15
- return if $context_runner.nil? # This is the case if we use --drb
13
+ old_behaviour_runner = defined?($behaviour_runner) ? $behaviour_runner : nil
14
+ $behaviour_runner = OptionParser.new.create_behaviour_runner(argv, err, out, warn_if_no_files)
15
+ return if $behaviour_runner.nil? # This is the case if we use --drb
16
16
 
17
- # If ARGV is a glob, it will actually each over each one of the matching files.
18
- argv.each do |file_or_dir|
19
- if File.directory?(file_or_dir)
20
- Dir["#{file_or_dir}/**/*.rb"].each do |file|
21
- load file
22
- end
23
- elsif File.file?(file_or_dir)
24
- load file_or_dir
25
- else
26
- raise "File or directory not found: #{file_or_dir}"
27
- end
28
- end
29
- $context_runner.run(exit)
30
- $context_runner = old_context_runner
17
+ $behaviour_runner.run(argv, exit)
18
+ $behaviour_runner = old_behaviour_runner
31
19
  end
32
20
  end
33
21
  end
@@ -9,8 +9,8 @@ module Spec
9
9
  def self.run(argv, stderr, stdout, exit=true, warn_if_no_files=true)
10
10
  begin
11
11
  DRb.start_service
12
- rails_spec_server = DRbObject.new_with_uri("druby://localhost:8989")
13
- rails_spec_server.run(argv, stderr, stdout)
12
+ spec_server = DRbObject.new_with_uri("druby://localhost:8989")
13
+ spec_server.run(argv, stderr, stdout)
14
14
  rescue DRb::DRbConnError
15
15
  stderr.puts "No server is running"
16
16
  exit 1 if exit
@@ -1,17 +1,30 @@
1
1
  module Kernel
2
- def context(name, &block)
3
- context = Spec::Runner::Context.new(name, &block)
4
- context_runner.add_context(context)
2
+ def describe(*args, &block)
3
+ raise ArgumentError if args.empty?
4
+ register_behaviour(Spec::DSL::BehaviourFactory.create(*args, &block))
5
5
  end
6
-
6
+ alias :context :describe
7
+
8
+ def respond_to(*names)
9
+ Spec::Matchers::RespondTo.new(*names)
10
+ end
11
+
7
12
  private
8
13
 
9
- def context_runner
14
+ def register_behaviour(behaviour)
15
+ if behaviour.shared?
16
+ Spec::DSL::Behaviour.add_shared_behaviour(behaviour)
17
+ else
18
+ behaviour_runner.add_behaviour(behaviour)
19
+ end
20
+ end
21
+
22
+ def behaviour_runner
10
23
  # TODO: Figure out a better way to get this considered "covered" and keep this statement on multiple lines
11
- unless $context_runner; \
12
- $context_runner = ::Spec::Runner::OptionParser.new.create_context_runner(ARGV.dup, STDERR, STDOUT, false); \
13
- at_exit { $context_runner.run(false) }; \
24
+ unless $behaviour_runner; \
25
+ $behaviour_runner = ::Spec::Runner::OptionParser.new.create_behaviour_runner(ARGV.dup, STDERR, STDOUT, false); \
26
+ at_exit { $behaviour_runner.run(nil, false) }; \
14
27
  end
15
- $context_runner
28
+ $behaviour_runner
16
29
  end
17
30
  end
@@ -1,5 +1,9 @@
1
+ require 'spec/runner/formatter/base_formatter'
1
2
  require 'spec/runner/formatter/base_text_formatter'
2
3
  require 'spec/runner/formatter/progress_bar_formatter'
3
4
  require 'spec/runner/formatter/rdoc_formatter'
4
5
  require 'spec/runner/formatter/specdoc_formatter'
5
6
  require 'spec/runner/formatter/html_formatter'
7
+ require 'spec/runner/formatter/failing_examples_formatter'
8
+ require 'spec/runner/formatter/failing_behaviours_formatter'
9
+ require 'spec/runner/formatter/snippet_extractor'
@@ -0,0 +1,63 @@
1
+ module Spec
2
+ module Runner
3
+ module Formatter
4
+ # Baseclass for formatters that implements all required methods as no-ops.
5
+ class BaseFormatter
6
+ def initialize(where)
7
+ @where = where
8
+ end
9
+
10
+ # This method is invoked before any examples are run, right after
11
+ # they have all been collected. This can be useful for special
12
+ # formatters that need to provide progress on feedback (graphical ones)
13
+ #
14
+ # This method will only be invoked once, and the next one to be invoked
15
+ # is #add_behaviour
16
+ def start(example_count)
17
+ end
18
+
19
+ # This method is invoked at the beginning of the execution of each context.
20
+ # +name+ is the name of the context and +first+ is true if it is the
21
+ # first context - otherwise it's false.
22
+ #
23
+ # The next method to be invoked after this is #example_failed or #example_finished
24
+ def add_behaviour(name)
25
+ end
26
+
27
+ # This method is invoked when an example starts. +name+ is the name of the
28
+ # example.
29
+ def example_started(name)
30
+ end
31
+
32
+ # This method is invoked when an example passes. +name+ is the name of the
33
+ # example.
34
+ def example_passed(name)
35
+ end
36
+
37
+ # This method is invoked when an example fails, i.e. an exception occurred
38
+ # inside it (such as a failed should or other exception). +name+ is the name
39
+ # of the example. +counter+ is the sequence number of the failure
40
+ # (starting at 1) and +failure+ is the associated Failure object.
41
+ def example_failed(name, counter, failure)
42
+ end
43
+
44
+ # This method is invoked after all of the examples have executed. The next method
45
+ # to be invoked after this one is #dump_failure (once for each failed example),
46
+ def start_dump
47
+ end
48
+
49
+ # Dumps detailed information about an example failure.
50
+ # This method is invoked for each failed example after all examples have run. +counter+ is the sequence number
51
+ # of the associated example. +failure+ is a Failure object, which contains detailed
52
+ # information about the failure.
53
+ def dump_failure(counter, failure)
54
+ end
55
+
56
+ # This method is invoked at the very end.
57
+ def dump_summary(duration, example_count, failure_count)
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -4,58 +4,29 @@ module Spec
4
4
  # Baseclass for text-based formatters. Can in fact be used for
5
5
  # non-text based ones too - just ignore the +output+ constructor
6
6
  # argument.
7
- class BaseTextFormatter
8
- def initialize(output, dry_run=false, colour=false)
9
- @output = output
10
- @dry_run = dry_run
7
+ class BaseTextFormatter < BaseFormatter
8
+ attr_writer :dry_run
9
+
10
+ # Creates a new instance that will write to +where+. If +where+ is a
11
+ # String, output will be written to the File with that name, otherwise
12
+ # +where+ is exected to be an IO (or an object that responds to #puts and #write).
13
+ def initialize(where)
14
+ super(where)
15
+ if where.is_a?(String)
16
+ @output = File.open(where, 'w')
17
+ else
18
+ @output = where
19
+ end
20
+ @colour = false
21
+ @dry_run = false
22
+ @snippet_extractor = SnippetExtractor.new
23
+ end
24
+
25
+ def colour=(colour)
11
26
  @colour = colour
12
27
  begin ; require 'Win32/Console/ANSI' if @colour && PLATFORM =~ /win32/ ; rescue LoadError ; raise "You must gem install win32console to use colour on Windows" ; end
13
28
  end
14
29
 
15
- # This method is invoked before any specs are run, right after
16
- # they have all been collected. This can be useful for special
17
- # formatters that need to provide progress on feedback (graphical ones)
18
- #
19
- # This method will only be invoked once, and the next one to be invoked
20
- # is #add_context
21
- def start(spec_count)
22
- end
23
-
24
- # This method is invoked at the beginning of the execution of each context.
25
- # +name+ is the name of the context and +first+ is true if it is the
26
- # first context - otherwise it's false.
27
- #
28
- # The next method to be invoked after this is #spec_started
29
- def add_context(name, first)
30
- end
31
-
32
- # This method is invoked right before a spec is executed.
33
- # The next method to be invoked after this one is one of #spec_failed
34
- # or #spec_passed.
35
- def spec_started(name)
36
- end
37
-
38
- # This method is invoked when a spec fails, i.e. an exception occurred
39
- # inside it (such as a failed should or other exception). +name+ is the name
40
- # of the specification. +counter+ is the sequence number of the failure
41
- # (starting at 1) and +failure+ is the associated Failure object.
42
- def spec_failed(name, counter, failure)
43
- end
44
-
45
- # This method is invoked when a spec passes. +name+ is the name of the
46
- # specification.
47
- def spec_passed(name)
48
- end
49
-
50
- # This method is invoked after all of the specs have executed. The next method
51
- # to be invoked after this one is #dump_failure (once for each failed spec),
52
- def start_dump
53
- end
54
-
55
- # Dumps detailed information about a spec failure.
56
- # This method is invoked for each failed spec after all specs have run. +counter+ is the sequence number
57
- # of the associated spec. +failure+ is a Failure object, which contains detailed
58
- # information about the failure.
59
30
  def dump_failure(counter, failure)
60
31
  @output.puts
61
32
  @output.puts "#{counter.to_s})"
@@ -67,16 +38,15 @@ module Spec
67
38
  @output.puts magenta(failure.exception.message)
68
39
  end
69
40
  @output.puts format_backtrace(failure.exception.backtrace)
70
- STDOUT.flush
41
+ @output.flush
71
42
  end
72
43
 
73
- # This method is invoked at the very end.
74
- def dump_summary(duration, spec_count, failure_count)
44
+ def dump_summary(duration, example_count, failure_count)
75
45
  return if @dry_run
76
46
  @output.puts
77
47
  @output.puts "Finished in #{duration} seconds"
78
48
  @output.puts
79
- summary = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
49
+ summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
80
50
  if failure_count == 0
81
51
  @output.puts green(summary)
82
52
  else
@@ -0,0 +1,25 @@
1
+ module Spec
2
+ module Runner
3
+ module Formatter
4
+ class FailingBehavioursFormatter < BaseTextFormatter
5
+ def add_behaviour(behaviour_name)
6
+ @behaviour_name = behaviour_name
7
+ end
8
+
9
+ def example_failed(name, counter, failure)
10
+ unless @behaviour_name.nil?
11
+ @output.puts @behaviour_name
12
+ @output.flush
13
+ @behaviour_name = nil
14
+ end
15
+ end
16
+
17
+ def dump_failure(counter, failure)
18
+ end
19
+
20
+ def dump_summary(duration, example_count, failure_count)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module Spec
2
+ module Runner
3
+ module Formatter
4
+ class FailingExamplesFormatter < BaseTextFormatter
5
+ def add_behaviour(behaviour_name)
6
+ @behaviour_name = behaviour_name
7
+ end
8
+
9
+ def example_failed(name, counter, failure)
10
+ @output.puts "#{@behaviour_name} #{name}"
11
+ @output.flush
12
+ end
13
+
14
+ def dump_failure(counter, failure)
15
+ end
16
+
17
+ def dump_summary(duration, example_count, failure_count)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,65 +2,73 @@ module Spec
2
2
  module Runner
3
3
  module Formatter
4
4
  class HtmlFormatter < BaseTextFormatter
5
- attr_reader :current_spec_number, :current_context_number
6
5
 
7
- def initialize(output, dry_run=false, colour=false)
6
+ def initialize(output)
8
7
  super
9
- @current_spec_number = 0
10
- @current_context_number = 0
8
+ @current_behaviour_number = 0
9
+ @current_example_number = 0
11
10
  end
12
11
 
13
- def start(spec_count)
14
- @spec_count = spec_count
12
+ # The number of the currently running behaviour
13
+ def current_behaviour_number
14
+ @current_behaviour_number
15
+ end
16
+
17
+ # The number of the currently running example
18
+ def current_example_number
19
+ @current_example_number
20
+ end
21
+
22
+ def start(example_count)
23
+ @example_count = example_count
15
24
 
16
25
  @output.puts HEADER_1
17
26
  @output.puts extra_header_content unless extra_header_content.nil?
18
27
  @output.puts HEADER_2
19
- STDOUT.flush
28
+ @output.flush
20
29
  end
21
30
 
22
- def add_context(name, first)
23
- @current_context_number += 1
24
- unless first
31
+ def add_behaviour(name)
32
+ @current_behaviour_number += 1
33
+ unless current_behaviour_number == 1
25
34
  @output.puts " </dl>"
26
35
  @output.puts "</div>"
27
36
  end
28
37
  @output.puts "<div class=\"context\">"
29
38
  @output.puts " <dl>"
30
- @output.puts " <dt id=\"context_#{@current_context_number}\">#{name}</dt>"
31
- STDOUT.flush
39
+ @output.puts " <dt id=\"context_#{current_behaviour_number}\">#{escape(name)}</dt>"
40
+ @output.flush
32
41
  end
33
42
 
34
43
  def start_dump
35
44
  @output.puts " </dl>"
36
45
  @output.puts "</div>"
37
- STDOUT.flush
38
- end
39
-
40
- def spec_started(name)
41
- @current_spec_number += 1
42
- STDOUT.flush
46
+ @output.flush
43
47
  end
44
48
 
45
- def spec_passed(name)
49
+ def example_passed(name)
50
+ @current_example_number += 1
46
51
  move_progress
47
52
  @output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{escape(name)}</span></dd>"
48
- STDOUT.flush
53
+ @output.flush
49
54
  end
50
55
 
51
- def spec_failed(name, counter, failure)
56
+ def example_failed(name, counter, failure)
57
+ extra = extra_failure_content(failure)
58
+
59
+ @current_example_number += 1
52
60
  @output.puts " <script type=\"text/javascript\">makeRed('header');</script>"
53
- @output.puts " <script type=\"text/javascript\">makeRed('context_#{@current_context_number}');</script>"
61
+ @output.puts " <script type=\"text/javascript\">makeRed('context_#{current_behaviour_number}');</script>"
54
62
  move_progress
55
63
  @output.puts " <dd class=\"spec failed\">"
56
64
  @output.puts " <span class=\"failed_spec_name\">#{escape(name)}</span>"
57
65
  @output.puts " <div class=\"failure\" id=\"failure_#{counter}\">"
58
66
  @output.puts " <div class=\"message\"><pre>#{escape(failure.exception.message)}</pre></div>" unless failure.exception.nil?
59
67
  @output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil?
60
- @output.puts extra_failure_content unless extra_failure_content.nil?
68
+ @output.puts extra unless extra == ""
61
69
  @output.puts " </div>"
62
70
  @output.puts " </dd>"
63
- STDOUT.flush
71
+ @output.flush
64
72
  end
65
73
 
66
74
  # Override this method if you wish to output extra HTML in the header
@@ -71,11 +79,12 @@ module Spec
71
79
  # Override this method if you wish to output extra HTML for a failed spec. For example, you
72
80
  # could output links to images or other files produced during the specs.
73
81
  #
74
- def extra_failure_content
82
+ def extra_failure_content(failure)
83
+ " <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(failure.exception)}</code></pre>"
75
84
  end
76
85
 
77
86
  def move_progress
78
- percent_done = @spec_count == 0 ? 100.0 : (@current_spec_number.to_f / @spec_count.to_f * 1000).to_i / 10.0
87
+ percent_done = @example_count == 0 ? 100.0 : (current_example_number.to_f / @example_count.to_f * 1000).to_i / 10.0
79
88
  @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
80
89
  end
81
90
 
@@ -86,18 +95,18 @@ module Spec
86
95
  def dump_failure(counter, failure)
87
96
  end
88
97
 
89
- def dump_summary(duration, spec_count, failure_count)
98
+ def dump_summary(duration, example_count, failure_count)
90
99
  if @dry_run
91
100
  totals = "This was a dry-run"
92
101
  else
93
- totals = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
102
+ totals = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
94
103
  end
95
104
  @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
96
105
  @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
97
106
  @output.puts "</div>"
98
107
  @output.puts "</body>"
99
108
  @output.puts "</html>"
100
- STDOUT.flush
109
+ @output.flush
101
110
  end
102
111
 
103
112
  HEADER_1 = <<-EOF
@@ -198,6 +207,42 @@ EOF
198
207
  a {
199
208
  color: #BE5C00;
200
209
  }
210
+
211
+ /* Ruby code, style similar to vibrant ink */
212
+ pre.ruby {
213
+ font-size: 12px;
214
+ font-family: monospace;
215
+ color: white;
216
+ background-color: black;
217
+ padding: 0.1em 0 0.2em 0;
218
+ }
219
+
220
+ .keyword { color: #FF6600; }
221
+ .constant { color: #339999; }
222
+ .attribute { color: white; }
223
+ .global { color: white; }
224
+ .module { color: white; }
225
+ .class { color: white; }
226
+ .string { color: #66FF00; }
227
+ .ident { color: white; }
228
+ .method { color: #FFCC00; }
229
+ .number { color: white; }
230
+ .char { color: white; }
231
+ .comment { color: #9933CC; }
232
+ .symbol { color: white; }
233
+ .regex { color: #44B4CC; }
234
+ .punct { color: white; }
235
+ .escape { color: white; }
236
+ .interp { color: white; }
237
+ .expr { color: white; }
238
+
239
+ .offending { background-color: gray; }
240
+ .linenum {
241
+ width: 75px;
242
+ padding: 0.1em 1em 0.2em 0;
243
+ color: #000000;
244
+ background-color: #FFFBD3;
245
+ }
201
246
  </style>
202
247
  </head>
203
248
  <body>