orangutan 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,59 +1,59 @@
1
- Orangutan is a mocking library.
2
-
3
- It allows you to create stub objects and to setup methods with return, yield and raise behaviours.
4
-
5
- It can be used in testing .net code using ironruby.
6
-
7
- At this stage only the simplest of clr interfaces can be stubbed.
8
-
9
- Note that only stub instances of objects are created. It can not create mocks of class methods.
10
-
11
- It works by recording all method calls so that assertions can be made about them after the fact.
12
-
13
- This means that orangutan can be used with any testing framework and in combination with other mock frameworks.
14
-
15
- Installation:
16
-
17
- gem install markryall-orangutan
18
-
19
- Usage:
20
-
21
- require 'orangutan'
22
- @o = Orangutan::Chantek.new
23
-
24
- # Creating a pure ruby stub
25
- @stub = @orangutan.stub :stub
26
-
27
- # Creating a stub that implements a clr interface
28
- @clr_stub = @orangutan.stub :clr_stub, :clr_interface => System::IDisposable
29
-
30
- # Setting up stub methods that return values
31
- @o.when(:stub).receives(:execute).with(7).return('baz')
32
-
33
- # Setting up stub methods that yield values
34
- @o.when(:stub).receives(:execute).with(7).yield('baz')
35
-
36
- # Setting up stub methods that raise errors
37
- @o.when(:stub).receives(:execute).with(7).raise('baz')
38
-
39
- # Checking recorded method calls
40
- # at this stage you need to scan the array of call structs recorded in @o.calls
41
- @o.calls[0].should == Orangutan::Call.new(:stub, :execute, [7])
42
-
43
- Questions:
44
-
45
- * Why Orangutan?
46
-
47
- 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.
48
-
49
- * Did it have anything to do with Clyde in "Every Which Way But Loose"
50
-
51
- Definately not. What a ridiculous question. I'm appalled.
52
-
53
- * What's Chantek?
54
-
55
- Chantek is a famous orangutan that can solve sudokus and the rubik's cube - http://en.wikipedia.org/wiki/Chantek
56
-
57
- * Why do I not need to register this as a mock framework?
58
-
1
+ Orangutan is a mocking library.
2
+
3
+ It allows you to create stub objects and to setup methods with return, yield and raise behaviours.
4
+
5
+ It can be used in testing .net code using ironruby.
6
+
7
+ At this stage only the simplest of clr interfaces can be stubbed.
8
+
9
+ Note that only stub instances of objects are created. It can not create mocks of class methods.
10
+
11
+ It works by recording all method calls so that assertions can be made about them after the fact.
12
+
13
+ This means that orangutan can be used with any testing framework and in combination with other mock frameworks.
14
+
15
+ Installation:
16
+
17
+ gem install markryall-orangutan
18
+
19
+ Usage:
20
+
21
+ require 'orangutan'
22
+ @o = Orangutan::Chantek.new
23
+
24
+ # Creating a pure ruby stub
25
+ @stub = @orangutan.stub :stub
26
+
27
+ # Creating a stub that implements a clr interface
28
+ @clr_stub = @orangutan.stub :clr_stub, :clr_interface => System::IDisposable
29
+
30
+ # Setting up stub methods that return values
31
+ @o.when(:stub).receives(:execute).with(7).return('baz')
32
+
33
+ # Setting up stub methods that yield values
34
+ @o.when(:stub).receives(:execute).with(7).yield('baz')
35
+
36
+ # Setting up stub methods that raise errors
37
+ @o.when(:stub).receives(:execute).with(7).raise('baz')
38
+
39
+ # Checking recorded method calls
40
+ # at this stage you need to scan the array of call structs recorded in @o.calls
41
+ @o.calls[0].should == Orangutan::Call.new(:stub, :execute, [7])
42
+
43
+ Questions:
44
+
45
+ * Why Orangutan?
46
+
47
+ 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.
48
+
49
+ * Did it have anything to do with Clyde in "Every Which Way But Loose"
50
+
51
+ Definately not. What a ridiculous question. I'm appalled.
52
+
53
+ * What's Chantek?
54
+
55
+ Chantek is a famous orangutan that can solve sudokus and the rubik's cube - http://en.wikipedia.org/wiki/Chantek
56
+
57
+ * Why do I not need to register this as a mock framework?
58
+
59
59
  Most frameworks such as rspec's mocks, mocha and stubba replace methods on existing classes. Because this can't be done with this library - you can only create pure stub objects and setup method behaviours, there's nothing that needs to be undone at the end of a test/example.
