matahari 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|