rr 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ - Fixed compatability issues with Ruby 1.9
2
+ - Aliased any_number_of_times with any_times
3
+ - Better error messages for have_received and assert_received matchers (Patch by Joe Ferris)
4
+ - Better documentation on RR wilcard matchers (Patch by Phil Arnowsky)
5
+
6
+ * 0.7.1
1
7
  - Performance improvements
2
8
 
3
9
  * 0.7.0
data/README.rdoc CHANGED
@@ -301,6 +301,10 @@ In RR, you would do:
301
301
  mock(object).foobar(satisfy {|arg| arg.length == 2})
302
302
  object.foobar("xy")
303
303
 
304
+ ==== Writing your own Argument Matchers
305
+ Writing a custom argument wildcard matcher is not difficult. See
306
+ RR::WildcardMatchers for details.
307
+
304
308
  === Invocation Amount Wildcard Matchers
305
309
  ==== any_times
306
310
  mock(object).method_name(anything).times(any_times) {return_value}
@@ -308,6 +312,7 @@ In RR, you would do:
308
312
  == Special Thanks To
309
313
  With any development effort, there are countless people who have contributed
310
314
  to making it possible. We all are standing on the shoulders of giants.
315
+ * Andreas Haller for patches
311
316
  * Aslak Hellesoy for Developing Rspec
312
317
  * Dan North for syntax ideas
313
318
  * Dave Astels for some BDD inspiration
@@ -325,5 +330,6 @@ to making it possible. We all are standing on the shoulders of giants.
325
330
  * Nick Kallen for documentation suggestions, bug reports, and patches
326
331
  * Nathan Sobo for various ideas and inspiration for cleaner and more expressive code
327
332
  * Parker Thompson for pairing with me
333
+ * Phil Arnowsky for patches
328
334
  * Pivotal Labs for sponsoring RR development
329
335
  * Stephen Baker for Developing Rspec
data/Rakefile CHANGED
@@ -1,5 +1,4 @@
1
1
  require "rake"
2
- require 'rake/gempackagetask'
3
2
  require 'rake/contrib/rubyforgepublisher'
4
3
  require 'rake/clean'
5
4
  require 'rake/testtask'
@@ -15,56 +14,36 @@ task(:spec) do
15
14
  run_suite
16
15
  end
17
16
 
18
- desc "Copies the trunk to a tag with the name of the current release"
19
- task(:tag_release) do
20
- tag_release
21
- end
22
-
23
17
  def run_suite
24
18
  dir = File.dirname(__FILE__)
25
19
  system("ruby #{dir}/spec/spec_suite.rb") || raise("Spec Suite failed")
26
20
  end
27
21
 
28
- PKG_NAME = "rr"
29
- PKG_VERSION = "0.7.1"
30
- PKG_FILES = FileList[
31
- '[A-Z]*',
32
- '*.rb',
33
- 'lib/**/*.rb',
34
- 'spec/**/*.rb'
35
- ]
36
-
37
- spec = Gem::Specification.new do |s|
38
- s.name = PKG_NAME
39
- s.version = PKG_VERSION
40
- s.summary = "RR (Double Ruby) is a double framework that features a rich " <<
41
- "selection of double techniques and a terse syntax. " <<
42
- "http://xunitpatterns.com/Test%20Double.html"
43
- s.test_files = "spec/spec_suite.rb"
44
- s.description = s.summary
45
-
46
- s.files = PKG_FILES.to_a
47
- s.require_path = 'lib'
48
-
49
- s.has_rdoc = true
50
- s.extra_rdoc_files = [ "README.rdoc", "CHANGES" ]
51
- s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
52
-
53
- s.test_files = Dir.glob('spec/*_spec.rb')
54
- s.require_path = 'lib'
55
- s.author = "Brian Takita"
56
- s.email = "brian@pivotallabs.com"
57
- s.homepage = "http://pivotallabs.com"
58
- s.rubyforge_project = "pivotalrb"
59
- end
60
-
61
- Rake::GemPackageTask.new(spec) do |pkg|
62
- pkg.need_zip = true
63
- pkg.need_tar = true
22
+ begin
23
+ require 'jeweler'
24
+ Jeweler::Tasks.new do |s|
25
+ s.name = "rr"
26
+ s.summary = "RR (Double Ruby) is a double framework that features a rich " <<
27
+ "selection of double techniques and a terse syntax. " <<
28
+ "http://xunitpatterns.com/Test%20Double.html"
29
+ s.email = "brian@pivotallabs.com"
30
+ s.homepage = "http://pivotallabs.com"
31
+ s.description = "RR (Double Ruby) is a double framework that features a rich " <<
32
+ "selection of double techniques and a terse syntax. " <<
33
+ "http://xunitpatterns.com/Test%20Double.html"
34
+ s.authors = ["Brian Takita"]
35
+ s.files = FileList[
36
+ '[A-Z]*',
37
+ '*.rb',
38
+ 'lib/**/*.rb',
39
+ 'spec/**/*.rb'
40
+ ].to_a
41
+ s.test_files = Dir.glob('spec/*_spec.rb')
42
+ s.has_rdoc = true
43
+ s.extra_rdoc_files = [ "README.rdoc", "CHANGES" ]
44
+ s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
45
+ s.rubyforge_project = "pivotalrb"
46
+ end
47
+ rescue LoadError
48
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
64
49
  end
