flexmock 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,5 +1,12 @@
1
1
  = Changes for FlexMock
2
2
 
3
+ == Version 0.2.1
4
+
5
+ * Added strict mode in record mode interface to facility using known
6
+ good algorithms for comparison testing.
7
+ * Improved the docs and examples. Fixed garbled first example in
8
+ README.
9
+
3
10
  == Version 0.2.0
4
11
 
5
12
  * Added record mode for building expectations.
data/README CHANGED
@@ -3,7 +3,7 @@
3
3
  FlexMock is a simple mock object for unit testing. The interface is
4
4
  simple, but still provides a good bit of flexibility.
5
5
 
6
- Version :: 0.2.0
6
+ Version :: 0.2.1
7
7
 
8
8
  = Links
9
9
 
@@ -40,10 +40,11 @@ Here's the complete example:
40
40
  def test_tempurature_sampler
41
41
  readings = [10, 12, 14]
42
42
  FlexMock.use("temp") do |sensor|
43
- sensor = FlexMock.new
44
43
  sensor.should_receive(:read_temperature).and_return { readings.shift }
45
- sampler = TemperatureSampler.new(sensor)
46
- assert_equal 12, sampler.average_temp
44
+
45
+ sampler = TemperatureSampler.new(sensor)
46
+ assert_equal 12, sampler.average_temp
47
+ end
47
48
  end
48
49
  end
49
50
 
@@ -226,7 +227,7 @@ All the query message must occur before any of the update messages.
226
227
 
227
228
  FlexMock('db').use |db|
228
229
  db.should_receive(:query).and_return([1,2,3]).ordered
229
- db.should_receive(:update).and_return(nil).ordered
230
+ db.should_recieve(:update).and_return(nil).ordered
230
231
  # test code here
231
232
  end
232
233
 
@@ -254,19 +255,45 @@ values to figure out what value to return.
254
255
  # test code here
255
256
  end
256
257
 
257
- === Same as above, but using the record mode interface
258
+ === Same as above, but using the Record Mode interface
259
+
260
+ The record mode interface offers much the same features as the
261
+ +should_receive+ interface introduced so far, but it allows the
262
+ messages to be sent directly to a recording object rather than be
263
+ specified indirectly using a symbol.
258
264
 
259
265
  FlexMock('db').use |db|
260
266
  db.should_expect do |rec|
261
267
  rec.startup.once.ordered
262
268
  rec.query("CPWR") { 12.3 }.once.ordered(:queries)
263
269
  rec.query("MSFT") { 10.0 }.once.ordered(:queries)
264
- rec.query(/^....$/) { 3.3 }.at_least.once.ordered(:queries)
265
- rec.finish.once.ordered
270
+ rec.query("^....$/) { 3.3 }.at_least.once.ordered(:queries)
271
+ rec.finish)once.ordered
266
272
  end
267
- # test code here
273
+ # test code here using +db+.
268
274
  end
269
275
 
276
+ === Using Record Mode to record a known, good algorithm for testing
277
+
278
+ Record mode is nice when you have a known, good algorithm that can use
279
+ a recording mock object to record the steps. Then you compare the
280
+ execution of a new algorithm to behavior of the old using the recorded
281
+ expectations in the mock. For this you probably want to put the
282
+ recorder in _strict_ mode so that the recorded expectations use exact
283
+ matching on argument lists, and strict ordering of the method calls.
284
+
285
+ <b>Note:</b> This is most useful when there are no queries on the mock
286
+ objects, because the query responses cannot be programmed into the
287
+ recorder object.
288
+
289
+ FlexMock.use('builder') do |builder|
290
+ builder.should_expect do |rec|
291
+ rec.should_be_strict
292
+ known_good_way_to_build_xml(rec) # record the messages
293
+ end
294
+ new_way_to_build_xml(builder) # compare to new way
295
+ end
296
+
270
297
  === Expect multiple calls, returning a different value each time
271
298
 
272
299
  Sometimes you need to return different values for each call to a
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ require 'rake/testtask'
8
8
 
9
9
  CLOBBER.include("html", 'pkg')
10
10
 
11
- PKG_VERSION = '0.2.0'
11
+ PKG_VERSION = '0.2.1'
12
12
 