data/Rakefile CHANGED
@@ -1,34 +1,34 @@
1
- desc 'build necessary assemblies for tests'
2
- task 'spec/ClassLibrary.dll' => FileList["spec/**/*.cs"] do
3
- system "csc /target:library /out:spec\\ClassLibrary.dll spec\\*.cs"
4
- end
5
-
6
- task :compile => 'spec/ClassLibrary.dll'
7
-
8
- desc 'run specs with bacon on ironruby'
9
- task :bacon => :compile do
10
- system "ibacon -Ispec -a"
11
- end
12
-
13
- (1..4).each do |i|
14
- desc "run spike #{i}"
15
- task "spike#{i}" do
16
- system "ir -I spec -I spikes spikes\\experiment#{i}.rb"
17
- end
18
- end
19
-
20
- begin
21
- require 'jeweler'
22
- Jeweler::Tasks.new do |gemspec|
23
- gemspec.name = "orangutan"
24
- gemspec.summary = "A mock objects library"
25
- gemspec.email = "mark@ryall.name"
26
- gemspec.homepage = "http://github.com/markryall/orangutan"
27
- gemspec.description = "A mocking library that supports creation of ironruby mock objects (in addition to pure ruby ones)"
28
- gemspec.files = FileList["[A-Z]*", "{lib,spec}/**/*.{rb,cs}"]
29
- gemspec.authors = ["Mark Ryall"]
30
- gemspec.rubyforge_project = 'orangutan'
31
- end
32
- rescue LoadError
33
- puts "Jeweler not available. Install it with: sudo gem install jeweler"
34
- end
1
+ desc 'build necessary assemblies for tests'
2
+ task 'spec/ClassLibrary.dll' => FileList["spec/**/*.cs"] do
3
+ system "csc /target:library /out:spec\\ClassLibrary.dll spec\\clr\\*.cs"
4
+ end
5
+
6
+ task :compile => 'spec/ClassLibrary.dll'
7
+
8
+ desc 'run specs with bacon on ironruby'
9
+ task :bacon => :compile do
10
+ system "ibacon -Ispec -a"
11
+ end
12
+
13
+ (1..4).each do |i|
14
+ desc "run spike #{i}"
15
+ task "spike#{i}" do
16
+ system "ir -I spec -I spikes spikes\\experiment#{i}.rb"
17
+ end
18
+ end
19
+
20
+ begin
21
+ require 'jeweler'
22
+ Jeweler::Tasks.new do |gemspec|
23
+ gemspec.name = "orangutan"
24
+ gemspec.summary = "A mock objects library"
25
+ gemspec.email = "mark@ryall.name"
26
+ gemspec.homepage = "http://github.com/markryall/orangutan"
27
+ gemspec.description = "A mocking library that supports creation of ironruby mock objects (in addition to pure ruby ones)"
28
+ gemspec.files = FileList["[A-Z]*", "{lib,spec}/**/*.{rb,cs}"]
29
+ gemspec.authors = ["Mark Ryall"]
30
+ gemspec.rubyforge_project = 'orangutan'
31
+ end
32
+ rescue LoadError
33
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
34
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 2
4
+ :major: 0
data/lib/orangutan.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Orangutan
2
- end
1
+ module Orangutan
2
+ end
3
3
  require 'orangutan/chantek'
@@ -1,68 +1,50 @@
1
- require 'orangutan/clean_slate'
2
- require 'orangutan/expectation'
3
- require 'orangutan/call'
4
-
5
- class Orangutan::Chantek
6
- attr_reader :calls
7
-
8
- def initialize
9
- @calls = []
10
- @expectations = {}
11
- end
12
-
13
- def stub name, params={}
14
- c = Class.new(Orangutan::CleanSlate) do
15
- if params[:clr_interface]
16
- include params[:clr_interface]
17
- params[:clr_interface].to_clr_type.get_methods.each do |m_info|
18
- snake = m_info.name.scan(/[A-Z][a-z0-9]*/).map {|a|a.downcase}.join('_').to_sym
19
- define_method snake do |*args|
20
- yield_container, return_value, raiser = __react__ snake, args
21
- raiser.execute if raiser
22
- yield yield_container.value if yield_container && block_given?
23
- return_value
24
- end
25
- end
26
- end
27
-
28
- def initialize name, parent
29
- @name, @parent = name, parent
30
- end
31
-
32
- def method_missing method, *args
33
- yield_container, return_value, raiser = __react__ method, args
34
- raiser.execute if raiser
35
- yield yield_container.value if yield_container && block_given?
36
- return_value
37
- end
38
-
39
- private
40
-
41
- def __react__ method, args
42
- yield_container, return_value, raiser = nil, nil, nil
43
- @parent.calls << Orangutan::Call.new(@name, method, args)
44
- first_match = @parent.first_match(@name, method, args)
45
- return first_match.yield_container, first_match.return_value, first_match.raiser if first_match
46
- return yield_container, return_value, raiser
47
- end
48
- end
49
- c.new name, self
50
- end
51
-
52
- def when name
53
- expectations_for_name = @expectations[name]
54
- @expectations[name] = expectations_for_name = [] unless expectations_for_name
55
- expectation = Orangutan::Expectation.new
56
- expectations_for_name << expectation
57
- expectation
58
- end
59
-
60
- def first_match name, method, args
61
- expectations_for_name = @expectations[name]
62
- if expectations_for_name
63
- expectations_for_name.each do |expectation|
64
- return expectation if expectation.matches?(method, *args)
65
- end
66
- end
67
- end
1
+ require 'orangutan/stub_base'
2
+ require 'orangutan/expectation'
3
+ require 'orangutan/call'
4
+
5
+ module Orangutan
6
+ class Chantek
7
+ attr_reader :calls
8
+
9
+ def initialize
10
+ @calls = []
11
+ @expectations = {}
12
+ @stubs= {}
13
+ end
14
+
15
+ def stub name, params={}
16
+ return @stubs[name] if @stubs[name]
17
+ c = Class.new(StubBase) do
18
+ if params[:clr_interface]
19
+ include params[:clr_interface]
20
+ params[:clr_interface].to_clr_type.get_methods.each do |m_info|
21
+ snake = m_info.name.scan(/[A-Z][a-z0-9]*/).map {|a|a.downcase}.join('_').to_sym
22
+ define_method snake do |*args|
23
+ yield_container, return_container = __react__(snake, args)
24
+ yield yield_container.value if yield_container && block_given?
25
+ __return__(method, return_container)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ @stubs[name] = c.new(name, self, params[:recursive])
31
+ end
32
+
33
+ def when name
34
+ expectations_for_name = @expectations[name]
35
+ @expectations[name] = expectations_for_name = [] unless expectations_for_name
36
+ expectation = Orangutan::Expectation.new
37
+ expectations_for_name << expectation
38
+ expectation
39
+ end
40
+
41
+ def first_match name, method, args
42
+ expectations_for_name = @expectations[name]
43
+ if expectations_for_name
44
+ expectations_for_name.each do |expectation|
45
+ return expectation if expectation.matches?(method, *args)
46
+ end
47
+ end
48
+ end
49
+ end
68
50
  end