65
-
66
- def tag_release
67
- dashed_version = PKG_VERSION.gsub('.', '-')
68
- svn_user = "#{ENV["SVN_USER"]}@" || ""
69
- `svn cp svn+ssh://#{svn_user}rubyforge.org/var/svn/pivotalrb/rr/trunk svn+ssh://#{svn_user}rubyforge.org/var/svn/pivotalrb/rr/tags/REL-#{dashed_version} -m 'Version #{PKG_VERSION}'`
70
- end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 8
4
+ :patch: 0
@@ -32,7 +32,12 @@ module RR
32
32
 
33
33
  def matches?(subject)
34
34
  @verification.subject = subject
35
- RR::Space.instance.recorded_calls.match_error(@verification) ? false : true
35
+ if error = RR::Space.instance.recorded_calls.match_error(@verification)
36
+ @failure_message = error.message
37
+ false
38
+ else
39
+ true
40
+ end
36
41
  end
37
42
 
38
43
  def nil?
@@ -160,6 +160,7 @@ module RR
160
160
  install_method_callback return_value_block
161
161
  self
162
162
  end
163
+ alias_method :any_times, :any_number_of_times
163
164
 
164
165
  # Double#times creates an TimesCalledExpectation of the passed
165
166
  # in number.
@@ -251,7 +252,7 @@ module RR
251
252
  if implementation
252
253
  implemented_by implementation
253
254
  else
254
- implemented_by lambda {value}
255
+ implemented_by proc {value}
255
256
  end
256
257
  self
257
258
  end
