stendhal 0.1.4 → 0.1.5

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/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stendhal (0.1.3)
4
+ stendhal (0.1.4)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/Readme.md CHANGED
@@ -10,9 +10,9 @@ development.
10
10
 
11
11
  * Pretty decent reporter with colors
12
12
  * Test doubles and stubs (no partial stubbing yet)
13
+ * Mocks (message expectations)
13
14
  * Nested example groups (declare them with either describe or context)
14
15
  * Pending examples
15
- * Lame reporter (but will get better eventually)
16
16
  * Matchers (use with object.must or object.must_not)
17
17
 
18
18
  eq() / eql()
@@ -86,6 +86,22 @@ development.
86
86
  end
87
87
  end
88
88
 
89
+ describe "Message expectation" do
90
+ it "is declared with expects" do
91
+ string = "my string"
92
+ string.expects(:reverse)
93
+
94
+ string.reverse # Expectation fulfilled!
95
+ end
96
+
97
+ it "is declared with does_not_expect in case it is negative" do
98
+ string = "my string"
99
+ string.does_not_expect(:reverse)
100
+
101
+ string.reverse # Fails!
102
+ end
103
+ end
104
+
89
105
  end
90
106
 
91
107
  ###Running the specs!
@@ -114,7 +130,18 @@ development.
114
130
  * is declared with double as well
115
131
  * can be given stubs
116
132
 
