mspec 1.2.0 → 1.3.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/Rakefile CHANGED
@@ -9,7 +9,7 @@ task :default => :spec
9
9
 
10
10
  spec = Gem::Specification.new do |s|
11
11
  s.name = %q{mspec}
12
- s.version = "1.2.0"
12
+ s.version = "1.3.0"
13
13
 
14
14
  s.specification_version = 2 if s.respond_to? :specification_version=
15
15
 
@@ -94,8 +94,7 @@ class MkSpec
94
94
  f.puts <<-EOS
95
95
 
96
96
  describe "#{meth}" do
97
- it "needs to be reviewed for spec completeness" do
98
- end
97
+ it "needs to be reviewed for spec completeness"
99
98
  end
100
99
  EOS
101
100
  end
@@ -127,7 +127,8 @@ class MSpecMain < MSpecScript
127
127
  def run
128
128
  ENV['MSPEC_RUNNER'] = '1'
129
129
 
130
- argv = config[:flags]
130
+ argv = ["-v"]
131
+ argv.concat config[:flags]
131
132
  argv.concat config[:includes]
132
133
  argv.concat config[:requires]
133
134
  argv << "#{MSPEC_HOME}/bin/mspec-#{ config[:command] || "run" }"
@@ -1,4 +1,9 @@
1
1
  class ExpectationNotMetError < StandardError; end
2
+ class ExpectationNotFoundError < StandardError
3
+ def message
4
+ "No behavior expectation was found in the example"
5
+ end
6
+ end
2
7
 
3
8
  class Expectation
4
9
  def self.fail_with(expected, actual)
@@ -1,5 +1,6 @@
1
1
  class Object
2
2
  def should(matcher=nil)
3
+ MSpec.expectation
3
4
  MSpec.actions :expectation, MSpec.current.state
4
5
  if matcher
5
6
  unless matcher.matches?(self)
@@ -11,6 +12,7 @@ class Object
11
12
  end
12
13
 
13
14
  def should_not(matcher=nil)
15
+ MSpec.expectation
14
16
  MSpec.actions :expectation, MSpec.current.state
15
17
  if matcher
16
18
  if matcher.matches?(self)
@@ -10,4 +10,8 @@ class IOStub < String
10
10
  def puts(*str)
11
11
  write(str.collect { |s| s.to_s.chomp }.concat([nil]).join("\n"))
12
12
  end
13
+
14
+ def flush
15
+ self
16
+ end
13
17
  end
@@ -41,7 +41,10 @@ module Mock
41
41
 
42
42
  proxy = MockProxy.new type
43
43
 
44
- MSpec.actions :expectation, MSpec.current.state if proxy.mock?
44
+ if proxy.mock?
45
+ MSpec.expectation
46
+ MSpec.actions :expectation, MSpec.current.state
47
+ end
45
48
 
46
49
  if proxy.stub?
47
50
  stubs[key].unshift proxy
@@ -50,14 +50,14 @@ class TallyAction
50
50
  def register
51
51
  MSpec.register :load, self
52
52
  MSpec.register :exception, self
53
- MSpec.register :after, self
53
+ MSpec.register :example, self
54
54
  MSpec.register :expectation, self
55
55
  end
56
56
 
57
57
  def unregister
58
58
  MSpec.unregister :load, self
59
59
  MSpec.unregister :exception, self
60
- MSpec.unregister :after, self
60
+ MSpec.unregister :example, self
61
61
  MSpec.unregister :expectation, self
62
62
  end
63
63
 
@@ -77,9 +77,9 @@ class TallyAction
77
77
  exception.failure? ? @counter.failures! : @counter.errors!
78
78
  end
79
79
 
80
- # Callback for the MSpec :after event. Increments the tally
80
+ # Callback for the MSpec :example event. Increments the tally
81
81
  # of examples.
82
- def after(state)
82
+ def example(state, block)
83
83
  @counter.examples!
84
84
  end
85
85
 
@@ -13,16 +13,17 @@ require 'mspec/runner/example'
13
13
  # is evaluated, just as +it+ refers to the example itself.
14
14
  #++
15
15
  class ContextState
16
+ attr_reader :state
17
+
16
18
  def initialize
17
- @start = []
19
+ @start = []
18
20
  @before = []
19
- @after = []
21
+ @after = []
20
22
  @finish = []
21
- @spec = []
22
- end
23
-
24
- def state
25
- @state
23
+ @spec = []
24
+ @mock_verify = lambda { Mock.verify_count }
25
+ @mock_cleanup = lambda { Mock.cleanup }
26
+ @expectation_missing = lambda { raise ExpectationNotFoundError }
26
27
  end
27
28
 
28
29
  def before(at=:each, &block)
@@ -54,7 +55,7 @@ class ContextState
54
55
  end
55
56
 
56
57
  def protect(what, blocks, check=true)
57
- return false if check and MSpec.pretend_mode?
58
+ return true if check and MSpec.pretend_mode?
58
59
  Array(blocks).all? { |block| MSpec.protect what, &block }