@@ -0,0 +1,158 @@
1
+ =begin rdoc
2
+
3
+ = Writing your own custom wildcard matchers.
4
+ Writing new wildcard matchers is not too difficult. If you've ever written
5
+ a custom expectation in RSpec, the implementation is very similar.
6
+
7
+ As an example, let's say that you want a matcher that will match any number
8
+ divisible by a certain integer. In use, it might look like this:
9
+
10
+ # Will pass if BananaGrabber#bunch_bananas is called with an integer
11
+ # divisible by 5.
12
+
13
+ mock(BananaGrabber).bunch_bananas(divisible_by(5))
14
+
15
+ To implement this, we need a class RR::WildcardMatchers::DivisibleBy with
16
+ these instance methods:
17
+
18
+ * ==(other)
19
+ * eql?(other) (usually aliased to #==)
20
+ * inspect
21
+ * wildcard_match?(other)
22
+
23
+ and optionally, a sensible initialize method. Let's look at each of these.
24
+
25
+ === .initialize
26
+
27
+ Most custom wildcard matchers will want to define initialize to store
28
+ some information about just what should be matched. DivisibleBy#initialize
29
+ might look like this:
30
+
31
+ class RR::WildcardMatchers::DivisibleBy
32
+ def initialize(divisor)
33
+ @expected_divisor = divisor
34
+ end
35
+ end
36
+
37
+ === #==(other)
38
+ DivisibleBy#==(other) should return true if other is a wildcard matcher that
39
+ matches the same things as self, so a natural way to write DivisibleBy#== is:
40
+
41
+
42
+ class RR::WildcardMatchers::DivisibleBy
43
+ def ==(other)
44
+ # Ensure that other is actually a DivisibleBy
45
+ return false unless other.is_a?(self.class)
46
+
47
+ # Does other expect to match the same divisor we do?
48
+ self.expected_divisor = other.expected_divisor
49
+ end
50
+ end
51
+
52
+ Note that this implementation of #== assumes that we've also declared
53
+ attr_reader :expected_divisor
54
+
55
+ === #inspect
56
+
57
+ Technically we don't have to declare DivisibleBy#inspect, since inspect is
58
+ defined for every object already. But putting a helpful message in inspect
59
+ will make test failures much clearer, and it only takes about two seconds to
60
+ write it, so let's be nice and do so:
61
+
62
+ class RR::WildcardMatchers::DivisibleBy
63
+ def inspect
64
+ "integer divisible by #{expected.divisor}"
65
+ end
66
+ end
67
+
68
+ Now if we run the example from above:
69
+
70
+ mock(BananaGrabber).bunch_bananas(divisible_by(5))
71
+
72
+ and it fails, we get a helpful message saying
73
+
74
+ bunch_bananas(integer divisible by 5)
75
+ Called 0 times.
76
+ Expected 1 times.
77
+
78
+ === #wildcard_matches?(other)
79
+
80
+ wildcard_matches? is the method that actually checks the argument against the
81
+ expectation. It should return true if other is considered to match,
82
+ false otherwise. In the case of DivisibleBy, wildcard_matches? reads:
83
+
84
+ class RR::WildcardMatchers::DivisibleBy
85
+ def wildcard_matches?(other)
86
+ # If other isn't a number, how can it be divisible by anything?
87
+ return false unless other.is_a?(Numeric)
88
+
89
+ # If other is in fact divisible by expected_divisor, then
90
+ # other modulo expected_divisor should be 0.
91
+
92
+ other % expected_divisor == 0
93
+ end
94
+ end
95
+
96
+ === A finishing touch: wrapping it neatly
97
+
98
+ We could stop here if we were willing to resign ourselves to using
99
+ DivisibleBy this way:
100
+
101
+ mock(BananaGrabber).bunch_bananas(DivisibleBy.new(5))
102
+
103
+ But that's less expressive than the original:
104
+
105
+ mock(BananaGrabber).bunch_bananas(divisible_by(5))
106
+
107
+ To be able to use the convenient divisible_by matcher rather than the uglier
108
+ DivisibleBy.new version, re-open the module RR::Adapters::RRMethods and
109
+ define divisible_by there as a simple wrapper around DivisibleBy.new:
110
+
111
+ module RR::Adapters::RRMethods
112
+ def divisible_by(expected_divisor)
113
+ RR::WildcardMatchers::DivisibleBy.new(expected_divisor)
114
+ end
115
+ end
116
+
117
+ == Recap
118
+
119
+ Here's all the code for DivisibleBy in one place for easy reference:
120
+
121
+ class RR::WildcardMatchers::DivisibleBy
122
+ def initialize(divisor)
123
+ @expected_divisor = divisor
124
+ end
125
+
126
+ def ==(other)
127
+ # Ensure that other is actually a DivisibleBy
128
+ return false unless other.is_a?(self.class)
129
+
130
+ # Does other expect to match the same divisor we do?
131
+ self.expected_divisor = other.expected_divisor
132
+ end
133
+
134
+ def inspect
135
+ "integer divisible by #{expected.divisor}"
136
+ end
137
+
138
+ def wildcard_matches?(other)
139
+ # If other isn't a number, how can it be divisible by anything?
140
+ return false unless other.is_a?(Numeric)
141
+
142
+ # If other is in fact divisible by expected_divisor, then
143
+ # other modulo expected_divisor should be 0.
144
+
145
+ other % expected_divisor == 0
146
+ end
147
+ end
148
+
149
+ module RR::Adapters::RRMethods
150
+ def divisible_by(expected_divisor)
151
+ RR::WildcardMatchers::DivisibleBy.new(expected_divisor)
152
+ end
153
+ end
154
+
155
+ =end
156
+
157
+ module RR::WildcardMatchers
158
+ end
@@ -253,6 +253,26 @@ module RR
253
253
  @result.should be
254
254
  end
255
255
  end
256
+
257
+ describe "that does not match" do
258
+ before do
259
+ @error = Object.new
260
+ @message = 'Verification error message'
261
+ stub(RR::Space.instance.recorded_calls).match_error { @error }
262
+ stub(@error).message { @message }
263
+
264
+ @matcher = InvocationMatcher.new(:foobar)
265
+ @result = @matcher.matches?(Object.new)
266
+ end
267
+
268
+ it "returns false when matching" do
269
+ @result.should_not be
270
+ end
271
+
272
+ it "returns a failure messsage" do
273
+ @matcher.failure_message.should == @message
274
+ end
275
+ end
256
276
  end
257
277
  end
258
278
  end
@@ -15,6 +15,7 @@ class TestUnitBacktraceTest < Test::Unit::TestCase
15
15
  end
16
16
 
17
17
  def test_backtrace_tweaking
18
+ skip "Skipped, because there is no Test::Unit::TestResult in this Test::Unit. Don't worry, this is totally fine." unless defined?(Test::Unit::TestResult)
18
19
  old_result = @_result
19
20
  result = Test::Unit::TestResult.new
20
21
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Takita
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-16 00:00:00 -05:00
12
+ date: 2009-03-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -23,6 +23,7 @@ extra_rdoc_files:
23
23
  - README.rdoc
24
24
  - CHANGES
25
25
  files:
26
+ - VERSION.yml
26
27
  - README.rdoc
27
28
  - Rakefile
28
29
  - CHANGES
@@ -68,6 +69,7 @@ files:
68
69
  - lib/rr/expectations/argument_equality_expectation.rb
69
70
  - lib/rr/expectations/any_argument_expectation.rb
70
71
  - lib/rr/expectations/times_called_expectation.rb
72
+ - lib/rr/wildcard_matchers.rb
71
73
  - lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb
72
74
  - lib/rr/double_definitions/strategies/implementation/reimplementation.rb
73
75
  - lib/rr/double_definitions/strategies/implementation/proxy.rb
@@ -160,6 +162,8 @@ rdoc_options:
160
162
  - README.rdoc
161
163
  - --inline-source
162
164
  - --line-numbers
165
+ - --inline-source
166
+ - --charset=UTF-8
163
167
  require_paths:
164
168
  - lib
165
169
  required_ruby_version: !ruby/object:Gem::Requirement