orangutan 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +135 -0
- data/lib/orangutan/chantek.rb +15 -2
- data/lib/orangutan/mock_adapter.rb +5 -0
- metadata +71 -9
- data/README +0 -111
data/README.rdoc
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
= Orangutan
|
2
|
+
|
3
|
+
Orangutan is a library for creating stubs.
|
4
|
+
|
5
|
+
It allows you to create stub objects and to specify methods to return and yield values as well as to raise errors.
|
6
|
+
|
7
|
+
Originally it was intended for use in testing .net code using ironruby. I'm now using it to test pure ruby code as I prefer the syntax over the alternatives.
|
8
|
+
|
9
|
+
At this stage only the simplest of .net clr interfaces can be stubbed. Eventually you should be able to test java classes (with jruby) in exactly the same way.
|
10
|
+
|
11
|
+
Pure stub objects can be created which have no methods - they simply record any method invocations. Methods of existing objects (including classes) can also be stubbed.
|
12
|
+
|
13
|
+
It works by recording all method calls so that assertions can be made about them after the fact and providing a simple
|
14
|
+
dsl for setting up stubbed methods (which can be used as expectations to assert on later).
|
15
|
+
|
16
|
+
All method invocations are reported to the one central array so you can assert method invocations occur across different objects (not that you should want to).
|
17
|
+
|
18
|
+
Installation:
|
19
|
+
|
20
|
+
gem install orangutan
|
21
|
+
|
22
|
+
Some examples of usage (note that these are not in the context of any testing framework and are intended only to indicate how to use the api):
|
23
|
+
|
24
|
+
require 'orangutan'
|
25
|
+
|
26
|
+
include Orangutan::Chantek
|
27
|
+
|
28
|
+
reset_stubs
|
29
|
+
|
30
|
+
== Creating a pure ruby stub
|
31
|
+
|
32
|
+
@stub = stub :stub
|
33
|
+
|
34
|
+
== Creating a stub that implements a clr interface
|
35
|
+
|
36
|
+
@clr_stub = stub :clr_stub, :clr_interface => System::IDisposable
|
37
|
+
|
38
|
+
== Setting up stub methods that return values
|
39
|
+
|
40
|
+
so_when(:stub).receives(:execute).with(7).return('baz')
|
41
|
+
|
42
|
+
== Setting up stub methods that yield values
|
43
|
+
|
44
|
+
so_when(:stub).receives(:execute).with(7).yield('baz')
|
45
|
+
|
46
|
+
== Setting up stub methods that raise errors
|
47
|
+
|
48
|
+
so_when(:stub).receives(:execute).with(7).raise('baz')
|
49
|
+
|
50
|
+
== checking whether an expectation was met
|
51
|
+
|
52
|
+
expectation = so_when(:stub).receives(:execute).with(7)
|
53
|
+
puts expectation.matched? (=> false)
|
54
|
+
@stub.execute(7)
|
55
|
+
puts expectation.matched? (=> false)
|
56
|
+
|
57
|
+
== setting limits on expectations
|
58
|
+
|
59
|
+
so_when(:stub).receives(:execute).with(7).once
|
60
|
+
so_when(:stub).receives(:execute).with(7).twice
|
61
|
+
so_when(:stub).receives(:execute).with(7).exactly(4).times
|
62
|
+
|
63
|
+
Note that once an expectation has reached its limit, it will no longer match.
|
64
|
+
Expections will match in the order they are specified.
|
65
|
+
This mechanism can be used to set up more complex expected call sequences:
|
66
|
+
|
67
|
+
e1 = so_when(:stub).receives(:execute).with(7).return('ok').once
|
68
|
+
e2 = so_when(:stub).receives(:execute).return('hmm').twice
|
69
|
+
|
70
|
+
puts e1.count (=> nil)
|
71
|
+
puts e2.count (=> nil)
|
72
|
+
@stub.execute(7) (=> 'ok')
|
73
|
+
puts e1.count (=> 1)
|
74
|
+
puts e2.count (=> nil)
|
75
|
+
@stub.execute(7) (=> 'hmm')
|
76
|
+
puts e1.count (=> 1)
|
77
|
+
puts e2.count (=> 1)
|
78
|
+
@stub.execute(7) (=> 'hmm')
|
79
|
+
puts e1.count (=> 1)
|
80
|
+
puts e2.count (=> 2)
|
81
|
+
@stub.execute(7) (=> nil)
|
82
|
+
puts e1.count (=> 1)
|
83
|
+
puts e2.count (=> 2)
|
84
|
+
puts e1.matched? (=> true)
|
85
|
+
puts e2.matched? (=> true)
|
86
|
+
|
87
|
+
== Checking all expectations
|
88
|
+
expectations.any? {|e| !e.matched? }
|
89
|
+
|
90
|
+
== Naming expectations
|
91
|
+
|
92
|
+
Sometimes you'll just want to verify that a stub expectation was actually matched:
|
93
|
+
|
94
|
+
so_when(:stub, :as => :execute_with_seven).receives(:execute).with(7).return('ok').once
|
95
|
+
raise "wasn't matched" unless expectation(:execute_with_seven).matched? # verifying explicitly
|
96
|
+
expectation(:execute_with_seven).should be_matched # verifying expectation (using rspec matchers)
|
97
|
+
|
98
|
+
== Examining recorded method calls
|
99
|
+
|
100
|
+
calls.each {|call| puts "#{call.name}.#{call.method}(#{call.args.join(',')})" }
|
101
|
+
|
102
|
+
Recorded call sequences can also be used for assertions in combination with or instead of checking expectations.
|
103
|
+
|
104
|
+
== Stubbing methods on object instances
|
105
|
+
|
106
|
+
register_object :math, Math # registers the object (this just gives the object a name for referencing in calls)
|
107
|
+
stub_method :math, :cos # replaces the implementation of the cos method with a recorder
|
108
|
+
so_when(:math).receives(:cos).with(0).return("i just can't take it anymore")
|
109
|
+
|
110
|
+
restore_methods # restores any changes made to methods (essential for any class methods that have been stubbed)
|
111
|
+
|
112
|
+
== Registering as a mock framework with rspec
|
113
|
+
|
114
|
+
require 'orangutan/mock_adapter'
|
115
|
+
Spec::Runner.configure do |config|
|
116
|
+
config.mock_with Orangutan::MockAdapter
|
117
|
+
end
|
118
|
+
|
119
|
+
= Questions:
|
120
|
+
|
121
|
+
== Why Orangutan?
|
122
|
+
|
123
|
+
My daughter likes orangutans and I couldn't think of a better name. Both Sumatran and Bornean orangutans are endangered species so even if you intensely dislike this project or its implementation, at least you can be made aware of the plight of these spectacular creatures.
|
124
|
+
|
125
|
+
== Did it have anything to do with Clyde in "Every Which Way But Loose"
|
126
|
+
|
127
|
+
Definately not. What a ridiculous question. I'm appalled.
|
128
|
+
|
129
|
+
== What's Chantek?
|
130
|
+
|
131
|
+
Chantek is a famous orangutan that can solve sudokus and the rubik's cube - http://en.wikipedia.org/wiki/Chantek
|
132
|
+
|
133
|
+
== Why would you create yet another mocking framework?
|
134
|
+
|
135
|
+
Pretty much for the sake of it. Originally it was an IronRuby contribution but Ivan Porto Carrera has provided a much better mocking solution for that in caricature (see http://github.com/casualjim/caricature). Now it's just an extremely interesting exercise in learning about metaprogramming in ruby.
|
data/lib/orangutan/chantek.rb
CHANGED
@@ -7,7 +7,7 @@ require 'orangutan/stub_include'
|
|
7
7
|
|
8
8
|
module Orangutan
|
9
9
|
module Chantek
|
10
|
-
attr_reader :calls, :
|
10
|
+
attr_reader :calls, :expectations
|
11
11
|
|
12
12
|
def call name, method, *args
|
13
13
|
Call.new(name, method, args)
|
@@ -16,6 +16,7 @@ module Orangutan
|
|
16
16
|
def reset_stubs
|
17
17
|
@calls = []
|
18
18
|
@expectations = {}
|
19
|
+
@named_expectations = {}
|
19
20
|
@stubs= {}
|
20
21
|
@events = {}
|
21
22
|
@stubbed_methods = []
|
@@ -92,10 +93,14 @@ module Orangutan
|
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
95
|
-
def so_when name
|
96
|
+
def so_when name, params={}
|
96
97
|
expectations_for_name = @expectations[name]
|
97
98
|
@expectations[name] = expectations_for_name = [] unless expectations_for_name
|
98
99
|
expectation = Orangutan::Expectation.new
|
100
|
+
if params[:as]
|
101
|
+
raise "An expectation called foo_expection was already registered" if @named_expectations[params[:as]]
|
102
|
+
@named_expectations[params[:as]] = expectation
|
103
|
+
end
|
99
104
|
expectations_for_name << expectation
|
100
105
|
expectation
|
101
106
|
end
|
@@ -118,5 +123,13 @@ module Orangutan
|
|
118
123
|
delegates.each { |delegate| delegate.invoke *args } if event_name == event
|
119
124
|
end
|
120
125
|
end
|
126
|
+
|
127
|
+
def expectation name
|
128
|
+
@named_expectations[name]
|
129
|
+
end
|
130
|
+
|
131
|
+
def stub_names
|
132
|
+
@stubs.keys
|
133
|
+
end
|
121
134
|
end
|
122
135
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orangutan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 7
|
9
|
+
version: 0.0.7
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Mark Ryall
|
@@ -9,12 +14,67 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-05-19 00:00:00 +10:00
|
13
18
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rake
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 8
|
30
|
+
- 7
|
31
|
+
version: 0.8.7
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
version: 1.3.0
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: gemesis
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
- 0
|
58
|
+
- 3
|
59
|
+
version: 0.0.3
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: splat
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
- 1
|
72
|
+
- 0
|
73
|
+
version: 0.1.0
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
16
76
|
description: |
|
17
|
-
|
77
|
+
Yet another test spy style mocking library that happens to support clr testing via ironruby
|
18
78
|
|
19
79
|
email: mark@ryall.name
|
20
80
|
executables: []
|
@@ -35,7 +95,7 @@ files:
|
|
35
95
|
- lib/orangutan/stub_base.rb
|
36
96
|
- lib/orangutan/stub_include.rb
|
37
97
|
- lib/orangutan.rb
|
38
|
-
- README
|
98
|
+
- README.rdoc
|
39
99
|
- MIT-LICENSE
|
40
100
|
has_rdoc: true
|
41
101
|
homepage: http://github.com/markryall/orangutan
|
@@ -50,18 +110,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
110
|
requirements:
|
51
111
|
- - ">="
|
52
112
|
- !ruby/object:Gem::Version
|
113
|
+
segments:
|
114
|
+
- 0
|
53
115
|
version: "0"
|
54
|
-
version:
|
55
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
117
|
requirements:
|
57
118
|
- - ">="
|
58
119
|
- !ruby/object:Gem::Version
|
120
|
+
segments:
|
121
|
+
- 0
|
59
122
|
version: "0"
|
60
|
-
version:
|
61
123
|
requirements: []
|
62
124
|
|
63
125
|
rubyforge_project:
|
64
|
-
rubygems_version: 1.3.
|
126
|
+
rubygems_version: 1.3.6
|
65
127
|
signing_key:
|
66
128
|
specification_version: 3
|
67
129
|
summary: A mock objects library
|
data/README
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
Orangutan is a library for creating stubs.
|
2
|
-
|
3
|
-
It allows you to create stub objects and to specify methods to return and yield values as well as to raise errors.
|
4
|
-
|
5
|
-
It can be used in testing .net code using ironruby although at this stage only the simplest of clr interfaces can be stubbed.
|
6
|
-
|
7
|
-
Note that only stub instances of objects are created. It can not create mocks of class methods.
|
8
|
-
|
9
|
-
It works by recording all method calls so that assertions can be made about them after the fact and providing a simple
|
10
|
-
dsl for setting up stubbed methods (which can be used as expectations to assert on later).
|
11
|
-
|
12
|
-
Orangutan can be used with any testing framework and in combination with other mock frameworks.
|
13
|
-
|
14
|
-
Installation:
|
15
|
-
|
16
|
-
gem install orangutan
|
17
|
-
|
18
|
-
Some examples of usage (note that these are not in the context of any testing framework and are intended only to indicate how to use the api):
|
19
|
-
|
20
|
-
require 'orangutan'
|
21
|
-
|
22
|
-
include Orangutan::Chantek
|
23
|
-
|
24
|
-
reset_stubs
|
25
|
-
|
26
|
-
# Creating a pure ruby stub
|
27
|
-
@stub = stub :stub
|
28
|
-
|
29
|
-
# Creating a stub that implements a clr interface
|
30
|
-
@clr_stub = stub :clr_stub, :clr_interface => System::IDisposable
|
31
|
-
|
32
|
-
# Setting up stub methods that return values
|
33
|
-
so_when(:stub).receives(:execute).with(7).return('baz')
|
34
|
-
|
35
|
-
# Setting up stub methods that yield values
|
36
|
-
so_when(:stub).receives(:execute).with(7).yield('baz')
|
37
|
-
|
38
|
-
# Setting up stub methods that raise errors
|
39
|
-
so_when(:stub).receives(:execute).with(7).raise('baz')
|
40
|
-
|
41
|
-
# checking whether an expectation was met
|
42
|
-
expectation = so_when(:stub).receives(:execute).with(7)
|
43
|
-
puts expectation.matched? (=> false)
|
44
|
-
@stub.execute(7)
|
45
|
-
puts expectation.matched? (=> false)
|
46
|
-
|
47
|
-
# setting limits on expectations
|
48
|
-
|
49
|
-
so_when(:stub).receives(:execute).with(7).once
|
50
|
-
so_when(:stub).receives(:execute).with(7).twice
|
51
|
-
so_when(:stub).receives(:execute).with(7).exactly(4).times
|
52
|
-
|
53
|
-
# Note that once an expectation has reached its limit, it will no longer match.
|
54
|
-
# Expections will match in the order they are specified.
|
55
|
-
# This mechanism can be used to set up more complex expected call sequences:
|
56
|
-
|
57
|
-
e1 = so_when(:stub).receives(:execute).with(7).return('ok').once
|
58
|
-
e2 = so_when(:stub).receives(:execute).return('hmm').twice
|
59
|
-
|
60
|
-
puts e1.count (=> nil)
|
61
|
-
puts e2.count (=> nil)
|
62
|
-
@stub.execute(7) (=> 'ok')
|
63
|
-
puts e1.count (=> 1)
|
64
|
-
puts e2.count (=> nil)
|
65
|
-
@stub.execute(7) (=> 'hmm')
|
66
|
-
puts e1.count (=> 1)
|
67
|
-
puts e2.count (=> 1)
|
68
|
-
@stub.execute(7) (=> 'hmm')
|
69
|
-
puts e1.count (=> 1)
|
70
|
-
puts e2.count (=> 2)
|
71
|
-
@stub.execute(7) (=> nil)
|
72
|
-
puts e1.count (=> 1)
|
73
|
-
puts e2.count (=> 2)
|
74
|
-
puts e1.matched? (=> true)
|
75
|
-
puts e2.matched? (=> true)
|
76
|
-
|
77
|
-
# Checking all expectations
|
78
|
-
expectations.any? {|e| !e.matched? }
|
79
|
-
|
80
|
-
# Examining recorded method calls
|
81
|
-
calls.each {|call| puts "#{call.name}.#{call.method}(#{call.args.join(',')})" }
|
82
|
-
|
83
|
-
# Recorded call sequences can also be used for assertions in combination with or instead of checking expectations.
|
84
|
-
|
85
|
-
# Stubbing methods on object instances
|
86
|
-
|
87
|
-
register_object :math, Math # registers the object (this just gives the object a name for referencing in calls)
|
88
|
-
stub_method :math, :cos # replaces the implementation of the cos method with a recorder
|
89
|
-
so_when(:math).receives(:cos).with(0).return("i just can't take it anymore")
|
90
|
-
|
91
|
-
# Registering as a mock framework with rspec
|
92
|
-
|
93
|
-
require 'orangutan/mock_adapter'
|
94
|
-
Spec::Runner.configure do |config|
|
95
|
-
# turn off mocking
|
96
|
-
config.mock_with Orangutan::MockAdapter
|
97
|
-
end
|
98
|
-
|
99
|
-
Questions:
|
100
|
-
|
101
|
-
* Why Orangutan?
|
102
|
-
|
103
|
-
My daughter likes orangutans and I couldn't think of a better name. Both Sumatran and Bornean orangutans are endangered species so even if you intensely dislike this project or its implementation, at least you can be made aware of the plight of these spectacular creatures.
|
104
|
-
|
105
|
-
* Did it have anything to do with Clyde in "Every Which Way But Loose"
|
106
|
-
|
107
|
-
Definately not. What a ridiculous question. I'm appalled.
|
108
|
-
|
109
|
-
* What's Chantek?
|
110
|
-
|
111
|
-
Chantek is a famous orangutan that can solve sudokus and the rubik's cube - http://en.wikipedia.org/wiki/Chantek
|