59
60
  end
60
61
 
@@ -64,21 +65,32 @@ class ContextState
64
65
 
65
66
  MSpec.shuffle @spec if MSpec.randomize?
66
67
  MSpec.actions :enter, @describe
67
- protect "before :all", @start
68
- @spec.each do |desc, spec, state|
69
- @state = state
70
- MSpec.actions :before, state
71
- if protect("before :each", @before)
72
- protect nil, spec
73
- protect "after :each", @after
74
- protect "Mock.verify_count", lambda { Mock.verify_count }
68
+
69
+ if protect "before :all", @start
70
+ @spec.each do |desc, spec, state|
71
+ @state = state
72
+ MSpec.actions :before, state
73
+
74
+ if protect("before :each", @before)
75
+ MSpec.clear_expectations
76
+ protect nil, spec
77
+ if spec
78
+ MSpec.actions :example, state, spec
79
+ protect nil, @expectation_missing unless MSpec.expectation?
80
+ end
81
+ protect "after :each", @after
82
+ protect "Mock.verify_count", @mock_verify
83
+ end
84
+
85
+ protect "Mock.cleanup", @mock_cleanup
86
+ MSpec.actions :after, state
87
+ @state = nil
75
88
  end
76
- protect "Mock.cleanup", lambda { Mock.cleanup }
77
- MSpec.actions :after, state
78
- @state = nil
89
+ protect "after :all", @finish
90
+ else
91
+ protect "Mock.cleanup", @mock_cleanup
79
92
  end
80
- protect "after :all", @finish
93
+
81
94
  MSpec.actions :leave
82
95
  end
83
96
  end
84
-
@@ -1,6 +1,8 @@
1
1
  class ExceptionState
2
2
  attr_reader :description, :describe, :it, :exception
3
3
 
4
+ PATH = /#{File.expand_path(File.dirname(__FILE__) + '/../../..')}/
5
+
4
6
  def initialize(state, location, exception)
5
7
  @exception = exception
6
8
 
@@ -16,13 +18,14 @@ class ExceptionState
16
18
  end
17
19
 
18
20
  def failure?
19
- @exception.is_a? ExpectationNotMetError
21
+ [ExpectationNotMetError, ExpectationNotFoundError].any? { |e| @exception.is_a? e }
20
22
  end
21
23
 
22
24
  def message
23
25
  if @exception.message.empty?
24
26
  "<No message>"
25
- elsif @exception.class == ExpectationNotMetError
27
+ elsif @exception.class == ExpectationNotMetError ||
28
+ @exception.class == ExpectationNotFoundError
26
29
  @exception.message
27
30
  else
28
31
  "#{@exception.class}: #{@exception.message}"
@@ -31,9 +34,10 @@ class ExceptionState
31
34
 
32
35
  def backtrace
33
36
  begin
34
- return @exception.awesome_backtrace.show
37
+ bt = @exception.awesome_backtrace.show.split "\n"
35
38
  rescue Exception
36
- return @exception.backtrace && @exception.backtrace.join("\n")
39
+ bt = @exception.backtrace || []
37
40
  end
41
+ bt.reject { |line| PATH =~ line }.join("\n")
38
42
  end
39
43
  end
@@ -93,5 +93,6 @@ class DottedFormatter
93
93
  # A convenience method to allow printing to different outputs.
94
94
  def print(*args)
95
95
  @out.print(*args)
96
+ @out.flush
96
97
  end
97
98
  end
@@ -18,8 +18,10 @@ module MSpec
18
18
  @mode = nil
19
19
  @load = nil
20
20
  @unload = nil
21
- @randomize = nil
22
- @expectation = nil
21
+ @exception = nil
22
+ @randomize = nil
23
+ @expectation = nil
24
+ @expectations = false
23
25
 
24
26
  def self.describe(mod, msg=nil, &block)
25
27
  stack.push ContextState.new
@@ -109,6 +111,7 @@ module MSpec
109
111
  # :enter before a describe block is run
110
112
  # :before before a single spec is run
111
113
  # :expectation before a 'should', 'should_receive', etc.
114
+ # :example after an example block is run, passed the block
112
115
  # :exception after an exception is rescued
113
116
  # :after after a single spec is run
114
117
  # :leave after a describe block is run
@@ -176,6 +179,21 @@ module MSpec
176
179
  end
177
180
  end
178
181
 
182
+ # Records that an expectation has been encountered in an example.
183
+ def self.expectation
184
+ store :expectations, true
185
+ end
186
+
187
+ # Returns true if an expectation has been encountered
188
+ def self.expectation?
189
+ retrieve :expectations
190
+ end
191
+
192
+ # Resets the flag that an expectation has been encountered in an example.
193
+ def self.clear_expectations
194
+ store :expectations, false
195
+ end
196
+
179
197
  # Transforms a spec filename into a tags filename by applying each
180
198
  # substitution pattern in :tags_pattern. The default patterns are:
181
199
  #