@@ -1,3 +1,32 @@
1
- class Orangutan::CleanSlate
2
- instance_methods.each { |m| undef_method m unless m =~ /^__/ }
1
+ module Orangutan
2
+ class CleanSlate
3
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
4
+
5
+ def initialize name, parent, recursive
6
+ @name, @parent, @recursive = name, parent, recursive
7
+ end
8
+
9
+ def method_missing method, *args
10
+ yield_container, return_container = __react__(method, args)
11
+ yield yield_container.value if yield_container && block_given?
12
+ __return__(method, return_container)
13
+ end
14
+ private
15
+ def __return__ method, return_container
16
+ return return_container.value if return_container
17
+ return @parent.stub(:"@name/method") if @recursive
18
+ nil
19
+ end
20
+
21
+ def __react__ method, args
22
+ yield_container, return_value = nil, nil
23
+ @parent.calls << Orangutan::Call.new(@name, method, args)
24
+ first_match = @parent.first_match(@name, method, args)
25
+ if first_match
26
+ first_match.raiser.execute if first_match.raiser
27
+ yield_container, return_value = first_match.yield_container, first_match.return_value
28
+ end
29
+ return yield_container, return_value
30
+ end
31
+ end
3
32
  end
@@ -1 +1,3 @@
1
- Orangutan::Container = Struct.new(:value)
1
+ module Orangutan
2
+ Container = Struct.new(:value)
3
+ end
@@ -1,37 +1,39 @@
1
- require 'orangutan/raiser'
2
- require 'orangutan/container'
3
-
4
- class Orangutan::Expectation
5
- attr_reader :return_value, :yield_container, :raiser
6
-
7
- def receives method
8
- @method = method
9
- self
10
- end
11
-
12
- def with *args
13
- @args = args
14
- self
15
- end
16
-
17
- def return value
18
- @return_value = value
19
- self
20
- end
21
-
22
- def yield value
23
- @yield_container = Orangutan::Container.new value
24
- self
25
- end
26
-
27
- def raise *args
28
- @raiser = Orangutan::Raiser.new args
29
- self
30
- end
31
-
32
- def matches? method, *args
33
- return false unless method == @method
34
- return true unless @args
35
- @args == args
36
- end
1
+ require 'orangutan/raiser'
2
+ require 'orangutan/container'
3
+
4
+ module Orangutan
5
+ class Expectation
6
+ attr_reader :return_container, :yield_container, :raiser
7
+
8
+ def receives method
9
+ @method = method
10
+ self
11
+ end
12
+
13
+ def with *args
14
+ @args = args
15
+ self
16
+ end
17
+
18
+ def return value
19
+ @return_container = Container.new value
20
+ self
21
+ end
22
+
23
+ def yield value
24
+ @yield_container = Container.new value
25
+ self
26
+ end
27
+
28
+ def raise *args
29
+ @raiser = Raiser.new args
30
+ self
31
+ end
32
+
33
+ def matches? method, *args
34
+ return false unless method == @method
35
+ return true unless @args
36
+ @args == args
37
+ end
38
+ end
37
39
  end
@@ -1,10 +1,10 @@
1
- class Orangutan::Raiser
2
- def initialize args
3
- @args = args
4
- end
5
-
6
- def execute
7
- puts 'RAISING ' + @args.inspect
8
- raise *@args
9
- end
1
+ class Orangutan::Raiser
2
+ def initialize args
3
+ @args = args
4
+ end
5
+
6
+ def execute
7
+ puts 'RAISING ' + @args.inspect
8
+ raise *@args
9
+ end
10
10
  end