mspec 1.0.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/LICENSE +22 -0
- data/README +101 -0
- data/Rakefile +44 -0
- data/bin/mkspec +7 -0
- data/bin/mspec +7 -0
- data/bin/mspec-ci +8 -0
- data/bin/mspec-run +8 -0
- data/bin/mspec-tag +8 -0
- data/lib/mspec.rb +6 -0
- data/lib/mspec/commands/mkspec.rb +147 -0
- data/lib/mspec/commands/mspec-ci.rb +71 -0
- data/lib/mspec/commands/mspec-run.rb +80 -0
- data/lib/mspec/commands/mspec-tag.rb +87 -0
- data/lib/mspec/commands/mspec.rb +143 -0
- data/lib/mspec/expectations.rb +2 -0
- data/lib/mspec/expectations/expectations.rb +12 -0
- data/lib/mspec/expectations/should.rb +23 -0
- data/lib/mspec/guards.rb +13 -0
- data/lib/mspec/guards/bug.rb +27 -0
- data/lib/mspec/guards/compliance.rb +18 -0
- data/lib/mspec/guards/conflict.rb +16 -0
- data/lib/mspec/guards/endian.rb +40 -0
- data/lib/mspec/guards/extensions.rb +12 -0
- data/lib/mspec/guards/guard.rb +120 -0
- data/lib/mspec/guards/noncompliance.rb +12 -0
- data/lib/mspec/guards/platform.rb +38 -0
- data/lib/mspec/guards/quarantine.rb +15 -0
- data/lib/mspec/guards/runner.rb +30 -0
- data/lib/mspec/guards/superuser.rb +15 -0
- data/lib/mspec/guards/support.rb +12 -0
- data/lib/mspec/guards/version.rb +40 -0
- data/lib/mspec/helpers.rb +6 -0
- data/lib/mspec/helpers/bignum.rb +5 -0
- data/lib/mspec/helpers/const_lookup.rb +5 -0
- data/lib/mspec/helpers/flunk.rb +5 -0
- data/lib/mspec/helpers/io.rb +13 -0
- data/lib/mspec/helpers/scratch.rb +17 -0
- data/lib/mspec/helpers/tmp.rb +32 -0
- data/lib/mspec/matchers.rb +16 -0
- data/lib/mspec/matchers/base.rb +95 -0
- data/lib/mspec/matchers/be_ancestor_of.rb +24 -0
- data/lib/mspec/matchers/be_close.rb +27 -0
- data/lib/mspec/matchers/be_empty.rb +20 -0
- data/lib/mspec/matchers/be_false.rb +20 -0
- data/lib/mspec/matchers/be_kind_of.rb +24 -0
- data/lib/mspec/matchers/be_nil.rb +20 -0
- data/lib/mspec/matchers/be_true.rb +20 -0
- data/lib/mspec/matchers/complain.rb +56 -0
- data/lib/mspec/matchers/eql.rb +26 -0
- data/lib/mspec/matchers/equal.rb +26 -0
- data/lib/mspec/matchers/equal_utf16.rb +34 -0
- data/lib/mspec/matchers/include.rb +32 -0
- data/lib/mspec/matchers/output.rb +67 -0
- data/lib/mspec/matchers/output_to_fd.rb +71 -0
- data/lib/mspec/matchers/raise_error.rb +48 -0
- data/lib/mspec/mocks.rb +3 -0
- data/lib/mspec/mocks/mock.rb +123 -0
- data/lib/mspec/mocks/object.rb +28 -0
- data/lib/mspec/mocks/proxy.rb +112 -0
- data/lib/mspec/runner.rb +13 -0
- data/lib/mspec/runner/actions.rb +6 -0
- data/lib/mspec/runner/actions/debug.rb +17 -0
- data/lib/mspec/runner/actions/filter.rb +40 -0
- data/lib/mspec/runner/actions/gdb.rb +17 -0
- data/lib/mspec/runner/actions/tag.rb +97 -0
- data/lib/mspec/runner/actions/tally.rb +80 -0
- data/lib/mspec/runner/actions/timer.rb +22 -0
- data/lib/mspec/runner/filters.rb +4 -0
- data/lib/mspec/runner/filters/match.rb +22 -0
- data/lib/mspec/runner/filters/profile.rb +54 -0
- data/lib/mspec/runner/filters/regexp.rb +7 -0
- data/lib/mspec/runner/filters/tag.rb +29 -0
- data/lib/mspec/runner/formatters.rb +7 -0
- data/lib/mspec/runner/formatters/dotted.rb +81 -0
- data/lib/mspec/runner/formatters/html.rb +87 -0
- data/lib/mspec/runner/formatters/specdoc.rb +27 -0
- data/lib/mspec/runner/formatters/spinner.rb +89 -0
- data/lib/mspec/runner/formatters/summary.rb +8 -0
- data/lib/mspec/runner/formatters/unit.rb +25 -0
- data/lib/mspec/runner/formatters/yaml.rb +43 -0
- data/lib/mspec/runner/mspec.rb +232 -0
- data/lib/mspec/runner/object.rb +20 -0
- data/lib/mspec/runner/shared.rb +12 -0
- data/lib/mspec/runner/state.rb +116 -0
- data/lib/mspec/runner/tag.rb +20 -0
- data/lib/mspec/utils/name_map.rb +130 -0
- data/lib/mspec/utils/options.rb +344 -0
- data/lib/mspec/utils/script.rb +77 -0
- data/lib/mspec/version.rb +3 -0
- data/spec/commands/mkspec_spec.rb +321 -0
- data/spec/commands/mspec_ci_spec.rb +139 -0
- data/spec/commands/mspec_run_spec.rb +146 -0
- data/spec/commands/mspec_spec.rb +359 -0
- data/spec/commands/mspec_tag_spec.rb +131 -0
- data/spec/expectations/expectations_spec.rb +16 -0
- data/spec/expectations/should_spec.rb +99 -0
- data/spec/guards/bug_spec.rb +137 -0
- data/spec/guards/compliance_spec.rb +70 -0
- data/spec/guards/conflict_spec.rb +20 -0
- data/spec/guards/endian_spec.rb +42 -0
- data/spec/guards/extensions_spec.rb +36 -0
- data/spec/guards/guard_spec.rb +355 -0
- data/spec/guards/noncompliance_spec.rb +36 -0
- data/spec/guards/platform_spec.rb +84 -0
- data/spec/guards/quarantine_spec.rb +19 -0
- data/spec/guards/runner_spec.rb +75 -0
- data/spec/guards/superuser_spec.rb +22 -0
- data/spec/guards/support_spec.rb +22 -0
- data/spec/guards/version_spec.rb +133 -0
- data/spec/helpers/bignum_spec.rb +11 -0
- data/spec/helpers/const_lookup_spec.rb +19 -0
- data/spec/helpers/flunk_spec.rb +15 -0
- data/spec/helpers/io_spec.rb +34 -0
- data/spec/helpers/scratch_spec.rb +22 -0
- data/spec/helpers/tmp_spec.rb +72 -0
- data/spec/matchers/base_spec.rb +180 -0
- data/spec/matchers/be_ancestor_of_spec.rb +28 -0
- data/spec/matchers/be_close_spec.rb +46 -0
- data/spec/matchers/be_empty_spec.rb +26 -0
- data/spec/matchers/be_false_spec.rb +28 -0
- data/spec/matchers/be_kind_of_spec.rb +29 -0
- data/spec/matchers/be_nil_spec.rb +27 -0
- data/spec/matchers/be_true_spec.rb +28 -0
- data/spec/matchers/complain_spec.rb +52 -0
- data/spec/matchers/eql_spec.rb +33 -0
- data/spec/matchers/equal_spec.rb +33 -0
- data/spec/matchers/equal_utf16_spec.rb +47 -0
- data/spec/matchers/include_spec.rb +37 -0
- data/spec/matchers/output_spec.rb +74 -0
- data/spec/matchers/output_to_fd_spec.rb +33 -0
- data/spec/matchers/raise_error_spec.rb +56 -0
- data/spec/mocks/mock_spec.rb +272 -0
- data/spec/mocks/proxy_spec.rb +259 -0
- data/spec/runner/actions/debug_spec.rb +61 -0
- data/spec/runner/actions/filter_spec.rb +84 -0
- data/spec/runner/actions/gdb_spec.rb +61 -0
- data/spec/runner/actions/tag_spec.rb +253 -0
- data/spec/runner/actions/tally_spec.rb +107 -0
- data/spec/runner/actions/timer_spec.rb +42 -0
- data/spec/runner/filters/a.yaml +4 -0
- data/spec/runner/filters/b.yaml +11 -0
- data/spec/runner/filters/match_spec.rb +44 -0
- data/spec/runner/filters/profile_spec.rb +117 -0
- data/spec/runner/filters/regexp_spec.rb +13 -0
- data/spec/runner/filters/tag_spec.rb +77 -0
- data/spec/runner/formatters/dotted_spec.rb +184 -0
- data/spec/runner/formatters/html_spec.rb +191 -0
- data/spec/runner/formatters/specdoc_spec.rb +57 -0
- data/spec/runner/formatters/spinner_spec.rb +78 -0
- data/spec/runner/formatters/summary_spec.rb +29 -0
- data/spec/runner/formatters/unit_spec.rb +71 -0
- data/spec/runner/formatters/yaml_spec.rb +123 -0
- data/spec/runner/mspec_spec.rb +393 -0
- data/spec/runner/shared_spec.rb +41 -0
- data/spec/runner/state_spec.rb +535 -0
- data/spec/runner/tag_spec.rb +93 -0
- data/spec/runner/tags.txt +3 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/utils/name_map_spec.rb +178 -0
- data/spec/utils/options_spec.rb +862 -0
- data/spec/utils/script_spec.rb +240 -0
- metadata +217 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'mspec/expectations/expectations'
|
|
2
|
+
require 'mspec/runner/formatters/dotted'
|
|
3
|
+
|
|
4
|
+
class UnitdiffFormatter < DottedFormatter
|
|
5
|
+
def finish
|
|
6
|
+
print "\n\n#{@timer.format}\n"
|
|
7
|
+
count = 0
|
|
8
|
+
@states.each do |state|
|
|
9
|
+
state.exceptions.each do |msg, exc|
|
|
10
|
+
outcome = failure?(state) ? "FAILED" : "ERROR"
|
|
11
|
+
print "\n#{count += 1})\n#{state.description} #{outcome}\n"
|
|
12
|
+
print "Exception occurred during: #{msg}\n" if msg
|
|
13
|
+
print((exc.message.empty? ? "<No message>" : exc.message) + ": \n")
|
|
14
|
+
print backtrace(exc)
|
|
15
|
+
print "\n"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
print "\n#{@tally.format}\n"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def backtrace(exc)
|
|
22
|
+
exc.backtrace && exc.backtrace.join("\n")
|
|
23
|
+
end
|
|
24
|
+
private :backtrace
|
|
25
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'mspec/expectations/expectations'
|
|
2
|
+
require 'mspec/runner/formatters/dotted'
|
|
3
|
+
|
|
4
|
+
class YamlFormatter < DottedFormatter
|
|
5
|
+
def initialize(out=nil)
|
|
6
|
+
@states = []
|
|
7
|
+
@out = $stdout
|
|
8
|
+
|
|
9
|
+
if out.nil?
|
|
10
|
+
@finish = $stdout
|
|
11
|
+
else
|
|
12
|
+
@finish = File.open out, "w"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def switch
|
|
17
|
+
@out = @finish
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def finish
|
|
21
|
+
switch
|
|
22
|
+
|
|
23
|
+
print "---\n"
|
|
24
|
+
print "exceptions:\n"
|
|
25
|
+
@states.each do |state|
|
|
26
|
+
state.exceptions.each do |msg, exc|
|
|
27
|
+
outcome = failure?(state) ? "FAILED" : "ERROR"
|
|
28
|
+
str = "#{state.description} #{outcome}\n"
|
|
29
|
+
str << "#{exc.class.name} occurred during: #{msg}\n" if msg
|
|
30
|
+
str << message(exc)
|
|
31
|
+
str << backtrace(exc)
|
|
32
|
+
print "- ", str.inspect, "\n"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
print "time: ", @timer.elapsed, "\n"
|
|
37
|
+
print "files: ", @tally.counter.files, "\n"
|
|
38
|
+
print "examples: ", @tally.counter.examples, "\n"
|
|
39
|
+
print "expectations: ", @tally.counter.expectations, "\n"
|
|
40
|
+
print "failures: ", @tally.counter.failures, "\n"
|
|
41
|
+
print "errors: ", @tally.counter.errors, "\n"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
|
|
2
|
+
require 'mspec/runner/state'
|
|
3
|
+
require 'mspec/runner/tag'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
|
|
6
|
+
module MSpec
|
|
7
|
+
|
|
8
|
+
@exit = nil
|
|
9
|
+
@start = nil
|
|
10
|
+
@enter = nil
|
|
11
|
+
@before = nil
|
|
12
|
+
@after = nil
|
|
13
|
+
@leave = nil
|
|
14
|
+
@finish = nil
|
|
15
|
+
@exclude = nil
|
|
16
|
+
@include = nil
|
|
17
|
+
@leave = nil
|
|
18
|
+
@mode = nil
|
|
19
|
+
@load = nil
|
|
20
|
+
@unload = nil
|
|
21
|
+
@randomize = nil
|
|
22
|
+
@expectation = nil
|
|
23
|
+
|
|
24
|
+
def self.describe(mod, msg=nil, &block)
|
|
25
|
+
stack.push RunState.new
|
|
26
|
+
|
|
27
|
+
current.describe(mod, msg, &block)
|
|
28
|
+
current.process
|
|
29
|
+
|
|
30
|
+
stack.pop
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.process
|
|
34
|
+
actions :start
|
|
35
|
+
files
|
|
36
|
+
actions :finish
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.files
|
|
40
|
+
return unless files = retrieve(:files)
|
|
41
|
+
|
|
42
|
+
shuffle files if randomize?
|
|
43
|
+
files.each do |file|
|
|
44
|
+
store :file, file
|
|
45
|
+
actions :load
|
|
46
|
+
protect("loading #{file}") { Kernel.load file }
|
|
47
|
+
actions :unload
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.actions(action, *args)
|
|
52
|
+
actions = retrieve(action)
|
|
53
|
+
actions.each { |obj| obj.send action, *args } if actions
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.register_exit(code)
|
|
57
|
+
store :exit, code
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.exit_code
|
|
61
|
+
retrieve(:exit).to_i
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.register_files(files)
|
|
65
|
+
store :files, files
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.register_tags_path(path)
|
|
69
|
+
store :tags_path, path
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.register_mode(mode)
|
|
73
|
+
store :mode, mode
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.retrieve(symbol)
|
|
77
|
+
instance_variable_get :"@#{symbol}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.store(symbol, value)
|
|
81
|
+
instance_variable_set :"@#{symbol}", value
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# This method is used for registering actions that are
|
|
85
|
+
# run at particular points in the spec cycle:
|
|
86
|
+
# :start before any specs are run
|
|
87
|
+
# :load before a spec file is loaded
|
|
88
|
+
# :enter before a describe block is run
|
|
89
|
+
# :before before a single spec is run
|
|
90
|
+
# :expectation before a 'should', 'should_receive', etc.
|
|
91
|
+
# :after after a single spec is run
|
|
92
|
+
# :leave after a describe block is run
|
|
93
|
+
# :unload after a spec file is run
|
|
94
|
+
# :finish after all specs are run
|
|
95
|
+
#
|
|
96
|
+
# Objects registered as actions above should respond to
|
|
97
|
+
# a method of the same name. For example, if an object
|
|
98
|
+
# is registered as a :start action, it should respond to
|
|
99
|
+
# a #start method call.
|
|
100
|
+
#
|
|
101
|
+
# Additionally, there are two "action" lists for
|
|
102
|
+
# filtering specs:
|
|
103
|
+
# :include return true if the spec should be run
|
|
104
|
+
# :exclude return true if the spec should NOT be run
|
|
105
|
+
#
|
|
106
|
+
def self.register(symbol, action)
|
|
107
|
+
unless value = retrieve(symbol)
|
|
108
|
+
value = store symbol, []
|
|
109
|
+
end
|
|
110
|
+
value << action unless value.include? action
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.unregister(symbol, action)
|
|
114
|
+
if value = retrieve(symbol)
|
|
115
|
+
value.delete action
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.protect(msg, &block)
|
|
120
|
+
begin
|
|
121
|
+
instance_eval(&block)
|
|
122
|
+
rescue Exception => e
|
|
123
|
+
register_exit 1
|
|
124
|
+
if current and current.state
|
|
125
|
+
current.state.exceptions << [msg, e]
|
|
126
|
+
else
|
|
127
|
+
STDERR.write "\nAn exception occurred in #{msg}:\n#{e.class}: #{e.message.inspect}\n"
|
|
128
|
+
STDERR.write "#{e.backtrace.join "\n"}"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def self.stack
|
|
134
|
+
@stack ||= []
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def self.current
|
|
138
|
+
stack.last
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def self.verify_mode?
|
|
142
|
+
@mode == :verify
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def self.report_mode?
|
|
146
|
+
@mode == :report
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def self.pretend_mode?
|
|
150
|
+
@mode == :pretend
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.randomize(flag=true)
|
|
154
|
+
@randomize = flag
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.randomize?
|
|
158
|
+
@randomize == true
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def self.shuffle(ary)
|
|
162
|
+
return if ary.empty?
|
|
163
|
+
|
|
164
|
+
size = ary.size
|
|
165
|
+
size.times do |i|
|
|
166
|
+
r = rand(size - i - 1)
|
|
167
|
+
ary[i], ary[r] = ary[r], ary[i]
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.tags_path
|
|
172
|
+
retrieve(:tags_path) || "spec/tags"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def self.tags_file
|
|
176
|
+
path = tags_path
|
|
177
|
+
file = retrieve :file
|
|
178
|
+
tags_file = File.basename(file, '.*').sub(/_spec$/, '_tags') + '.txt'
|
|
179
|
+
|
|
180
|
+
m = file.match %r[.*spec/(.*)/.*_spec.rb]
|
|
181
|
+
path = File.join(path, m[1]) if m
|
|
182
|
+
File.join path, tags_file
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def self.read_tags(*keys)
|
|
186
|
+
tags = []
|
|
187
|
+
file = tags_file
|
|
188
|
+
if File.exist? file
|
|
189
|
+
File.open(file, "r") do |f|
|
|
190
|
+
f.each_line do |line|
|
|
191
|
+
tag = SpecTag.new line.chomp
|
|
192
|
+
tags << tag if keys.include? tag.tag
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
tags
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def self.write_tag(tag)
|
|
200
|
+
string = tag.to_s
|
|
201
|
+
file = tags_file
|
|
202
|
+
path = File.dirname file
|
|
203
|
+
FileUtils.mkdir_p(path) unless File.exist?(path)
|
|
204
|
+
if File.exist? file
|
|
205
|
+
File.open(file, "r") do |f|
|
|
206
|
+
f.each_line { |line| return false if line.chomp == string }
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
File.open(file, "a") { |f| f.puts string }
|
|
210
|
+
return true
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def self.delete_tag(tag)
|
|
214
|
+
deleted = false
|
|
215
|
+
pattern = /#{tag.tag}.*#{Regexp.escape tag.description}/
|
|
216
|
+
file = tags_file
|
|
217
|
+
if File.exist? file
|
|
218
|
+
lines = IO.readlines(file)
|
|
219
|
+
File.open(file, "w") do |f|
|
|
220
|
+
lines.each do |line|
|
|
221
|
+
unless pattern =~ line.chomp
|
|
222
|
+
f.puts line
|
|
223
|
+
else
|
|
224
|
+
deleted = true
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
File.delete file unless File.size? file
|
|
229
|
+
end
|
|
230
|
+
return deleted
|
|
231
|
+
end
|
|
232
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class Object
|
|
2
|
+
def before(at=:each, &block)
|
|
3
|
+
MSpec.current.before at, &block
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def after(at=:each, &block)
|
|
7
|
+
MSpec.current.after at, &block
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def describe(mod, msg=nil, &block)
|
|
11
|
+
MSpec.describe mod, msg, &block
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def it(msg, &block)
|
|
15
|
+
MSpec.current.it msg, &block
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
alias_method :context, :describe
|
|
19
|
+
alias_method :specify, :it
|
|
20
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'mspec/runner/mspec'
|
|
2
|
+
|
|
3
|
+
class RunState
|
|
4
|
+
def initialize
|
|
5
|
+
@start = []
|
|
6
|
+
@before = []
|
|
7
|
+
@after = []
|
|
8
|
+
@finish = []
|
|
9
|
+
@spec = []
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def state
|
|
13
|
+
@state
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def before(at=:each, &block)
|
|
17
|
+
case at
|
|
18
|
+
when :each
|
|
19
|
+
@before << block
|
|
20
|
+
when :all
|
|
21
|
+
@start << block
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def after(at=:each, &block)
|
|
26
|
+
case at
|
|
27
|
+
when :each
|
|
28
|
+
@after << block
|
|
29
|
+
when :all
|
|
30
|
+
@finish << block
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def it(desc, &block)
|
|
35
|
+
state = SpecState.new @describe, desc
|
|
36
|
+
@spec << [desc, block, state] unless state.filtered?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def describe(mod, desc=nil, &block)
|
|
40
|
+
@describe = desc ? "#{mod} #{desc}" : mod.to_s
|
|
41
|
+
@block = block
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def protect(what, blocks, check=true)
|
|
45
|
+
return if check and MSpec.pretend_mode?
|
|
46
|
+
Array(blocks).each { |block| MSpec.protect what, &block }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def process
|
|
50
|
+
protect @describe, @block, false
|
|
51
|
+
return unless @spec.any? { |desc, spec, state| state.unfiltered? }
|
|
52
|
+
|
|
53
|
+
MSpec.shuffle @spec if MSpec.randomize?
|
|
54
|
+
MSpec.actions :enter, @describe
|
|
55
|
+
protect "before :all", @start
|
|
56
|
+
@spec.each do |desc, spec, state|
|
|
57
|
+
@state = state
|
|
58
|
+
MSpec.actions :before, state
|
|
59
|
+
protect "before :each", @before
|
|
60
|
+
protect nil, spec
|
|
61
|
+
protect "after :each", @after
|
|
62
|
+
protect "Mock.verify_count", lambda { Mock.verify_count }
|
|
63
|
+
protect "Mock.cleanup", lambda { Mock.cleanup }
|
|
64
|
+
MSpec.actions :after, state
|
|
65
|
+
@state = nil
|
|
66
|
+
end
|
|
67
|
+
protect "after :all", @finish
|
|
68
|
+
MSpec.actions :leave
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class SpecState
|
|
73
|
+
def initialize(describe, it)
|
|
74
|
+
@describe = describe
|
|
75
|
+
@it = it
|
|
76
|
+
@unfiltered = nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def describe
|
|
80
|
+
@describe
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def it
|
|
84
|
+
@it
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def description
|
|
88
|
+
@description ||= "#{@describe} #{@it}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def exceptions
|
|
92
|
+
@exceptions ||= []
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def exception?
|
|
96
|
+
not exceptions.empty?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def unfiltered?
|
|
100
|
+
unless @unfiltered
|
|
101
|
+
incl = MSpec.retrieve(:include) || []
|
|
102
|
+
excl = MSpec.retrieve(:exclude) || []
|
|
103
|
+
@unfiltered = incl.empty? || incl.any? { |f| f === description }
|
|
104
|
+
@unfiltered &&= excl.empty? || !excl.any? { |f| f === description }
|
|
105
|
+
end
|
|
106
|
+
@unfiltered
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def filtered?
|
|
110
|
+
not unfiltered?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def failure?(exception)
|
|
114
|
+
exception.is_a?(ExpectationNotMetError)
|
|
115
|
+
end
|
|
116
|
+
end
|