@@ -100,7 +100,6 @@ class NameMap
100
100
  hash["#{name}."] = ms.sort unless ms.empty?
101
101
 
102
102
  ms = m.public_instance_methods(false) +
103
- m.private_instance_methods(false) +
104
103
  m.protected_instance_methods(false)
105
104
  hash["#{name}#"] = ms.sort unless ms.empty?
106
105
 
@@ -76,6 +76,7 @@ class MSpecScript
76
76
  end
77
77
 
78
78
  def self.main
79
+ $VERBOSE = nil unless ENV['OUTPUT_WARNINGS']
79
80
  script = new
80
81
  script.load 'default.mspec'
81
82
  script.load '~/.mspecrc'
data/lib/mspec/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module MSpec
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -208,6 +208,16 @@ describe MkSpec, "#write_spec" do
208
208
  @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb")
209
209
  @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
210
210
  end
211
+
212
+ it "writes a template spec" do
213
+ @file.should_receive(:puts).with(<<EOS)
214
+
215
+ describe "Object#inspect" do
216
+ it "needs to be reviewed for spec completeness"
217
+ end
218
+ EOS
219
+ @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
220
+ end
211
221
  end
212
222
 
213
223
  describe MkSpec, "#create_file" do
@@ -215,16 +215,17 @@ describe MSpecMain, "#run" do
215
215
  end
216
216
 
217
217
  it "uses exec to invoke the runner script" do
218
- @script.should_receive(:exec).with("ruby", %r"mspec/bin/mspec-run$")
218
+ @script.should_receive(:exec).with("ruby", "-v", %r"mspec/bin/mspec-run$")
219
219
  @script.options
220
220
  @script.run
221
221
  end
222
222
 
223
223
  it "calls #multi_exec if the command is 'ci' and the multi option is passed" do
224
224
  @script.should_receive(:multi_exec).and_return do |arg|
225
- arg.length.should == 2
226
- arg.first.should =~ %r"mspec/bin/mspec-ci$"
227
- arg.last.should == "-fy"
225
+ arg.length.should == 3
226
+ arg[0].should == "-v"
227
+ arg[1].should =~ %r"mspec/bin/mspec-ci$"
228
+ arg[2].should == "-fy"
228
229
  end
229
230
  @script.options ["ci", "-j"]
230
231
  @script.run
@@ -7,6 +7,19 @@ describe ExpectationNotMetError do
7
7
  end
8
8
  end
9
9
 
10
+ describe ExpectationNotFoundError do
11
+ it "is a subclass of StandardError" do
12
+ ExpectationNotFoundError.ancestors.should include(StandardError)
13
+ end
14
+ end
15
+
16
+ describe ExpectationNotFoundError, "#message" do
17
+ it "returns 'No behavior expectation was found in the example'" do
18
+ m = ExpectationNotFoundError.new.message
19
+ m.should == "No behavior expectation was found in the example"
20
+ end
21
+ end
22
+
10
23
  describe Expectation, "#fail_with" do
11
24
  it "raises an ExpectationNotMetError" do