13
13
  PKG_FILES = FileList[
14
14
  '[A-Z]*',
data/lib/flexmock.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  #---
4
- # Copyright 2003, 2004, 2005 by Jim Weirich (jim@weirichhouse.org).
4
+ # Copyright 2003, 2004, 2005, 2006 by Jim Weirich (jim@weirichhouse.org).
5
5
  # All rights reserved.
6
6
 
7
7
  # Permission is granted for use, copying, modification, distribution,
@@ -213,8 +213,16 @@ class FlexMock
213
213
  end
214
214
 
215
215
  # Invoke the expectations for a given set of arguments.
216
+ #
217
+ # First, look for an expectation that matches the arguements and
218
+ # is eligible to be called. Failing that, look for a expectation
219
+ # that matches teh arguments (at this point it will be ineligible,
220
+ # but at least we will get a good failure message). Finally,
221
+ # check for expectations that don't have any argument matching
222
+ # criteria.
216
223
  def call(*args)
217
- exp = @expectations.find { |e| e.match_args(args) } ||
224
+ exp = @expectations.find { |e| e.match_args(args) && e.eligible? } ||
225
+ @expectations.find { |e| e.match_args(args) } ||
218
226
  @expectations.find { |e| e.expected_args.nil? }
219
227
  FlexMock.check("no matching handler found for " +
220
228
  FlexMock.format_args(@sym, args)) { ! exp.nil? }
@@ -315,6 +323,13 @@ class FlexMock
315
323
  @exp = expectation
316
324
  @limit = limit
317
325
  end
326
+
327
+ # If the expectation has been called +n+ times, is it still
328
+ # eligible to be called again? The default answer compares n to
329
+ # the established limit.
330
+ def eligible?(n)
331
+ n < @limit
332
+ end
318
333
  end
319
334
 
320
335
  ####################################################################
@@ -340,6 +355,14 @@ class FlexMock
340
355
  "Method '#{@exp}' should be called at least #{@limit} times,\n" +
341
356
  "only called #{n} times"
342
357
  end
358
+
359
+ # If the expectation has been called +n+ times, is it still
360
+ # eligible to be called again? Since this validator only
361
+ # establishes a lower limit, not an upper limit, then the answer
362
+ # is always true.
363
+ def eligible?(n)
364
+ true
365
+ end
343
366
  end
344
367
 
345
368
  ####################################################################
@@ -396,6 +419,12 @@ class FlexMock
396
419
  @return_block.call(*args)
397
420
  end
398
421
 
422
+ # Is this expectation eligible to be called again? It is eligible
423
+ # only if all of its count validators agree that it is eligible.
424
+ def eligible?
425
+ @count_validators.all? { |v| v.eligible?(@actual_count) }
426
+ end
427
+
399
428
  # Validate that the order
400
429
  def validate_order
401
430
  return if @order_number.nil?
@@ -569,15 +598,53 @@ class FlexMock
569
598
  # mock object.
570
599
  #
571
600
  class Recorder
601
+ include FlexMock::ArgumentTypes
602
+
572
603
  # Create a method recorder for the mock +mock+.
573
604
  def initialize(mock)
574
605
  @mock = mock
606
+ @strict = false
607
+ end
608
+
609
+ # Place the record in strict mode. While recording expectations
610
+ # in strict mode, the following will be true.
611
+ #
612
+ # * All expectations will be expected in the order they were
613
+ # recorded.
614
+ # * All expectations will be expected once.
615
+ # * All arguments will be placed in exact match mode,
616
+ # including regular expressions and class objects.
617
+ #
618
+ # Strict mode is usually used when giving the recorder to a known
619
+ # good algorithm. Strict mode captures the exact sequence of
620
+ # calls and validate that the code under test performs the exact
621
+ # same sequence of calls.
622
+ #
623
+ # The recorder may exit strict mode via a
624
+ # <tt>should_be_strict(false)</tt> call. Non-strict expectations
625
+ # may be recorded at that point, or even explicit expectations
626
+ # (using +should_receieve+) can be specified.
627
+ #
628
+ def should_be_strict(is_strict=true)
629
+ @strict = is_strict
630
+ end
631
+
632
+ # Is the recorder in strict mode?
633
+ def strict?
634
+ @strict
575
635
  end
576
636
 
577
637
  # Record an expectation for receiving the method +sym+ with the
578
638
  # given arguments.
579
639
  def method_missing(sym, *args, &block)
580
- @mock.should_receive(sym).and_return(&block).with(*args)
640
+ expectation = @mock.should_receive(sym).and_return(&block)
641
+ if @strict
642
+ args = args.collect { |arg| eq(arg) }
643
+ expectation.with(*args).ordered.once
644
+ else
645
+ expectation.with(*args)
646
+ end
647
+ expectation
581
648
  end
582
649
  end
583
650
 
@@ -106,4 +106,55 @@ class TestRecordMode < Test::Unit::TestCase
106
106
  end
107
107
  end
108
108
 
109
+ def test_strict_record_mode_requires_exact_argument_matches
110
+ assert_fails do
111
+ FlexMock.use("mock") do |mock|
112
+ mock.should_expect do |rec|
113
+ rec.should_be_strict
114
+ rec.f(Integer)
115
+ end
116
+ mock.f(3)
117
+ end
118
+ end
119
+ end
120
+
121
+ def test_strict_record_mode_requires_exact_ordering
122
+ assert_fails do
123
+ FlexMock.use("mock") do |mock|
124
+ mock.should_expect do |rec|
125
+ rec.should_be_strict
126
+ rec.f(1)
127
+ rec.f(2)
128
+ end
129
+ mock.f(2)
130
+ mock.f(1)
131
+ end
132
+ end
133
+ end
134
+
135
+ def test_strict_record_mode_requires_once
136
+ assert_fails do
137
+ FlexMock.use("mock") do |mock|
138
+ mock.should_expect do |rec|
139
+ rec.should_be_strict
140
+ rec.f(1)
141
+ end
142
+ mock.f(1)
143
+ mock.f(1)
144
+ end
145
+ end
146
+ end
147
+
148
+ def test_strict_record_mode_can_not_fail
149
+ FlexMock.use("mock") do |mock|
150
+ mock.should_expect do |rec|
151
+ rec.should_be_strict
152
+ rec.f(Integer)
153
+ rec.f(2)
154
+ end
155
+ mock.f(Integer)
156
+ mock.f(2)
157
+ end
158
+ end
159
+
109
160
  end
@@ -507,6 +507,25 @@ class TestFlexMockShoulds < Test::Unit::TestCase
507
507
  assert_equal 'f(1, "two", /^3$/)', exp.to_s
508
508
  end
509
509
 
510
+ def test_explicit_ordering_with_limits_allow_multiple_return_values
511
+ FlexMock.use('mock') do |m|
512
+ m.should_receive(:f).with(2).once.and_return { :first_time }
513
+ m.should_receive(:f).with(2).twice.and_return { :second_or_third_time }
514
+ m.should_receive(:f).with(2).and_return { :forever }
515
+
516
+ assert_equal :first_time, m.f(2)
517
+ assert_equal :second_or_third_time, m.f(2)
518
+ assert_equal :second_or_third_time, m.f(2)
519
+ assert_equal :forever, m.f(2)
520
+ assert_equal :forever, m.f(2)
521
+ assert_equal :forever, m.f(2)
522
+ assert_equal :forever, m.f(2)
523
+ assert_equal :forever, m.f(2)
524
+ assert_equal :forever, m.f(2)
525
+ assert_equal :forever, m.f(2)
526
+ end
527
+ end
528
+
510
529
  def assert_failure
511
530
  assert_raises(Test::Unit::AssertionFailedError) do yield end
512
531
  end
metadata CHANGED
@@ -1,9 +1,9 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11.6
2
+ rubygems_version: 0.8.11.5
3
3
  specification_version: 1
4
4
  name: flexmock
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.0
6
+ version: 0.2.1
7
7
  date: 2006-03-21 00:00:00 -05:00
8
8
  summary: Simple and Flexible Mock Objects for Testing
9
9
  require_paths:
@@ -32,8 +32,8 @@ files:
32
32
  - Rakefile
33
33
  - README
34
34
  - lib/flexmock.rb
35
- - test/test_record_mode.rb
36
35
  - test/test_should_receive.rb
36
+ - test/test_record_mode.rb
37
37
  - test/test_samples.rb
38
38
  - test/test_mock.rb
39
39
  - test/test_naming.rb