117
- 11 examples, 2 failures, 2 pending
133
+ Message expectation
134
+ * is declared with expects
135
+ * is declared with does_not_expect in case it is negative
136
+
137
+ 13 examples, 3 failures, 2 pending
138
+
139
+ ##Feedback
140
+
141
+ Reporting issues, asking for new features and constructive criticizing can be
142
+ done either through Github issues, the mailing list
143
+ (http://librelist.com/browser/stendhal/) or you can always reach me on twitter
144
+ (I am @txustice). Don't hesitate to tell me anything! :)
118
145
 
119
146
  ##Note on Patches/Pull Requests
120
147
 
@@ -0,0 +1,71 @@
1
+ Feature: Mocks (message expectations)
2
+
3
+ With mocks you can check whether objects receive certain messages.
4
+
5
+ Scenario: declare a message expectation
6
+ Given a directory named "stendhal_project"
7
+ When I cd to "stendhal_project"
8
+ Given a file named "sample_spec.rb" with:
9
+ """
10
+ class MyClass
11
+
12
+ def foo
13
+ end
14
+
15
+ def bar
16
+ foo
17
+ end
18
+
19
+ end
20
+
21
+ describe "bar" do
22
+ it "calls foo" do
23
+ object = MyClass.new
24
+ object.expects(:foo)
25
+
26
+ object.bar
27
+ end
28
+ it "never calls foo" do
29
+ object = MyClass.new
30
+ object.expects(:foo)
31
+ end
32
+ end
33
+ """
34
+ When I run "stendhal sample_spec.rb"
35
+ Then the exit status should be 0
36
+ And the output should contain "2 examples, 1 failure"
37
+ And the output should contain "expected to be sent :foo 1 time, but received it 0 times"
38
+
39
+ Scenario: declare a negative message expectation
40
+ Given a directory named "stendhal_project"
41
+ When I cd to "stendhal_project"
42
+ Given a file named "sample_spec.rb" with:
43
+ """
44
+ class MyClass
45
+
46
+ def foo
47
+ end
48
+
49
+ def bar
50
+ foo
51
+ end
52
+
53
+ end
54
+
55
+ describe "bar" do
56
+ it "calls foo" do
57
+ object = MyClass.new
58
+ object.does_not_expect(:foo)
59
+
60
+ object.bar
61
+ end
62
+ it "never calls foo" do
63
+ object = MyClass.new
64
+ object.does_not_expect(:foo)
65
+ end
66
+ end
67
+ """
68
+ When I run "stendhal sample_spec.rb"
69
+ Then the exit status should be 0
70
+ And the output should contain "2 examples, 1 failure"
71
+ And the output should contain "expected to be sent :foo 0 times, but received it 1 time"
@@ -0,0 +1,3 @@
1
+ class Object
2
+ include Stendhal::Mocks::Mockable
3
+ end
@@ -19,7 +19,9 @@ module Stendhal
19
19
 
20
20
  def run
21
21
  begin
22
+ Stendhal::Mocks::MockVerifier.reset!
22
23
  self.instance_eval(&@block)
24
+ Stendhal::Mocks::MockVerifier.verify!
23
25
  return 0
24
26
  rescue Exceptions::ExpectationNotMet=>e
25
27
  @failed = true
@@ -0,0 +1,71 @@
1
+ module Stendhal
2
+ module Mocks
3
+ class MockVerifier
4
+
5
+ @@verifiers = []
6
+
7
+ attr_reader :expectations
8
+
9
+ def initialize(object)
10
+ @expectations = []
11
+ @object = object
12
+ @@verifiers << self
13
+ end
14
+
15
+ def add_expectation(method)
16
+ @expectations << MessageExpectation.new(method)
17
+ end
18
+
19
+ def add_negative_expectation(method)
20
+ @expectations << MessageExpectation.new(method, :negative => true)
21
+ end
22
+
23
+ def fulfill_expectation(method)
24
+ @expectations.select{|e| e.method == method}.each(&:register_call)
25
+ end
26
+
27
+ def verify!
28
+ expectations.each do |expectation|
29
+ begin
30
+ expectation.verify
31
+ rescue Stendhal::Exceptions::ExpectationNotMet=>e
32
+ raise Stendhal::Exceptions::ExpectationNotMet.new "#{@object} #{e.message}"
33
+ end
34
+ end
35
+ end
36
+
37
+ def self.verifiers
38
+ @@verifiers
39
+ end
40
+
41
+ def self.verify!
42
+ verifiers.each(&:verify!)
43
+ end
44
+
45
+ def self.reset!
46
+ @@verifiers = []
47
+ end
48
+
49
+ class MessageExpectation
50
+ attr_reader :method
51
+ attr_reader :times_called
52
+ attr_reader :times_expected
53
+
54
+ def initialize(method, options = {})
55
+ @method = method
56
+ @times_expected = options[:negative] ? 0 : 1
57
+ @times_called = 0
58
+ end
59
+
60
+ def register_call
61
+ @times_called += 1
62
+ end
63
+
64
+ def verify
65
+ raise Stendhal::Exceptions::ExpectationNotMet.new "expected to be sent :#{method} #{times_expected} time#{times_expected == 1 ? '' : 's'}, but received it #{times_called} time#{times_called == 1 ? '' : 's'}" unless times_expected == times_called
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,34 @@
1
+ module Stendhal
2
+ module Mocks
3
+ module Mockable
4
+
5
+ def expects(method, options = {})
6
+ if options[:negative]
7
+ __verifier.add_negative_expectation(method)
8
+ else
9
+ __verifier.add_expectation(method)
10
+ end
11
+ metaclass = (class << self;self;end)
12
+ metaclass.send(:alias_method, :"__original_#{method}", method.to_sym)
13
+ metaclass.send(:undef_method, method.to_sym)
14
+ metaclass.class_eval <<EOT
15
+ def #{method}(*args, &block)
16
+ @__verifier.fulfill_expectation(:#{method},*args,&block)
17
+ __original_#{method}(*args,&block)
18
+ end
19
+ EOT
20
+ end
21
+
22
+ def does_not_expect(method)
23
+ expects(method, :negative => true)
24
+ end
25
+
26
+ private
27
+
28
+ def __verifier
29
+ @__verifier ||= MockVerifier.new(self)
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -1,4 +1,6 @@
1
1
  require 'stendhal/mocks/test_double'
2
+ require 'stendhal/mocks/mock_verifier'
3
+ require 'stendhal/mocks/mockable'
2
4
 
3
5
  module Stendhal
4
6
  module Mocks
@@ -1,3 +1,3 @@
1
1
  module Stendhal
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
data/lib/stendhal.rb CHANGED
@@ -6,4 +6,5 @@ require 'stendhal/example'
6
6
  require 'stendhal/example_group'
7
7
 
8
8
  require 'stendhal/core_ext/kernel'
9
+ require 'stendhal/core_ext/object'
9
10
  require 'stendhal/dsl'
@@ -60,6 +60,26 @@ module Stendhal
60
60
  example.should be_aborted
61
61
  end
62
62
 
63
+ it "verifies all message expectations after running the block" do
64
+ example = Example.new("docstring") do
65
+
66
+ end
67
+ example.should_receive(:instance_eval).ordered
68
+ Stendhal::Mocks::MockVerifier.should_receive(:verify!).ordered
69
+
70
+ example.run
71
+ end
72
+
73
+ it "resets all message expectations before running the block" do
74
+ example = Example.new("docstring") do
75
+
76
+ end
77
+ Stendhal::Mocks::MockVerifier.should_receive(:reset!)
78
+ example.should_receive(:instance_eval).ordered
79
+
80
+ example.run
81
+ end
82
+
63
83
  end
64
84
 
65
85
  describe "#fail" do
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ module Stendhal
4
+ module Mocks
5
+ describe MockVerifier do
6
+
7
+ subject { verifier = MockVerifier.new('object') }
8
+
9
+ it 'includes itself in verifiers when created' do
10
+ subject
11
+ MockVerifier.should have(1).verifiers
12
+ end
13
+
14
+ describe "instance methods" do
15
+
16
+ describe "#add_expectation" do
17
+ it 'adds an expectation for a given method' do
18
+ MockVerifier::MessageExpectation.should_receive(:new).with(:reverse)
19
+
20
+ subject.add_expectation(:reverse)
21
+ end
22
+ end
23
+
24
+ describe "#add_negative_expectation" do
25
+ it 'adds a negative expectation for a given method' do
26
+ MockVerifier::MessageExpectation.should_receive(:new).with(:reverse, :negative => true)
27
+
28
+ subject.add_negative_expectation(:reverse)
29
+ end
30
+ end
31
+
32
+ describe "#fulfill_expectation" do
33
+ it 'registers a call for a given method' do
34
+ subject.add_expectation(:reverse)
35
+ subject.expectations.first.should_receive(:register_call)
36
+
37
+ subject.fulfill_expectation(:reverse)
38
+ end
39
+ end
40
+
41
+ describe "#verify!" do
42
+ it 'verifies each of the expectations until one fails' do
43
+ expectations = [double, double, double]
44
+ expectations.each do |e|
45
+ e.should_receive(:verify)
46
+ end
47
+ subject.should_receive(:expectations).and_return(expectations)
48
+
49
+ subject.verify!
50
+ end
51
+ it 'adds the object inspect to the message if raised any ExpectationNotMet' do
52
+ expectations = [double, double, double]
53
+ expectations.first.should_receive(:verify).and_raise(Stendhal::Exceptions::ExpectationNotMet.new('expected foo to be bar'))
54
+
55
+ subject.should_receive(:expectations).and_return(expectations)
56
+
57
+ expect {
58
+ subject.verify!
59
+ }.to raise_error(Stendhal::Exceptions::ExpectationNotMet, "object expected foo to be bar")
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ describe "class methods" do
66
+
67
+ describe "#verify!" do
68
+ it 'verifies each of the verifiers' do
69
+ verifiers = [double, double, double]
70
+ verifiers.each { |v| v.should_receive(:verify!) }
71
+ MockVerifier.should_receive(:verifiers).and_return verifiers
72
+
73
+ MockVerifier.verify!
74
+ end
75
+ end
76
+
77
+ describe "#reset!" do
78
+ it 'deletes all verifiers' do
79
+ MockVerifier.new('object')
80
+ MockVerifier.new('other object')
81
+
82
+ MockVerifier.reset!
83
+
84
+ MockVerifier.should have(0).verifiers
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ describe MockVerifier::MessageExpectation do
93
+
94
+ subject { MockVerifier::MessageExpectation.new(:length) }
95
+
96
+ it "initializes with 0 times called" do
97
+ subject.times_called.should == 0
98
+ end
99
+
100
+ context "when given no options" do
101
+ it "initializes with 1 times expected" do
102
+ subject.times_expected.should == 1
103
+ end
104
+ end
105
+
106
+ context "when given :negative => true" do
107
+ it "initializes with 0 times expected" do
108
+ negative_expectation = MockVerifier::MessageExpectation.new(:length, :negative => true)
109
+ negative_expectation.times_expected.should == 0
110
+ end
111
+ end
112
+
113
+ describe "instance methods" do
114
+
115
+ describe "#register_call" do
116
+ it 'registers a call for the given expectation' do
117
+ expect{
118
+ subject.register_call
119
+ }.to change(subject, :times_called).by(1)
120
+ end
121
+ end
122
+
123
+ describe "#verify" do
124
+ it 'registers a call for the given expectation' do
125
+ subject.stub(:times_called).and_return 2
126
+ subject.stub(:times_expected).and_return 1
127
+
128
+ expect {
129
+ subject.verify
130
+ }.to raise_error(Stendhal::Exceptions::ExpectationNotMet, "expected to be sent :length 1 time, but received it 2 times")
131
+ end
132
+ end
133
+
134
+ end
135
+
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ class MyArray < Array
4
+ include Stendhal::Mocks::Mockable
5
+ end
6
+
7
+ module Stendhal
8
+ module Mocks
9
+ describe "a Mockable class" do
10
+
11
+ subject { MyArray.new([1,2,3]) }
12
+
13
+ describe "#expects" do
14
+ it 'creates a verifier' do
15
+ subject.expects(:length)
16
+ subject.send(:__verifier).should be_a(MockVerifier)
17
+ end
18
+ it 'creates a message expectation on the given method' do
19
+ subject.expects(:length)
20
+ subject.send(:__verifier).expectations.map(&:method).should include(:length)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 4
9
- version: 0.1.4
8
+ - 5
9
+ version: 0.1.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Josep M. Bach
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-03 00:00:00 +01:00
17
+ date: 2010-11-09 00:00:00 +01:00
18
18
  default_executable: stendhal
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -91,12 +91,14 @@ files:
91
91
  - bin/stendhal
92
92
  - features/examples.feature
93
93
  - features/expectations.feature
94
+ - features/mocks.feature
94
95
  - features/reporter.feature
95
96
  - features/support/env.rb
96
97
  - features/test_doubles_and_stubs.feature
97
98
  - lib/stendhal.rb
98
99
  - lib/stendhal/autorun.rb
99
100
  - lib/stendhal/core_ext/kernel.rb
101
+ - lib/stendhal/core_ext/object.rb
100
102
  - lib/stendhal/dsl.rb
101
103
  - lib/stendhal/example.rb
102
104
  - lib/stendhal/example_group.rb
@@ -107,6 +109,8 @@ files:
107
109
  - lib/stendhal/matchers/kind.rb
108
110
  - lib/stendhal/matchers/predicate.rb
109
111
  - lib/stendhal/mocks.rb
112
+ - lib/stendhal/mocks/mock_verifier.rb
113
+ - lib/stendhal/mocks/mockable.rb
110
114
  - lib/stendhal/mocks/test_double.rb
111
115
  - lib/stendhal/reporter.rb
112
116
  - lib/stendhal/version.rb
@@ -120,8 +124,10 @@ files:
120
124
  - spec/stendhal/matchers/kind_spec.rb
121
125
  - spec/stendhal/matchers/predicate_spec.rb
122
126
  - spec/stendhal/matchers_spec.rb
127
+ - spec/stendhal/mocks/mock_verifier_spec.rb
128
+ - spec/stendhal/mocks/mockable_spec.rb
129
+ - spec/stendhal/mocks/test_double_spec.rb
123
130
  - spec/stendhal/reporter_spec.rb
124
- - spec/stendhal/test_double_spec.rb
125
131
  - stendhal.gemspec
126
132
  has_rdoc: true
127
133
  homepage: http://rubygems.org/gems/stendhal
@@ -158,6 +164,7 @@ summary: Stendhal is a really simple test framework.
158
164
  test_files:
159
165
  - features/examples.feature
160
166
  - features/expectations.feature
167
+ - features/mocks.feature
161
168
  - features/reporter.feature
162
169
  - features/support/env.rb
163
170
  - features/test_doubles_and_stubs.feature
@@ -170,5 +177,7 @@ test_files:
170
177
  - spec/stendhal/matchers/kind_spec.rb
171
178
  - spec/stendhal/matchers/predicate_spec.rb
172
179
  - spec/stendhal/matchers_spec.rb
180
+ - spec/stendhal/mocks/mock_verifier_spec.rb
181
+ - spec/stendhal/mocks/mockable_spec.rb
182
+ - spec/stendhal/mocks/test_double_spec.rb
173
183
  - spec/stendhal/reporter_spec.rb
174
- - spec/stendhal/test_double_spec.rb