mspec 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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