rspec 0.4.0 → 0.5.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 (94) hide show
  1. data/CHANGES +7 -12
  2. data/Rakefile +17 -12
  3. data/TUTORIAL +1 -1
  4. data/WHY_RSPEC +115 -0
  5. data/bin/spec +17 -4
  6. data/bin/test2rspec +35 -0
  7. data/examples/airport_spec.rb +35 -0
  8. data/examples/mocking_spec.rb +16 -0
  9. data/examples/spec_framework_spec.rb +28 -0
  10. data/examples/stack.rb +36 -0
  11. data/examples/stack_spec.rb +112 -0
  12. data/lib/spec.rb +5 -18
  13. data/lib/spec/api.rb +4 -0
  14. data/lib/spec/{exceptions.rb → api/exceptions.rb} +1 -1
  15. data/lib/spec/{expectations.rb → api/expectations.rb} +5 -4
  16. data/lib/spec/api/helper.rb +10 -0
  17. data/lib/spec/{have_helper.rb → api/helper/have_helper.rb} +1 -1
  18. data/lib/spec/{instance_helper.rb → api/helper/instance_helper.rb} +0 -0
  19. data/lib/spec/{instance_negator.rb → api/helper/instance_negator.rb} +0 -0
  20. data/lib/spec/{kind_helper.rb → api/helper/kind_helper.rb} +0 -0
  21. data/lib/spec/{kind_negator.rb → api/helper/kind_negator.rb} +0 -0
  22. data/lib/spec/{respond_helper.rb → api/helper/respond_helper.rb} +0 -0
  23. data/lib/spec/{respond_negator.rb → api/helper/respond_negator.rb} +0 -0
  24. data/lib/spec/{should_base.rb → api/helper/should_base.rb} +6 -4
  25. data/lib/spec/{should_helper.rb → api/helper/should_helper.rb} +12 -0
  26. data/lib/spec/{should_negator.rb → api/helper/should_negator.rb} +11 -0
  27. data/lib/spec/api/mock.rb +184 -0
  28. data/lib/spec/rake/spectask.rb +153 -0
  29. data/lib/spec/runner.rb +9 -0
  30. data/lib/spec/runner/backtrace_tweaker.rb +17 -0
  31. data/lib/spec/runner/context.rb +47 -0
  32. data/lib/spec/runner/context_runner.rb +52 -0
  33. data/lib/spec/runner/execution_context.rb +15 -0
  34. data/lib/spec/runner/instance_exec.rb +15 -0
  35. data/lib/spec/runner/kernel_ext.rb +6 -0
  36. data/lib/spec/runner/option_parser.rb +41 -0
  37. data/lib/spec/runner/rdoc_formatter.rb +17 -0
  38. data/lib/spec/runner/simple_text_reporter.rb +92 -0
  39. data/lib/spec/runner/specification.rb +42 -0
  40. data/lib/spec/tool/command_line.rb +39 -0
  41. data/lib/spec/tool/test_unit_translator.rb +112 -0
  42. data/lib/spec/version.rb +13 -0
  43. data/test/spec/api/helper/arbitrary_predicate_test.rb +121 -0
  44. data/test/spec/api/helper/containment_test.rb +117 -0
  45. data/test/spec/api/helper/equality_test.rb +46 -0
  46. data/test/spec/api/helper/identity_test.rb +68 -0
  47. data/test/spec/api/helper/raising_test.rb +50 -0
  48. data/test/spec/api/helper/regex_matching_test.rb +38 -0
  49. data/test/spec/api/helper/should_satisfy_test.rb +37 -0
  50. data/test/spec/api/helper/throwing_test.rb +56 -0
  51. data/test/spec/api/helper/true_false_special_case_test.rb +87 -0
  52. data/test/spec/api/helper/typing_test.rb +107 -0
  53. data/test/spec/api/mock_test.rb +161 -0
  54. data/test/spec/runner/backtrace_tweaker_test.rb +20 -0
  55. data/test/spec/runner/context_runner_test.rb +19 -0
  56. data/test/spec/runner/context_test.rb +29 -0
  57. data/test/spec/runner/execution_context_test.rb +13 -0
  58. data/test/spec/runner/option_parser_test.rb +50 -0
  59. data/test/spec/runner/rdoc_formatter_test.rb +23 -0
  60. data/test/spec/runner/simple_text_reporter_test.rb +128 -0
  61. data/test/spec/runner/specification_test.rb +70 -0
  62. data/test/spec/tool/command_line_test.rb +22 -0
  63. data/test/spec/tool/test_unit_api_spec.rb +61 -0
  64. data/test/spec/tool/test_unit_api_test.rb +61 -0
  65. data/test/spec/tool/test_unit_translator_test.rb +29 -0
  66. data/test/test_helper.rb +8 -0
  67. metadata +89 -67
  68. data/examples/add_specification_spec.rb +0 -15
  69. data/examples/craps.rb +0 -15
  70. data/examples/craps_spec.rb +0 -105
  71. data/examples/dsl_spec.rb +0 -8
  72. data/examples/movie.rb +0 -7
  73. data/examples/movie_list.rb +0 -19
  74. data/examples/movie_spec.rb +0 -37
  75. data/lib/spec/collector.rb +0 -17
  76. data/lib/spec/context.rb +0 -89
  77. data/lib/spec/dsl.rb +0 -23
  78. data/lib/spec/gui_runner.rb +0 -59
  79. data/lib/spec/mock.rb +0 -183
  80. data/lib/spec/text_runner.rb +0 -75
  81. data/test/collection_owner.rb +0 -48
  82. data/test/context_fixtures_test.rb +0 -71
  83. data/test/context_run_test.rb +0 -174
  84. data/test/dsl_test.rb +0 -48
  85. data/test/error_reporting_test.rb +0 -225
  86. data/test/expectations_for_should_have_test.rb +0 -144
  87. data/test/expectations_test.rb +0 -592
  88. data/test/get_classes.rb +0 -6
  89. data/test/gui_runner_test.rb +0 -162
  90. data/test/mock_test.rb +0 -157
  91. data/test/spec_collection_test.rb +0 -39
  92. data/test/specification_addition_test.rb +0 -29
  93. data/test/specification_identification_test.rb +0 -71
  94. data/test/text_runner_test.rb +0 -146