12
25
  lambda {
@@ -19,11 +19,15 @@ end
19
19
  describe Object, "#should" do
20
20
  before :each do
21
21
  class Object; alias_method :should, :mspec_should; end
22
+
23
+ @state = mock("example state", :null_object => true)
24
+ context = mock("context state", :null_object => true)
25
+ context.stub!(:state).and_return(@state)
26
+ MSpec.stub!(:current).and_return(context)
22
27
  MSpec.stub!(:actions)
23
- MSpec.stub!(:current).and_return(mock("spec state", :null_object => true))
24
28
 
25
29
  @target = "target"
26
- @matcher = mock("matcher")
30
+ @matcher = mock("matcher", :null_object => true)
27
31
  end
28
32
 
29
33
  after :each do
@@ -54,17 +58,31 @@ describe Object, "#should" do
54
58
  class Object; alias_method :should, :rspec_should; end
55
59
  matcher.should be_instance_of(PositiveOperatorMatcher)
56
60
  end
61
+
62
+ it "invokes the MSpec :expectation actions" do
63
+ MSpec.should_receive(:actions).with(:expectation, @state)
64
+ @target.should @matcher
65
+ end
66
+
67
+ it "registers that an expectation has been encountered" do
68
+ MSpec.should_receive(:expectation)
69
+ @target.should @matcher
70
+ end
57
71
  end
58
72
 
59
73
  describe Object, "#should_not" do
60
74
  before :each do
61
75
  class Object; alias_method :should, :mspec_should; end
62
76
  class Object; alias_method :should_not, :mspec_should_not; end
77
+
78
+ @state = mock("example state", :null_object => true)
79
+ context = mock("context state", :null_object => true)
80
+ context.stub!(:state).and_return(@state)
81
+ MSpec.stub!(:current).and_return(context)
63
82
  MSpec.stub!(:actions)
64
- MSpec.stub!(:current).and_return(mock("spec state", :null_object => true))
65
83
 
66
84
  @target = "target"
67
- @matcher = mock("matcher")
85
+ @matcher = mock("matcher", :null_object => true)
68
86
  end
69
87
 
70
88
  after :each do
@@ -96,4 +114,16 @@ describe Object, "#should_not" do
96
114
  class Object; alias_method :should, :rspec_should; end
97
115
  matcher.should be_instance_of(NegativeOperatorMatcher)
98
116
  end
117
+
118
+ it "invokes the MSpec :expectation actions" do
119
+ MSpec.should_receive(:actions).with(:expectation, @state)
120
+ @matcher.should_receive(:negative_failure_message).and_return(["expected", "actual"])
121
+ @target.should_not @matcher rescue nil
122
+ end
123
+
124
+ it "registers that an expectation has been encountered" do
125
+ MSpec.should_receive(:expectation)
126
+ @matcher.should_receive(:negative_failure_message).and_return(["expected", "actual"])
127
+ @target.should_not @matcher rescue nil
128
+ end
99
129
  end
@@ -31,4 +31,8 @@ describe IOStub do
31
31
  @out.puts "hello", 1, 2, 3
32
32
  @out.should == "hello\n1\n2\n3\n"
33
33
  end
34
+
35
+ it "provides a flush method that does nothing and returns self" do
36
+ @out.flush.should == @out
37
+ end
34
38
  end
@@ -130,6 +130,14 @@ describe Mock, ".install_method for mocks" do
130
130
  Mock.install_method(@mock, :method_call).and_return(1)
131
131
  @mock.method_call.should == 1
132
132
  end
133
+
134
+ it "registers that an expectation has been encountered" do
135
+ state = mock("run state", :null_object => true)
136
+ state.stub!(:state).and_return(mock("spec state"))
137
+ MSpec.should_receive(:expectation)
138
+ Mock.install_method(@mock, :method_call).and_return(1)
139
+ @mock.method_call.should == 1
140
+ end
133
141
  end
134
142
 
135
143
  describe Mock, ".install_method for stubs" do
@@ -73,8 +73,8 @@ describe TallyAction do
73
73
  @tally.counter.expectations.should == 1
74
74
  end
75
75
 
76
- it "responds to #after by incrementing counts returned by Tally#examples" do
77
- @tally.after @state
76
+ it "responds to #example by incrementing counts returned by Tally#examples" do
77
+ @tally.example @state, nil
78
78
  @tally.counter.examples.should == 1
79
79
  @tally.counter.expectations.should == 0
80
80
  @tally.counter.failures.should == 0
@@ -101,7 +101,7 @@ describe TallyAction do
101
101
 
102
102
  it "responds to #format by returning a readable string of counts" do
103
103
  @tally.load
104
- @tally.after @state
104
+ @tally.example @state, nil
105
105
  @tally.expectation @state
106
106
  @tally.expectation @state
107
107
  exc = ExceptionState.new nil, nil, ExpectationNotMetError.new("Failed!")
@@ -111,7 +111,7 @@ describe TallyAction do
111
111
 
112
112
  it "responds to #register by registering itself with MSpec for appropriate actions" do
113
113
  MSpec.should_receive(:register).with(:load, @tally)
114
- MSpec.should_receive(:register).with(:after, @tally)
114
+ MSpec.should_receive(:register).with(:example, @tally)
115
115
  MSpec.should_receive(:register).with(:exception, @tally)
116
116
  MSpec.should_receive(:register).with(:expectation, @tally)
117
117
  @tally.register
@@ -120,7 +120,7 @@ describe TallyAction do
120
120
  it "responds to #unregister by unregistering itself with MSpec for appropriate actions" do
121
121
  MSpec.should_receive(:unregister).with(:load, @tally)
122
122
  MSpec.should_receive(:unregister).with(:exception, @tally)
123
- MSpec.should_receive(:unregister).with(:after, @tally)
123
+ MSpec.should_receive(:unregister).with(:example, @tally)
124
124
  MSpec.should_receive(:unregister).with(:expectation, @tally)
125
125
  @tally.unregister
126
126
  end
@@ -1,4 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'mspec/expectations/expectations'
2
3
  require 'mspec/matchers/base'
3
4
  require 'mspec/runner/mspec'
4
5
  require 'mspec/mocks/mock'
@@ -52,9 +53,9 @@ describe ContextState, "#protect" do
52
53
  @c = lambda { raise Exception, "Fail!" }
53
54
  end
54
55
 
55
- it "returns false and does execute any blocks if check is true and MSpec.pretend_mode? is true" do
56
+ it "returns true and does execute any blocks if check is true and MSpec.pretend_mode? is true" do
56
57
  MSpec.stub!(:pretend_mode?).and_return(true)
57
- ContextState.new.protect("message", [@a, @b]).should be_false
58
+ ContextState.new.protect("message", [@a, @b]).should be_true
58
59
  ScratchPad.recorded.should == []
59
60
  end
60
61
 
@@ -136,13 +137,6 @@ describe ContextState, "#process" do
136
137
  ScratchPad.recorded.should == [:a, :b]
137
138
  end
138
139
 
139
- it "does not call the it block if an exception is raised in before(:each)" do
140
- @state.before(:each) { raise Exception, "Fail!" }
141
- @state.it("one", &@a)
142
- @state.process
143
- ScratchPad.recorded.should == []
144
- end
145
-
146
140
  it "calls each before(:each) block" do
147
141
  @state.before(:each, &@a)
148
142
  @state.before(:each, &@b)
@@ -159,14 +153,6 @@ describe ContextState, "#process" do
159
153
  ScratchPad.recorded.should == [:a, :b]
160
154
  end
161
155
 
162
- it "does not call after(:each) if an exception is raised in before(:each)" do
163
- @state.before(:each) { raise Exception, "Fail!" }
164
- @state.after(:each, &@a)
165
- @state.it("") { }
166
- @state.process
167
- ScratchPad.recorded.should == []
168
- end
169
-
170
156
  it "calls Mock.cleanup for each it block" do
171
157
  @state.it("") { }
172
158
  @state.it("") { }
@@ -181,13 +167,6 @@ describe ContextState, "#process" do
181
167
  @state.process
182
168
  end
183
169
 
184
- it "does not call Mock.verify_count if an exception is raised in before(:each)" do
185
- @state.before(:each) { raise Exception, "Fail!" }
186
- @state.it("") { }
187
- Mock.should_not_receive(:verify_count)
188
- @state.process
189
- end
190
-
191
170
  it "calls the describe block" do
192
171
  ScratchPad.record []
193
172
  @state.describe(Object, "msg") { ScratchPad << :a }
@@ -203,6 +182,14 @@ describe ContextState, "#process" do
203
182
  ScratchPad.recorded.should be_kind_of(ExampleState)
204
183
  end
205
184
 
185
+ it "clears the expectations flag before evaluating the #it block" do
186
+ MSpec.clear_expectations
187
+ MSpec.should_receive(:clear_expectations)
188
+ @state.it("it") { ScratchPad.record MSpec.expectation? }
189
+ @state.process
190
+ ScratchPad.recorded.should be_false
191
+ end
192
+
206
193
  it "shuffles the spec list if MSpec.randomize? is true" do
207
194
  MSpec.randomize
208
195
  MSpec.should_receive(:shuffle)
@@ -212,15 +199,151 @@ describe ContextState, "#process" do
212
199
  end
213
200
  end
214
201
 
215
- describe ContextState, "#process in pretend mode" do
216
- before :all do
217
- MSpec.register_mode :pretend
202
+ describe ContextState, "#process" do
203
+ before :each do
204
+ MSpec.store :exception, []
205
+
206
+ @state = ContextState.new
207
+ @state.describe("") { }
208
+
209
+ action = mock("action")
210
+ def action.exception(exc)
211
+ ScratchPad.record :exception if exc.exception.is_a? ExpectationNotFoundError
212
+ end
213
+ MSpec.register :exception, action
214
+
215
+ MSpec.clear_expectations
216
+ ScratchPad.clear
218
217
  end
219
218
 
220
- after :all do
221
- MSpec.register_mode nil
219
+ after :each do
220
+ MSpec.store :exception, nil
222
221
  end
223
222
 
223
+ it "raises an ExpectationNotFoundError if an #it block does not contain an expectation" do
224
+ @state.it("it") { }
225
+ @state.process
226
+ ScratchPad.recorded.should == :exception
227
+ end
228
+
229
+ it "does not raise an ExpectationNotFoundError if an #it block does contain an expectation" do
230
+ @state.it("it") { MSpec.expectation }
231
+ @state.process
232
+ ScratchPad.recorded.should be_nil
233
+ end
234
+ end
235
+
236
+ describe ContextState, "#process" do
237
+ before :each do
238
+ MSpec.store :example, []
239
+
240
+ @state = ContextState.new
241
+ @state.describe("") { }
242
+
243
+ example = mock("example")
244
+ def example.example(state, spec)
245
+ ScratchPad << state << spec
246
+ end
247
+ MSpec.register :example, example
248
+
249
+ ScratchPad.record []
250
+ end
251
+
252
+ after :each do
253
+ MSpec.store :example, nil
254
+ end
255
+
256
+ it "calls registered example actions with the current ExampleState and block" do
257
+ @state.it("") { MSpec.expectation }
258
+ @state.process
259
+
260
+ ScratchPad.recorded.first.should be_kind_of(ExampleState)
261
+ ScratchPad.recorded.last.should be_kind_of(Proc)
262
+ end
263
+
264
+ it "does not call registered example actions if the example has no block" do
265
+ @state.it("empty example")
266
+ @state.process
267
+ ScratchPad.recorded.should == []
268
+ end
269
+ end
270
+
271
+ describe ContextState, "#process" do
272
+ before :each do
273
+ MSpec.store :before, []
274
+ MSpec.store :after, []
275
+
276
+ @state = ContextState.new
277
+ @state.describe("") { }
278
+ @state.it("") { MSpec.expectation }
279
+ end
280
+
281
+ after :each do
282
+ MSpec.store :before, nil
283
+ MSpec.store :after, nil
284
+ end
285
+
286
+ it "calls registered before actions with the current ExampleState instance" do
287
+ before = mock("before")
288
+ before.should_receive(:before).and_return {
289
+ ScratchPad.record :before
290
+ @spec_state = @state.state
291
+ }
292
+ MSpec.register :before, before
293
+ @state.process
294
+ ScratchPad.recorded.should == :before
295
+ @spec_state.should be_kind_of(ExampleState)
296
+ end
297
+
298
+ it "calls registered after actions with the current ExampleState instance" do
299
+ after = mock("after")
300
+ after.should_receive(:after).and_return {
301
+ ScratchPad.record :after
302
+ @spec_state = @state.state
303
+ }
304
+ MSpec.register :after, after
305
+ @state.process
306
+ ScratchPad.recorded.should == :after
307
+ @spec_state.should be_kind_of(ExampleState)
308
+ end
309
+ end
310
+
311
+ describe ContextState, "#process" do
312
+ end
313
+
314
+ describe ContextState, "#process" do
315
+ before :each do
316
+ MSpec.store :enter, []
317
+ MSpec.store :leave, []
318
+
319
+ @state = ContextState.new
320
+ @state.describe("") { }
321
+ @state.it("") { MSpec.expectation }
322
+ end
323
+
324
+ after :each do
325
+ MSpec.store :enter, nil
326
+ MSpec.store :leave, nil
327
+ end
328
+
329
+ it "calls registered enter actions with the current #describe string" do
330
+ enter = mock("enter")
331
+ enter.should_receive(:enter).and_return { ScratchPad.record :enter }
332
+ MSpec.register :enter, enter
333
+ @state.process
334
+ ScratchPad.recorded.should == :enter
335
+ end
336
+
337
+ it "calls registered leave actions" do
338
+ leave = mock("leave")
339
+ leave.should_receive(:leave).and_return { ScratchPad.record :leave }
340
+ MSpec.register :leave, leave
341
+ @state.process
342
+ ScratchPad.recorded.should == :leave
343
+ end
344
+ end
345
+
346
+ describe ContextState, "#process when an exception is raised in before(:all)" do
224
347
  before :each do
225
348
  MSpec.store :before, []
226
349
  MSpec.store :after, []
@@ -231,70 +354,68 @@ describe ContextState, "#process in pretend mode" do
231
354
  @a = lambda { ScratchPad << :a }
232
355
  @b = lambda { ScratchPad << :b }
233
356
  ScratchPad.record []
357
+
358
+ @state.before(:all) { raise Exception, "Fail!" }
234
359
  end
235
360
 
236
- it "does not call any before(:all) block" do
237
- @state.before(:all, &@a)
238
- @state.before(:all, &@b)
239
- @state.it("") { }
240
- @state.process
241
- ScratchPad.recorded.should == []
361
+ after :each do
362
+ MSpec.store :before, nil
363
+ MSpec.store :after, nil
242
364
  end
243
365
 
244
- it "does not call any after(:all) block" do
245
- @state.after(:all, &@a)
246
- @state.after(:all, &@b)
366
+ it "does not call before(:each)" do
367
+ @state.before(:each, &@a)
247
368
  @state.it("") { }
248
369
  @state.process
249
370
  ScratchPad.recorded.should == []
250
371
  end
251
372
 
252
- it "does not call any it block" do
373
+ it "does not call the it block" do
253
374
  @state.it("one", &@a)
254
- @state.it("two", &@b)
255
375
  @state.process
256
376
  ScratchPad.recorded.should == []
257
377
  end
258
378
 
259
- it "does not call any before(:each) block" do
260
- @state.before(:each, &@a)
261
- @state.before(:each, &@b)
379
+ it "does not call after(:each)" do
380
+ @state.after(:each, &@a)
262
381
  @state.it("") { }
263
382
  @state.process
264
383
  ScratchPad.recorded.should == []
265
384
  end
266
385
 
267
- it "does not call any after(:each) block" do
268
- @state.after(:each, &@a)
269
- @state.after(:each, &@b)
386
+ it "does not call after(:each)" do
387
+ @state.after(:all, &@a)
270
388
  @state.it("") { }
271
389
  @state.process
272
390
  ScratchPad.recorded.should == []
273
391
  end
274
392
 
275
- it "does not call Mock.cleanup" do
276
- @state.it("") { }
393
+ it "does not call Mock.verify_count" do
277
394
  @state.it("") { }
278
- Mock.should_not_receive(:cleanup)
395
+ Mock.should_not_receive(:verify_count)
279
396
  @state.process
280
397
  end
281
398
 
282
- it "calls the describe block" do
283
- ScratchPad.record []
284
- @state.describe(Object, "msg") { ScratchPad << :a }
399
+ it "calls Mock.cleanup" do
400
+ @state.it("") { }
401
+ Mock.should_receive(:cleanup)
285
402
  @state.process
286
- ScratchPad.recorded.should == [:a]
287
403
  end
288
404
  end
289
405
 
290
- describe ContextState, "#process" do
406
+ describe ContextState, "#process when an exception is raised in before(:each)" do
291
407
  before :each do
292
408
  MSpec.store :before, []
293
409
  MSpec.store :after, []
294
410
 
295
411
  @state = ContextState.new
296
412
  @state.describe("") { }
297
- @state.it("") { }
413
+
414
+ @a = lambda { ScratchPad << :a }
415
+ @b = lambda { ScratchPad << :b }
416
+ ScratchPad.record []
417
+
418
+ @state.before(:each) { raise Exception, "Fail!" }
298
419
  end
299
420
 
300
421
  after :each do
@@ -302,28 +423,23 @@ describe ContextState, "#process" do
302
423
  MSpec.store :after, nil
303
424
  end
304
425
 
305
- it "calls registered before actions with the current ExampleState instance" do
306
- before = mock("before")
307
- before.should_receive(:before).and_return {
308
- ScratchPad.record :before
309
- @spec_state = @state.state
310
- }
311
- MSpec.register :before, before
426
+ it "does not call the it block" do
427
+ @state.it("one", &@a)
312
428
  @state.process
313
- ScratchPad.recorded.should == :before
314
- @spec_state.should be_kind_of(ExampleState)
429
+ ScratchPad.recorded.should == []
315
430
  end
316
431
 
317
- it "calls registered after actions with the current ExampleState instance" do
318
- after = mock("after")
319
- after.should_receive(:after).and_return {
320
- ScratchPad.record :after
321
- @spec_state = @state.state
322
- }
323
- MSpec.register :after, after
432
+ it "does not call after(:each)" do
433
+ @state.after(:each, &@a)
434
+ @state.it("") { }
435
+ @state.process
436
+ ScratchPad.recorded.should == []
437
+ end
438
+
439
+ it "does not call Mock.verify_count" do
440
+ @state.it("") { }
441
+ Mock.should_not_receive(:verify_count)
324
442
  @state.process
325
- ScratchPad.recorded.should == :after
326
- @spec_state.should be_kind_of(ExampleState)
327
443
  end
328
444
  end
329
445
 
@@ -337,6 +453,7 @@ describe ContextState, "#process in pretend mode" do
337
453
  end
338
454
 
339
455
  before :each do
456
+ ScratchPad.clear
340
457
  MSpec.store :before, []
341
458
  MSpec.store :after, []
342
459
 
@@ -375,35 +492,78 @@ describe ContextState, "#process in pretend mode" do
375
492
  end
376
493
  end
377
494
 
378
- describe ContextState, "#process" do
495
+ describe ContextState, "#process in pretend mode" do
496
+ before :all do
497
+ MSpec.register_mode :pretend
498
+ end
499
+
500
+ after :all do
501
+ MSpec.register_mode nil
502
+ end
503
+
379
504
  before :each do
380
- MSpec.store :enter, []
381
- MSpec.store :leave, []
505
+ MSpec.store :before, []
506
+ MSpec.store :after, []
382
507
 
383
508
  @state = ContextState.new
384
509
  @state.describe("") { }
510
+
511
+ @a = lambda { ScratchPad << :a }
512
+ @b = lambda { ScratchPad << :b }
513
+ ScratchPad.record []
514
+ end
515
+
516
+ it "calls the describe block" do
517
+ ScratchPad.record []
518
+ @state.describe(Object, "msg") { ScratchPad << :a }
519
+ @state.process
520
+ ScratchPad.recorded.should == [:a]
521
+ end
522
+
523
+ it "does not call any before(:all) block" do
524
+ @state.before(:all, &@a)
525
+ @state.before(:all, &@b)
385
526
  @state.it("") { }
527
+ @state.process
528
+ ScratchPad.recorded.should == []
386
529
  end
387
530
 
388
- after :each do
389
- MSpec.store :enter, nil
390
- MSpec.store :leave, nil
531
+ it "does not call any after(:all) block" do
532
+ @state.after(:all, &@a)
533
+ @state.after(:all, &@b)
534
+ @state.it("") { }
535
+ @state.process
536
+ ScratchPad.recorded.should == []
391
537
  end
392
538
 
393
- it "calls registered enter actions with the current #describe string" do
394
- enter = mock("enter")
395
- enter.should_receive(:enter).and_return { ScratchPad.record :enter }
396
- MSpec.register :enter, enter
539
+ it "does not call any it block" do
540
+ @state.it("one", &@a)
541
+ @state.it("two", &@b)
397
542
  @state.process
398
- ScratchPad.recorded.should == :enter
543
+ ScratchPad.recorded.should == []
399
544
  end
400
545
 
401
- it "calls registered leave actions" do
402
- leave = mock("leave")
403
- leave.should_receive(:leave).and_return { ScratchPad.record :leave }
404
- MSpec.register :leave, leave
546
+ it "does not call any before(:each) block" do
547
+ @state.before(:each, &@a)
548
+ @state.before(:each, &@b)
549
+ @state.it("") { }
550
+ @state.process
551
+ ScratchPad.recorded.should == []
552
+ end
553
+
554
+ it "does not call any after(:each) block" do
555
+ @state.after(:each, &@a)
556
+ @state.after(:each, &@b)
557
+ @state.it("") { }
558
+ @state.process
559
+ ScratchPad.recorded.should == []
560
+ end
561
+
562
+ it "does not call Mock.cleanup" do
563
+ @state.it("") { }
564
+ @state.it("") { }
565
+ Mock.should_not_receive(:cleanup)
405
566
  @state.process
406
- ScratchPad.recorded.should == :leave
407
567
  end
408
568
  end
409
569
 
@@ -70,7 +70,12 @@ describe ExceptionState, "#failure?" do
70
70
  exc.failure?.should be_true
71
71
  end
72
72
 
73
- it "returns false if the exception is not an ExpectationNotMetError" do
73
+ it "returns true if the exception is an ExpectationNotFoundError" do
74
+ exc = ExceptionState.new @state, "", ExpectationNotFoundError.new("Fail!")
75
+ exc.failure?.should be_true
76
+ end
77
+
78
+ it "returns false if the exception is not an ExpectationNotMetError or an ExpectationNotFoundError" do
74
79
  exc = ExceptionState.new @state, "", Exception.new("Fail!")
75
80
  exc.failure?.should be_false
76
81
  end
@@ -82,12 +87,18 @@ describe ExceptionState, "#message" do
82
87
  exc.message.should == "<No message>"
83
88
  end
84
89
 
85
- it "returns the message without exception class when the exception is ExpectationNotMetError" do
90
+ it "returns the message without exception class when the exception is an ExpectationNotMetError" do
86
91
  exc = ExceptionState.new @state, "", ExpectationNotMetError.new("Fail!")
87
92
  exc.message.should == "Fail!"
88
93
  end
89
94
 
90
- it "returns the message with exception class when the exception is not ExpectationNotMetError" do
95
+ it "returns ExpectationNotFoundError#message when the exception is an ExpectationNotFoundError" do
96
+ e = ExpectationNotFoundError.new
97
+ exc = ExceptionState.new @state, "", e
98
+ exc.message.should == e.message
99
+ end
100
+
101
+ it "returns the message with exception class when the exception is not an ExpectationNotMetError or an ExpectationNotFoundError" do
91
102
  exc = ExceptionState.new @state, "", Exception.new("Fail!")
92
103
  exc.message.should == "Exception: Fail!"
93
104
  end
@@ -95,16 +106,25 @@ end
95
106
 
96
107
  describe ExceptionState, "#backtrace" do
97
108
  before :each do
98
- begin
99
- raise Exception, "mock backtrace"
100
- rescue Exception => @exception
109
+ @action = mock("action")
110
+ def @action.exception(exc)
111
+ ScratchPad.record exc.exception
101
112
  end
113
+ MSpec.register :exception, @action
114
+
115
+ ScratchPad.clear
116
+ MSpec.protect("") { raise Exception }
117
+
118
+ @exc = ExceptionState.new @state, "", ScratchPad.recorded
102
119
  end
103
120
 
104
121
  it "returns a string representation of the exception backtrace" do
105
- exc = ExceptionState.new @state, "", @exception
106
- exc.backtrace.should be_kind_of(String)
122
+ @exc.backtrace.should be_kind_of(String)
107
123
  end
108
124
 
109
- # TODO: spec the filtering of the backtrace so mspec files don't display
125
+ it "strips MSpec files from the backtrace" do
126
+ @exc.backtrace.split("\n").each do |line|
127
+ line.should_not =~ ExceptionState::PATH
128
+ end
129
+ end
110
130
  end
@@ -389,3 +389,33 @@ benchmark(0.01825):The#fastest method today
389
389
  File.exist?(tmp("tags.txt")).should == false
390
390
  end
391
391
  end
392
+
393
+ describe MSpec, ".expectation" do
394
+ it "sets the flag that an expectation has been reported" do
395
+ MSpec.clear_expectations
396
+ MSpec.expectation?.should be_false
397
+ MSpec.expectation
398
+ MSpec.expectation?.should be_true
399
+ end
400
+ end
401
+
402
+ describe MSpec, ".expectation?" do
403
+ it "returns true if an expectation has been reported" do
404
+ MSpec.expectation
405
+ MSpec.expectation?.should be_true
406
+ end
407
+
408
+ it "returns false if an expectation has not been reported" do
409
+ MSpec.clear_expectations
410
+ MSpec.expectation?.should be_false
411
+ end
412
+ end
413
+
414
+ describe MSpec, ".clear_expectations" do
415
+ it "clears the flag that an expectation has been reported" do
416
+ MSpec.expectation
417
+ MSpec.expectation?.should be_true
418
+ MSpec.clear_expectations
419
+ MSpec.expectation?.should be_false
420
+ end
421
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Ford