matahari 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +20 -4
- data/lib/matahari.rb +4 -9
- data/lib/matahari/adapters/matahari_methods.rb +9 -0
- data/lib/matahari/adapters/rspec.rb +18 -0
- data/lib/matahari/adapters/test_unit.rb +17 -0
- data/lib/matahari/debriefing.rb +10 -0
- data/lib/matahari/spy.rb +18 -3
- data/lib/matahari/version.rb +3 -0
- metadata +56 -71
- data/lib/matahari/rspec/matchers.rb +0 -10
- data/spec/debriefing_spec.rb +0 -86
- data/spec/spec_helper.rb +0 -2
- data/spec/spy_spec.rb +0 -49
- data/test/spy_test.rb +0 -16
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= matahari
|
2
2
|
|
3
|
-
*
|
3
|
+
* http://tomstuart.co.uk/2011/06/05/mocks-suck-matahari-sucks-less.html
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
@@ -10,8 +10,7 @@ It is designed to allow you to test interactions between objects *without* requi
|
|
10
10
|
you to specify all method calls, including uninteresting ones.
|
11
11
|
|
12
12
|
== SYNOPSIS:
|
13
|
-
|
14
|
-
require 'matahari'
|
13
|
+
Matahari allows you to do this (RSpec example)
|
15
14
|
|
16
15
|
describe "my object" do
|
17
16
|
obj = MyAwesomeObject.new
|
@@ -23,7 +22,24 @@ you to specify all method calls, including uninteresting ones.
|
|
23
22
|
collaborator.should have_received(3.times).some_interesting_method("Some", "arguments")
|
24
23
|
end
|
25
24
|
|
26
|
-
See also the cucumber
|
25
|
+
See also the cucumber features, easily viewable at http://relishapp.com/mortice/matahari
|
26
|
+
|
27
|
+
== USING:
|
28
|
+
|
29
|
+
=== RSpec
|
30
|
+
|
31
|
+
In your spec_helper, include this:
|
32
|
+
|
33
|
+
RSpec.configure do |config|
|
34
|
+
config.include Matahari::Adapters::RSpec
|
35
|
+
end
|
36
|
+
|
37
|
+
=== test/unit
|
38
|
+
In your test_helper, include this:
|
39
|
+
|
40
|
+
class Test::Unit::TestCase
|
41
|
+
include Matahari::Adapters::TestUnit
|
42
|
+
end
|
27
43
|
|
28
44
|
== CONTEXT:
|
29
45
|
|
data/lib/matahari.rb
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__)) unless
|
2
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
|
-
module Matahari
|
5
|
-
VERSION = '0.1.1'
|
6
|
-
end
|
7
|
-
|
8
4
|
require 'matahari/spy'
|
9
5
|
require 'matahari/debriefing'
|
10
|
-
require 'matahari/
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
6
|
+
require 'matahari/adapters/matahari_methods'
|
7
|
+
require 'matahari/adapters/rspec'
|
8
|
+
require 'matahari/adapters/test_unit'
|
9
|
+
require 'matahari/version'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Matahari
|
2
|
+
module Adapters
|
3
|
+
module RSpec
|
4
|
+
include Matahari::Adapters::MatahariMethods
|
5
|
+
|
6
|
+
def have_received(times = nil)
|
7
|
+
if times
|
8
|
+
@calls_expected = 0
|
9
|
+
times.each { @calls_expected+= 1 }
|
10
|
+
|
11
|
+
Debriefing.new(@calls_expected)
|
12
|
+
else
|
13
|
+
Debriefing.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Matahari
|
2
|
+
module Adapters
|
3
|
+
module TestUnit
|
4
|
+
include Matahari::Adapters::MatahariMethods
|
5
|
+
|
6
|
+
def assert_received(subject, &block)
|
7
|
+
result = block.call
|
8
|
+
assert result.matches?(subject), result.failure_message_for_should
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_not_received(subject, &block)
|
12
|
+
result = block.call
|
13
|
+
assert !result.matches?(subject), result.failure_message_for_should_not
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/matahari/debriefing.rb
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
class Debriefing
|
2
|
+
|
3
|
+
#TODO I can't work out how to disentangle the 2 responsibilities of this class:
|
4
|
+
#1. Inspecting and acting on spy invocations
|
5
|
+
#2. Presenting the results of those inspections.
|
6
|
+
#
|
7
|
+
#One to revisit later when my head is less befuddled.
|
8
|
+
|
2
9
|
def initialize(expected_call_count = nil)
|
3
10
|
@expected_call_count = expected_call_count
|
4
11
|
end
|
@@ -23,6 +30,9 @@ class Debriefing
|
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
33
|
+
#Allows chaining of method calls following has_received?/should have_received,
|
34
|
+
#e.g. spy.should_have received.some_method, where #some_method is handled by
|
35
|
+
#method_missing, its arguments and name being stored until #matches? is called.
|
26
36
|
def method_missing(sym, *args, &block)
|
27
37
|
@call_to_verify = sym
|
28
38
|
@args_to_verify = args
|
data/lib/matahari/spy.rb
CHANGED
@@ -5,12 +5,23 @@ class Spy
|
|
5
5
|
@name = name if name
|
6
6
|
@invocations = []
|
7
7
|
@stubbed_calls = {}
|
8
|
+
self.class.instance_methods.each do |meth|
|
9
|
+
next if [:define_method, :stubs, :method_missing, :record_invocation].include?(meth)
|
10
|
+
end
|
11
|
+
class << self
|
12
|
+
instance_methods.each do |meth|
|
13
|
+
next if [:name, :define_method, :stubs, :method_missing, :record_invocation, :invocations, :has_received?, :object_id, :respond_to?, :respond_to_missing?, :instance_eval, :instance_exec, :class_eval, :__send__, :send, :should, :should_not].include?(meth)
|
14
|
+
undef_method(meth)
|
15
|
+
end
|
16
|
+
end
|
8
17
|
end
|
9
18
|
|
19
|
+
#When a given method call, sym, is invoked on self, call block and return its result
|
10
20
|
def stubs(sym, &block)
|
11
21
|
@stubbed_calls[sym] = block
|
12
22
|
end
|
13
23
|
|
24
|
+
#Captures the details of any method call and store for later inspection
|
14
25
|
def method_missing(sym, *args, &block)
|
15
26
|
if @verifying
|
16
27
|
raise
|
@@ -20,12 +31,16 @@ class Spy
|
|
20
31
|
end
|
21
32
|
end
|
22
33
|
|
34
|
+
#Pass an iterator to this method to specify the number of times the method should
|
35
|
+
#have been called. E.g. spy.has_received?(3.times). While other iterators might work,
|
36
|
+
#the idea is to allow this nice DSL-ish way of asserting on the number of calls, hence
|
37
|
+
#the odd method signature.
|
23
38
|
def has_received?(times=nil)
|
24
39
|
if times
|
25
|
-
|
26
|
-
times.each {
|
40
|
+
calls_expected = 0
|
41
|
+
times.each { calls_expected += 1 }
|
27
42
|
|
28
|
-
Debriefing.new(
|
43
|
+
Debriefing.new(calls_expected)
|
29
44
|
else
|
30
45
|
Debriefing.new
|
31
46
|
end
|
metadata
CHANGED
@@ -1,103 +1,88 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: matahari
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 2
|
10
|
-
version: 0.1.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Tom Stuart
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: rspec
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2157293000 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :development
|
34
|
-
|
35
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2157293000
|
25
|
+
- !ruby/object:Gem::Dependency
|
36
26
|
name: cucumber
|
27
|
+
requirement: &2157292460 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
37
34
|
prerelease: false
|
38
|
-
|
35
|
+
version_requirements: *2157292460
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: aruba
|
38
|
+
requirement: &2157292040 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
version: "0"
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
47
44
|
type: :development
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2157292040
|
47
|
+
description: Matahari provides test spies for Ruby
|
48
|
+
email:
|
49
|
+
- tom@therye.org
|
51
50
|
executables: []
|
52
|
-
|
53
51
|
extensions: []
|
54
|
-
|
55
|
-
|
56
|
-
-
|
57
|
-
|
58
|
-
-
|
59
|
-
- test/spy_test.rb
|
60
|
-
- spec/debriefing_spec.rb
|
61
|
-
- spec/spec_helper.rb
|
62
|
-
- spec/spy_spec.rb
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- lib/matahari/adapters/matahari_methods.rb
|
55
|
+
- lib/matahari/adapters/rspec.rb
|
56
|
+
- lib/matahari/adapters/test_unit.rb
|
63
57
|
- lib/matahari/debriefing.rb
|
64
|
-
- lib/matahari/rspec/matchers.rb
|
65
58
|
- lib/matahari/spy.rb
|
59
|
+
- lib/matahari/version.rb
|
66
60
|
- lib/matahari.rb
|
67
|
-
|
61
|
+
- README.rdoc
|
68
62
|
homepage: https://github.com/mortice/matahari
|
69
63
|
licenses: []
|
70
|
-
|
71
64
|
post_install_message:
|
72
|
-
rdoc_options:
|
65
|
+
rdoc_options:
|
73
66
|
- --main
|
74
67
|
- README.rdoc
|
75
|
-
require_paths:
|
68
|
+
require_paths:
|
76
69
|
- lib
|
77
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
71
|
none: false
|
79
|
-
requirements:
|
80
|
-
- -
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
|
83
|
-
|
84
|
-
- 0
|
85
|
-
version: "0"
|
86
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
77
|
none: false
|
88
|
-
requirements:
|
89
|
-
- -
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
|
92
|
-
segments:
|
93
|
-
- 0
|
94
|
-
version: "0"
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.3.6
|
95
82
|
requirements: []
|
96
|
-
|
97
83
|
rubyforge_project:
|
98
|
-
rubygems_version: 1.
|
84
|
+
rubygems_version: 1.8.5
|
99
85
|
signing_key:
|
100
86
|
specification_version: 3
|
101
87
|
summary: Test spy library, inspired by Mockito and RR
|
102
88
|
test_files: []
|
103
|
-
|
data/spec/debriefing_spec.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
describe Debriefing do
|
3
|
-
it "matches simple invocations" do
|
4
|
-
#we have to use rspec mocks here because testing matahari with matahari
|
5
|
-
#makes my brain hurt
|
6
|
-
|
7
|
-
subject = mock(:subject)
|
8
|
-
debriefing = Debriefing.new
|
9
|
-
|
10
|
-
subject.should_receive(:invocations).and_return([{:method => :one, :args => [[]]}])
|
11
|
-
|
12
|
-
debriefing.one
|
13
|
-
|
14
|
-
debriefing.matches?(subject).should be_true
|
15
|
-
end
|
16
|
-
|
17
|
-
it "matches invocations based on arguments" do
|
18
|
-
subject = mock(:subject)
|
19
|
-
correct_debriefing = Debriefing.new
|
20
|
-
incorrect_debriefing = Debriefing.new
|
21
|
-
|
22
|
-
subject.should_receive(:invocations).twice.and_return([{:method => :one, :args => [["Hello", "goodbye"]]}])
|
23
|
-
|
24
|
-
correct_debriefing.one("Hello", "goodbye")
|
25
|
-
incorrect_debriefing.one("Hello", "goodbye", "Hello again")
|
26
|
-
|
27
|
-
correct_debriefing.matches?(subject).should be_true
|
28
|
-
incorrect_debriefing.matches?(subject).should be_false
|
29
|
-
end
|
30
|
-
|
31
|
-
it "gives a failure message for should when method not called" do
|
32
|
-
subject = mock(:subject)
|
33
|
-
debriefing = Debriefing.new
|
34
|
-
|
35
|
-
subject.should_receive(:invocations).and_return([{:method => :one, :args => [[]]}])
|
36
|
-
subject.should_receive(:name).and_return(:subject)
|
37
|
-
|
38
|
-
debriefing.two
|
39
|
-
|
40
|
-
debriefing.matches?(subject).should be_false
|
41
|
-
|
42
|
-
debriefing.failure_message_for_should.should == "Spy(:subject) expected to receive :two once, received 0 times"
|
43
|
-
end
|
44
|
-
|
45
|
-
it "gives a failure message for should when method called with wrong arguments" do
|
46
|
-
subject = mock(:subject)
|
47
|
-
debriefing = Debriefing.new
|
48
|
-
|
49
|
-
subject.should_receive(:invocations).and_return([{:method => :one, :args => [[]]}])
|
50
|
-
subject.should_receive(:name).and_return(:subject)
|
51
|
-
|
52
|
-
debriefing.one("Hello")
|
53
|
-
|
54
|
-
debriefing.matches?(subject).should be_false
|
55
|
-
|
56
|
-
debriefing.failure_message_for_should.should == "Spy(:subject) expected to receive :one(\"Hello\") once, received 0 times"
|
57
|
-
end
|
58
|
-
|
59
|
-
it "gives a failure message for should when method called wrong number of times" do
|
60
|
-
subject = mock(:subject)
|
61
|
-
debriefing = Debriefing.new(2)
|
62
|
-
|
63
|
-
subject.should_receive(:invocations).and_return([{:method => :one, :args => [[]]}])
|
64
|
-
subject.should_receive(:name).and_return(:subject)
|
65
|
-
|
66
|
-
debriefing.one
|
67
|
-
|
68
|
-
debriefing.matches?(subject).should be_false
|
69
|
-
|
70
|
-
debriefing.failure_message_for_should.should == "Spy(:subject) expected to receive :one twice, received once"
|
71
|
-
end
|
72
|
-
|
73
|
-
it "gives a failure message for should not" do
|
74
|
-
subject = mock(:subject)
|
75
|
-
debriefing = Debriefing.new
|
76
|
-
|
77
|
-
subject.should_receive(:invocations).and_return([{:method => :two, :args => [[]]}])
|
78
|
-
subject.should_receive(:name).and_return(:subject)
|
79
|
-
|
80
|
-
debriefing.two
|
81
|
-
|
82
|
-
debriefing.matches?(subject).should be_true
|
83
|
-
|
84
|
-
debriefing.failure_message_for_should_not.should == "Spy(:subject) expected not to receive :two but received it once"
|
85
|
-
end
|
86
|
-
end
|
data/spec/spec_helper.rb
DELETED
data/spec/spy_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Spy" do
|
4
|
-
it "takes an optional name parameter" do
|
5
|
-
named = Spy.new(:bond)
|
6
|
-
unnamed = Spy.new
|
7
|
-
|
8
|
-
named.name.should == :bond
|
9
|
-
unnamed.name.should == nil
|
10
|
-
end
|
11
|
-
|
12
|
-
context "in the field" do
|
13
|
-
it "remains as a sleeper agent until called upon" do
|
14
|
-
mata_hari = Spy.new(:mata_hari)
|
15
|
-
lambda do
|
16
|
-
mata_hari.one
|
17
|
-
mata_hari.two
|
18
|
-
mata_hari.three
|
19
|
-
end.should_not raise_error NoMethodError
|
20
|
-
end
|
21
|
-
|
22
|
-
it "captures communications" do
|
23
|
-
mata_hari = Spy.new(:mata_hari)
|
24
|
-
|
25
|
-
mata_hari.one
|
26
|
-
mata_hari.two
|
27
|
-
|
28
|
-
mata_hari.invocations.should == [{:method => :one, :args => [[]]}, {:method => :two, :args => [[]]}]
|
29
|
-
end
|
30
|
-
|
31
|
-
it "captures the details of communications" do
|
32
|
-
mata_hari = Spy.new(:mata_hari)
|
33
|
-
|
34
|
-
mata_hari.one
|
35
|
-
mata_hari.two("Hello")
|
36
|
-
|
37
|
-
mata_hari.invocations.should == [{:method => :one, :args => [[]]}, {:method => :two, :args => [["Hello"]]}]
|
38
|
-
end
|
39
|
-
|
40
|
-
it "doesn't stop you stubbing" do
|
41
|
-
mata_hari = Spy.new(:mata_hari)
|
42
|
-
|
43
|
-
mata_hari.stubs(:test) { "Hello" }
|
44
|
-
|
45
|
-
mata_hari.test.should == "Hello"
|
46
|
-
mata_hari.invocations.should == [{:method => :test, :args => [[]]}]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/test/spy_test.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'matahari'
|
3
|
-
|
4
|
-
class SpyTest < Test::Unit::TestCase
|
5
|
-
#minimal test to make sure we stay compatible. For full tests, see spec/
|
6
|
-
def test_matahari_works_with_test_unit
|
7
|
-
mata_hari = spy(:mata_hari)
|
8
|
-
|
9
|
-
mata_hari.one
|
10
|
-
|
11
|
-
#I know this syntax sucks but at least it shows you don't *need* rspec to use matahari.
|
12
|
-
#TODO make an assert_received method for test/unit
|
13
|
-
assert mata_hari.has_received?.one.matches?(mata_hari)
|
14
|
-
assert !mata_hari.has_received?.two.matches?(mata_hari)
|
15
|
-
end
|
16
|
-
end
|