rspec 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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>