@@ -1,37 +0,0 @@
1
- require 'spec'
2
- require 'movie'
3
- require 'movie_list'
4
-
5
- class EmptyMovieList < Spec::Context
6
-
7
- def setup
8
- @list = MovieList.new
9
- end
10
-
11
- def should_have_size_of_0
12
- @list.size.should.equal 0
13
- end
14
-
15
- def should_not_include_star_wars
16
- @list.should.not.include "Star Wars"
17
- end
18
-
19
- end
20
-
21
- class OneMovieList < Spec::Context
22
-
23
- def setup
24
- @list = MovieList.new
25
- star_wars = Movie.new "Star Wars"
26
- @list.add star_wars
27
- end
28
-
29
- def should_have_size_of_1
30
- @list.size.should.equal 1
31
- end
32
-
33
- def should_include_star_wars
34
- @list.should.include "Star Wars"
35
- end
36
-
37
- end
@@ -1,17 +0,0 @@
1
- require 'spec'
2
-
3
-
4
- module Spec
5
- class Collector
6
-
7
- def self.collection
8
- collection = []
9
- ObjectSpace.each_object(Class) do |cls|
10
- collection << cls.collection if cls < Spec::Context
11
- end
12
- collection.flatten
13
- end
14
-
15
- end
16
- end
17
-
@@ -1,89 +0,0 @@
1
- require 'spec'
2
-
3
- module Spec
4
- # TODO: Could we try to make this a mixin (Module) instead? It would make it easier to
5
- # create extensions that can be mixed and matched (AH).
6
- class Context
7
-
8
- def initialize(specification=nil)
9
- @specification = specification
10
- @mocks = []
11
- end
12
-
13
- def setup
14
- end
15
-
16
- def teardown
17
- end
18
-
19
- # Creates a new named mock that will be automatically verified after #teardown
20
- # has run. By using this method instead of Mock#new you don't have to worry about
21
- # forgetting to verify your mocks.
22
- def mock(name)
23
- mock = Mock.new(name)
24
- @mocks << mock
25
- mock
26
- end
27
-
28
- # Immediately violates the current specification with +message+.
29
- def violated(message="")
30
- raise Spec::Exceptions::ExpectationNotMetError.new(message)
31
- end
32
-
33
- def self.collection
34
- specs = []
35
- self.specifications.each do |spec|
36
- specs << self.new(spec.to_sym)
37
- end
38
-
39
- return specs
40
- end
41
-
42
- def run(result_listener)
43
- result = false
44
-
45
- result_listener.spec(@specification)
46
- setup
47
- begin
48
- __send__(@specification)
49
- result_listener.pass(@specification)
50
- rescue Exception
51
- result_listener.failure(@specification, $!)
52
- ensure
53
- begin
54
- teardown
55
- verify_mocks
56
- rescue Exception
57
- result_listener.failure(@specification, $!)
58
- end
59
- end
60
-
61
- return result
62
- end
63
-
64
- def self.add_specification(name, &block)
65
- self.send(:define_method, name.to_sym, Proc.new { || block.call })
66
- end
67
-
68
- private
69
-
70
- def self.my_methods
71
- self.instance_methods - self.superclass.instance_methods
72
- end
73
-
74
- def self.specification_name?(name)
75
- return false unless self.new.method(name).arity == 0
76
- return false if name[0..0] == '_'
77
- true
78
- end
79
-
80
- def self.specifications
81
- return self.my_methods.select {|spec| self.specification_name?(spec)}
82
- end
83
-
84
- def verify_mocks
85
- @mocks.each{|m| m.__verify}
86
- end
87
-
88
- end
89
- end
@@ -1,23 +0,0 @@
1
- require 'spec'
2
-
3
- module DSLExtensions
4
-
5
- def context(name)
6
- eval "$#{name} = Class.new(Spec::Context)"
7
- $current_context = eval "$#{name}"
8
- end
9
-
10
- def specification(name, &block)
11
- $default_context ||= Class.new(Spec::Context)
12
- $current_context = $default_context if $current_context.nil?
13
-
14
- $current_context.add_specification(name.to_sym, &block)
15
- end
16
-
17
- end
18
-
19
- class Object
20
- include DSLExtensions
21
- end
22
-
23
- alias example specification if ENV['USER'] == 'marick'
@@ -1,59 +0,0 @@
1
- require 'socket'
2
- @socket
3
- module Spec
4
- class GuiRunner
5
-
6
- def initialize(port)
7
- @failures = Array.new
8
- @specification_count = 0
9
- @failure_count = 0
10
- @failed = false
11
- @socket = TCPSocket.new("127.0.0.1", port)
12
- @socket << "connected\n"
13
- end
14
-
15
- def run(context_or_collection = Spec::Collector)
16
- specs = context_or_collection.collection
17
- start_run specs.size
18
- specs.each {|spec| spec.run(self)}
19
- end_run
20
- @socket.shutdown
21
- end
22
-
23
- def spec(spec)
24
- @failed = false
25
- end
26
-
27
- def pass(spec)
28
- @socket << "passed\n"
29
- end
30
-
31
- def failure(spec, exception)
32
- return if @failed
33
- @socket << "failed\n"
34
- @failed = true
35
- dump_failure(exception)
36
- end
37
-
38
- def start_run(number_of_specs)
39
- @socket << "start #{number_of_specs.to_i}\n"
40
- end
41
-
42
- def end_run
43
- @socket << "end\n"
44
- end
45
-
46
- def dump_failure(exception)
47
- @socket << "#{exception.message} (#{exception.class.name})\n"
48
- dump_backtrace(exception.backtrace)
49
- @socket << "!\n"
50
- end
51
-
52
- def dump_backtrace(trace)
53
- lines = trace.reject {|line| line.include? "lib/spec"}.reject {|line | line.include? "./spec:"}
54
- @socket << lines.join("\n")
55
- @socket << "\n"
56
- end
57
-
58
- end
59
- end
@@ -1,183 +0,0 @@
1
- require 'spec'
2
-
3
- class Mock
4
-
5
- DEFAULT_OPTIONS = {
6
- :null_object => false
7
- }
8
- # Creates a new mock with a +name+ (that will be used in error messages only)
9
- # Options:
10
- # * :null_object - if true, the mock object acts as a forgiving null object allowing any message to be sent to it.
11
- def initialize(name, options={})
12
- @name = name
13
- @options = DEFAULT_OPTIONS.dup.merge(options)
14
- @expectations = []
15
- end
16
-
17
- # AH: How about renaming this to should_receive. This would be:
18
- # * well aligned with the rest of the API (should)
19
- # * emphasize the dynamic oo lingo from smalltalk using 'message' instead of 'method'
20
- def should_receive(sym, &block)
21
- expected_from = caller(1)[0]
22
- expectation = MessageExpectation.new(@name, expected_from, sym, block_given? ? block : nil)
23
- @expectations << expectation
24
- expectation
25
- end
26
-
27
- def __verify
28
- @expectations.each do |expectation|
29
- expectation.verify_messages_received
30
- end
31
- end
32
-
33
- def method_missing(sym, *args, &block)
34
- # TODO: use find_expectation(sym, args) which will lookup based on sym, args and strict mode.
35
- if expectation = find_matching_expectation(sym, *args)
36
- expectation.verify_message(args, block)
37
- else
38
- begin
39
- # act as null object if method is missing and we ignore them. return value too!
40
- @options[:null_object] ? self : super(sym, *args, &block)
41
- rescue NoMethodError
42
- raise Spec::Exceptions::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with " + (args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", "))
43
- end
44
- end
45
- end
46
-
47
- private
48
-
49
- def find_matching_expectation(sym, *args)
50
- expectation = @expectations.find {|expectation| expectation.matches(sym, args)}
51
- end
52
-
53
- end
54
-
55
- # Represents the expection of the reception of a message
56
- class MessageExpectation
57
-
58
- def initialize(mock_name, expected_from, sym, block)
59
- @mock_name = mock_name
60
- @expected_from = expected_from
61
- @sym = sym
62
- @method_block = block
63
- @block = proc {}
64
- @received_count = 0
65
- @expected_received_count = 1
66
- @expected_params = nil
67
- @consecutive = false
68
- end
69
-
70
- def matches(sym, args)
71
- @sym == sym and (@expected_params.nil? or @expected_params == args)
72
- end
73
-
74
- # This method is called at the end of a spec, after teardown.
75
- def verify_messages_received
76
- # TODO: this doesn't provide good enough error messages to fix the error.
77
- # Error msg should tell exactly what went wrong. (AH).
78
-
79
- return if @expected_received_count == -2
80
- return if (@expected_received_count == -1) && (@received_count > 0)
81
- return if @expected_received_count == @received_count
82
-
83
- expected_signature = nil
84
- if @expected_params.nil?
85
- expected_signature = @sym
86
- else
87
- params = @expected_params.collect{|param| "<#{param}:#{param.class.name}>"}.join(", ")
88
- expected_signature = "#{@sym}(#{params})"
89
- end
90
-
91
- count_message = "{@expected_received_count} times"
92
- count_message = "at least once" if (@expected_received_count == -1)
93
- count_message = "never" if (@expected_received_count == 0)
94
- count_message = "once" if (@expected_received_count == 1)
95
- count_message = "twice" if (@expected_received_count == 2)
96
-
97
- message = "#{@expected_from}: Mock '#{@mock_name}' expected #{expected_signature} #{count_message}, but received it #{@received_count} times"
98
- raise Spec::Exceptions::MockExpectationError, message
99
- end
100
-
101
- # This method is called when a method is invoked on a mock
102
- def verify_message(args, block)
103
- unless @method_block.nil?
104
- begin
105
- result = @method_block.call(*args)
106
- rescue Spec::Exceptions::ExpectationNotMetError => detail
107
- raise Spec::Exceptions::MockExpectationError, "Call expectation violated with: " + $!
108
- end
109
- @received_count += 1
110
- return result
111
- end
112
-
113
- unless @expected_params.nil? or @expected_params == args
114
- raise Spec::Exceptions::MockExpectationError,
115
- "#{@sym}: Parameter mismatch: Expected <#{@expected_params}>, got <#{args}>"
116
- end
117
- args << block unless block.nil?
118
- @received_count += 1
119
- value = @block.call(*args)
120
-
121
- return value unless @consecutive
122
-
123
- value[[@received_count, value.size].min - 1]
124
- end
125
-
126
- def with(*args)
127
- @expected_params = args
128
- self
129
- end
130
-
131
- def with_no_args
132
- @expected_params = []
133
- self
134
- end
135
-
136
- def with_any_args
137
- @expected_params = nil
138
- self
139
- end
140
-
141
- def at_least_once
142
- @expected_received_count = -1
143
- self
144
- end
145
-
146
- def any_number_of_times
147
- @expected_received_count = -2
148
- self
149
- end
150
-
151
- def never
152
- @expected_received_count = 0
153
- self
154
- end
155
-
156
- def once
157
- @expected_received_count = 1
158
- self
159
- end
160
-
161
- def twice
162
- @expected_received_count = 2
163
- self
164
- end
165
-
166
- def returns(value=nil,&block)
167
- @block = block_given? ? block : proc { value }
168
- end
169
-
170
- def returns_consecutively(value=[nil],&block)
171
- @consecutive = true
172
- @block = block_given? ? block : proc { value }
173
- end
174
-
175
- # this reads better in English IMHO: (AH)
176
- # uri_specs.should_receive(:[]).with(:overview).and_return("http://some.host/look_here/\#{path}")
177
- alias :and_return :returns
178
- alias :and_return_consecutively :returns_consecutively
179
-
180
- end
181
-
182
- class Counter
183
- end
@@ -1,75 +0,0 @@
1
- module Spec
2
- class TextRunner
3
-
4
- def initialize(appendable = $stdout)
5
- @failures = Array.new
6
- @specification_count = 0
7
- @failure_count = 0
8
- @failed = false
9
- @output = appendable
10
- end
11
-
12
- def run(context_or_collection = Spec::Collector)
13
- start_run
14
- context_or_collection.collection.each {|context| context.run(self)}
15
- end_run
16
- end
17
-
18
- def spec(spec)
19
- @specification_count += 1
20
- @failed = false
21
- end
22
-
23
- def pass(spec)
24
- @output << "."
25
- end
26
-
27
- def failure(spec, exception)
28
- @output << "X" unless @failed
29
- @failure_count += 1 unless @failed
30
- @failed = true
31
- @failures << exception
32
- end
33
-
34
- def start_run
35
- @output << "\n"
36
- @start_time = Time.new
37
- end
38
-
39
- def end_run
40
- @end_time = Time.new
41
- @output << "\n\n"
42
-
43
- dump_failures
44
-
45
- dump_duration(@end_time - @start_time)
46
-
47
- dump_counts
48
- end
49
-
50
- def dump_failures
51
- @failures.inject(1) do |index, exception|
52
- @output << index.to_s << ")\n"
53
- @output << "#{exception.message} (#{exception.class.name})\n"
54
- dump_backtrace(exception.backtrace)
55
- index + 1
56
- end
57
- end
58
-
59
- def dump_backtrace(trace)
60
- lines = trace.reject {|line| line.include? "lib/spec"}.reject {|line | line.include? "./spec:"}
61
- @output << lines.join("\n")
62
- @output << "\n\n"
63
- end
64
-
65
- def dump_duration(duration)
66
- @output << "Finished in " << duration.to_s << " seconds\n"
67
- end
68
-
69
- def dump_counts
70
- @output << "\n" << @specification_count.to_s << " specifications, "
71
- @output << @failure_count.to_s << " failures\n"
72
- end
73
-
74
- end
75
- end