rspec 0.4.0 → 0.5.0

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