baretest 0.2.4 → 0.4.0.pre1
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.txt +6 -6
- data/MANIFEST.txt +40 -18
- data/README.rdoc +8 -1
- data/bin/baretest +126 -118
- data/doc/baretest.rdoc +1 -1
- data/doc/mocking_stubbing_test_doubles.rdoc +31 -3
- data/doc/news/news-0.3.0.rdoc +7 -0
- data/doc/quickref.rdoc +74 -28
- data/doc/whats_going_on.rdoc +5 -0
- data/doc/writing_tests.rdoc +25 -13
- data/examples/components/rack-test.rb +17 -0
- data/examples/{tests/irb_mode → irb_mode}/failures.rb +0 -0
- data/examples/rake/test.rake +40 -0
- data/examples/tests/01_basics_I.rb +34 -0
- data/examples/tests/02_basics_II_helpers.rb +25 -0
- data/examples/tests/03_basics_III_setup_and_teardown.rb +53 -0
- data/examples/tests/04_advanced_I_dependencies.rb +31 -0
- data/examples/tests/05_advanced_II_tags.rb +12 -0
- data/examples/tests/06_advanced_III_requires.rb +21 -0
- data/examples/tests/07_advanced_IV_components.rb +48 -0
- data/examples/tests/08_expert_I_setup_variants.rb +46 -0
- data/lib/baretest.rb +142 -21
- data/lib/baretest/assertion.rb +83 -92
- data/lib/baretest/assertion/context.rb +9 -0
- data/lib/baretest/assertion/support.rb +88 -61
- data/lib/baretest/commandline.rb +268 -0
- data/lib/baretest/formatter.rb +58 -0
- data/lib/baretest/invalidselectors.rb +24 -0
- data/lib/baretest/irb_mode.rb +100 -58
- data/lib/baretest/persistence.rb +94 -0
- data/lib/baretest/run.rb +138 -37
- data/lib/baretest/run/cli.rb +97 -43
- data/lib/baretest/run/minimal.rb +2 -1
- data/lib/baretest/run/none.rb +21 -0
- data/lib/baretest/run/xml.rb +21 -19
- data/lib/baretest/setup.rb +2 -0
- data/lib/baretest/status.rb +93 -0
- data/lib/baretest/suite.rb +185 -59
- data/lib/baretest/uid.rb +51 -0
- data/lib/baretest/use/mocha.rb +24 -0
- data/lib/baretest/use/rack_test.rb +9 -0
- data/lib/baretest/use/rr.rb +17 -0
- data/lib/baretest/version.rb +18 -4
- data/lib/command.rb +36 -0
- data/lib/command/argument.rb +11 -0
- data/lib/command/decoratinghash.rb +31 -0
- data/lib/command/definition.rb +294 -0
- data/lib/command/directorynotfounderror.rb +11 -0
- data/lib/command/env.rb +11 -0
- data/lib/command/filenotfounderror.rb +11 -0
- data/lib/command/kernel.rb +14 -0
- data/lib/command/nodirectoryerror.rb +11 -0
- data/lib/command/nofileerror.rb +11 -0
- data/lib/command/option.rb +16 -0
- data/lib/command/parser.rb +145 -0
- data/lib/command/result.rb +11 -0
- data/lib/command/types.rb +33 -0
- data/lib/command/version.rb +28 -0
- data/test/setup.rb +3 -0
- data/test/suite/lib/baretest.rb +0 -178
- data/test/suite/lib/baretest/assertion.rb +133 -112
- data/test/suite/lib/baretest/assertion/context.rb +40 -0
- data/test/suite/lib/baretest/assertion/failure.rb +19 -0
- data/test/suite/lib/baretest/assertion/skip.rb +19 -0
- data/test/suite/lib/baretest/assertion/support.rb +366 -84
- data/test/suite/lib/baretest/run.rb +114 -15
- data/test/suite/lib/baretest/suite.rb +70 -29
- metadata +46 -24
- data/examples/test.rake +0 -65
- data/examples/tests/mock_developer/test/helper/mocks.rb +0 -0
- data/examples/tests/mock_developer/test/setup.rb +0 -57
- data/examples/tests/mock_developer/test/suite/mock_demo.rb +0 -19
- data/examples/tests/overview/test.rb +0 -89
- data/examples/tests/variations/variations_01.rb +0 -14
- data/examples/tests/variations/variations_02.rb +0 -19
- data/examples/tests/variations/variations_03.rb +0 -19
- data/lib/baretest/mocha.rb +0 -18
- data/lib/baretest/rr.rb +0 -16
- data/lib/baretest/run/errors.rb +0 -49
- data/lib/baretest/skipped.rb +0 -15
- data/lib/baretest/skipped/assertion.rb +0 -20
- data/lib/baretest/skipped/suite.rb +0 -49
- data/test/external/bootstraptest.rb +0 -5
- data/test/external/bootstrapwrap.rb +0 -2
- data/test/helper/mocks.rb +0 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# pretend the lib 'baretest/demo/06_advanced_requires' was already loaded
|
2
|
+
$LOADED_FEATURES << 'baretest/demo/06_advanced_requires'
|
3
|
+
|
4
|
+
|
5
|
+
# You can baretest tell that a suite depends on an external lib using the
|
6
|
+
# :requires option, it accepts either a String or an Array of strings.
|
7
|
+
BareTest.suite do
|
8
|
+
# Baretest will load all libraries mentioned in :requires via a standard
|
9
|
+
# Kernel.require upon suite definition
|
10
|
+
suite "Depends on an existing lib", :requires => 'baretest/demo/06_advanced_requires' do
|
11
|
+
assert "Succeeds because library-dependency is met" do
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
suite "Depends on a missing lib", :requires => 'baretest/demo/06_advanced_requires_missing' do
|
17
|
+
assert "Skipped because library-dependency is NOT met" do
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# This code should be in 'baretest/use/demo_component', somewhere in rubys
|
2
|
+
# $LOAD_PATH.
|
3
|
+
module DemoComponent
|
4
|
+
module DemoMethods
|
5
|
+
def demo
|
6
|
+
demo_component = @demo_component
|
7
|
+
@demo_component = :executed
|
8
|
+
same(:setup, demo_component)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
BareTest.new_component :demo_component do
|
14
|
+
# Make our components' assertion helpers available in assertions
|
15
|
+
BareTest::Assertion::Context.send :include, DemoComponent::DemoMethods
|
16
|
+
|
17
|
+
setup do
|
18
|
+
@demo_component = :setup
|
19
|
+
end
|
20
|
+
|
21
|
+
teardown do
|
22
|
+
same(:executed, @demo_component, "@demo_component after the assertion")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
BareTest.suite do
|
28
|
+
suite "Using DemoComponent", :use => :demo_component do
|
29
|
+
assert "Successful assertions must use the 'demo' method" do
|
30
|
+
demo
|
31
|
+
end
|
32
|
+
|
33
|
+
assert "Fails if 'demo' is not invoked, even if otherwise successful" do
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
assert "Fails if @demo_component was changed prior to calling 'demo'" do
|
38
|
+
@demo_component = :unexpected
|
39
|
+
demo
|
40
|
+
end
|
41
|
+
|
42
|
+
assert "Fails if @demo_component was changed after to calling 'demo'" do
|
43
|
+
demo
|
44
|
+
@demo_component = :unexpected
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# The thing we want to test
|
2
|
+
class String
|
3
|
+
def numeric?
|
4
|
+
self =~ /[+-]?(?:[1-9]\d*|0)(?:\.\d+)?(?:[eE][+-]?\d+)?/
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
BareTest.suite do
|
9
|
+
suite "Variations - Notation I" do
|
10
|
+
setup :number, '123' do |number|
|
11
|
+
@number = '123'
|
12
|
+
end
|
13
|
+
|
14
|
+
setup :number, '-123' do |number|
|
15
|
+
@number = '-123'
|
16
|
+
end
|
17
|
+
|
18
|
+
setup :number, '1.23' do |number|
|
19
|
+
@number = '1.23'
|
20
|
+
end
|
21
|
+
|
22
|
+
assert ":number should be a numeric" do
|
23
|
+
@number.numeric?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
suite "Variations - Notation II" do
|
28
|
+
setup :number, %w[123 -123 1.23 -1.23 1e3 -1e3 1e-3 -1e-3] do |number|
|
29
|
+
@number = number
|
30
|
+
end
|
31
|
+
|
32
|
+
assert ":number should be a numeric" do
|
33
|
+
@number.numeric?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
suite "Variations - Notation III" do
|
38
|
+
setup :number, {'"123"' => "123", '"1.23"' => "1.23", '"1e3"' => "1e3"} do |number|
|
39
|
+
@number = number
|
40
|
+
end
|
41
|
+
|
42
|
+
assert ":number should be a numeric" do
|
43
|
+
@number.numeric?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/baretest.rb
CHANGED
@@ -7,6 +7,9 @@
|
|
7
7
|
|
8
8
|
|
9
9
|
require 'baretest/assertion'
|
10
|
+
require 'baretest/commandline'
|
11
|
+
require 'baretest/formatter'
|
12
|
+
require 'baretest/invalidselectors'
|
10
13
|
require 'baretest/irb_mode'
|
11
14
|
require 'baretest/run'
|
12
15
|
require 'baretest/suite'
|
@@ -17,7 +20,45 @@ require 'ruby/kernel'
|
|
17
20
|
|
18
21
|
|
19
22
|
module BareTest
|
23
|
+
# A lookup table to test which of two states is more important
|
24
|
+
# (MoreImportantStatus[[a,b]] # => a or b)
|
25
|
+
MoreImportantStatus = {}
|
26
|
+
|
27
|
+
# All states in the order of relevance, more relevant states first
|
28
|
+
StatusOrder = :error,
|
29
|
+
:failure,
|
30
|
+
:pending,
|
31
|
+
:manually_skipped,
|
32
|
+
:dependency_missing,
|
33
|
+
:library_missing,
|
34
|
+
:component_missing,
|
35
|
+
:ignored,
|
36
|
+
:success
|
37
|
+
|
38
|
+
StatusOrder.combination(2) do |x,y|
|
39
|
+
more_important = StatusOrder.index(x) < StatusOrder.index(y) ? x : y
|
40
|
+
MoreImportantStatus[[x,y]] = more_important
|
41
|
+
MoreImportantStatus[[y,x]] = more_important
|
42
|
+
end
|
43
|
+
StatusOrder.each do |status|
|
44
|
+
MoreImportantStatus[[status,status]] = status
|
45
|
+
MoreImportantStatus[[nil,status]] = status
|
46
|
+
MoreImportantStatus[[status,nil]] = status
|
47
|
+
end
|
48
|
+
|
49
|
+
# The standard glob used by baretest to load test files
|
50
|
+
# :nodoc:
|
51
|
+
DefaultInitialPositiveGlob = 'test/{suite,unit,isolation,integration,system}/**/*.rb'
|
52
|
+
|
53
|
+
# Selectors that are valid to be passed into process_selectors
|
54
|
+
# :nodoc:
|
55
|
+
ValidStateSelectors = [:new, :success, :failure, :error, :skipped, :pending]
|
56
|
+
|
20
57
|
class << self
|
58
|
+
# A hash of components - available via BareTest::use(name) and
|
59
|
+
# Suite#suite :use => name
|
60
|
+
attr_reader :components
|
61
|
+
|
21
62
|
# A hash of formatters (require-string => module) to be used with Test::Run.
|
22
63
|
attr_reader :format
|
23
64
|
|
@@ -33,6 +74,21 @@ module BareTest
|
|
33
74
|
attr_reader :required_file # :nodoc:
|
34
75
|
end
|
35
76
|
|
77
|
+
# Enure that the suite is run wiht a minimal version of baretest
|
78
|
+
def self.require_baretest(version)
|
79
|
+
if (version.split(".").map { |s| s.to_i } <=> BareTest::VERSION.to_a) == 0 then
|
80
|
+
abort "Requires baretest version #{version}, you have #{BareTest::VERSION}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Ensure that the suite is run with a minimal version of ruby
|
85
|
+
def self.require_ruby(version)
|
86
|
+
if (version.split(".").map { |s| s.to_i } <=> RUBY_VERSION.split(".").map { |s| s.to_i }) == 1 then
|
87
|
+
abort "Requires ruby version #{version}, you have #{RUBY_VERSION}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
36
92
|
# Loads all files in a test directory in order to load the suites and
|
37
93
|
# assertions. Used by the 'baretest' executable and the standard rake task.
|
38
94
|
#
|
@@ -44,16 +100,20 @@ module BareTest
|
|
44
100
|
def self.load_standard_test_files(opts={})
|
45
101
|
verbose = opts.delete(:verbose)
|
46
102
|
setup_path = opts.delete(:setup_path) || 'test/setup.rb'
|
103
|
+
lib_path = opts.delete(:lib_path) || 'test/lib'
|
47
104
|
chdir = opts.delete(:chdir) || '.'
|
48
|
-
files = opts.delete(:files)
|
105
|
+
files = opts.delete(:files)
|
106
|
+
files = [DefaultInitialPositiveGlob] if (files.nil? || files.empty?)
|
49
107
|
Dir.chdir(chdir) do
|
108
|
+
$LOAD_PATH.unshift(File.expand_path(lib_path)) if File.exist?(lib_path)
|
50
109
|
load(setup_path) if File.exist?(setup_path)
|
51
110
|
files.each do |glob|
|
52
111
|
glob = "#{glob}/**/*.rb" if File.directory?(glob)
|
53
112
|
Dir.glob(glob) { |path|
|
54
113
|
helper_path = path.sub(%r{^test/(suite|unit|integration|system)/}, 'test/helper/\1/')
|
55
|
-
|
56
|
-
|
114
|
+
exists = (helper_path != path && File.exist?(helper_path))
|
115
|
+
puts(exists ? "Loading helper file #{helper_path}" : "No helper file #{helper_path} to load") if verbose
|
116
|
+
load(helper_path) if exists
|
57
117
|
puts "Loading test file #{path}" if verbose
|
58
118
|
load(path)
|
59
119
|
}
|
@@ -61,10 +121,70 @@ module BareTest
|
|
61
121
|
end
|
62
122
|
end
|
63
123
|
|
124
|
+
# Determine which of the named states is the most important one (see
|
125
|
+
# StatusOrder)
|
126
|
+
def self.most_important_status(states)
|
127
|
+
(StatusOrder & states).first # requires Array#& to be stable (keep order of first operand)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Convert an array of selectors into a hash with those selectors preprocessed
|
131
|
+
# as far as possible.
|
132
|
+
# Example:
|
133
|
+
# BareTest.process_selectors %w[-some/**/glob/*.rb %failure :tag1 -:tag2]
|
134
|
+
# # => {
|
135
|
+
# # :files => ...an array with paths...,
|
136
|
+
# # :include_tags => [:tag1],
|
137
|
+
# # :exclude_tags => [:tag2],
|
138
|
+
# # :include_states => [:failure]
|
139
|
+
# # :exclude_states => nil,
|
140
|
+
# # }
|
141
|
+
def self.process_selectors(selectors, base_directory=".", default_initial_positive_glob=nil)
|
142
|
+
files = []
|
143
|
+
include_tags = []
|
144
|
+
exclude_tags = []
|
145
|
+
include_states = []
|
146
|
+
exclude_states = []
|
147
|
+
|
148
|
+
default_initial_positive_glob ||= DefaultInitialPositiveGlob
|
149
|
+
Dir.chdir(base_directory) do
|
150
|
+
selectors.each do |selector|
|
151
|
+
case selector
|
152
|
+
when /\A-%(.*)/ then exclude_states << $1.to_sym
|
153
|
+
when /\A-:(.*)/ then exclude_tags << $1.to_sym
|
154
|
+
when /\A\+?%(.*)/ then include_states << $1.to_sym
|
155
|
+
when /\A\+?:(.*)/ then include_tags << $1.to_sym
|
156
|
+
when /\A-(.*)/ then
|
157
|
+
files = Dir[default_initial_positive_glob] if files.empty? && default_initial_positive_glob
|
158
|
+
glob = File.directory?($1) ? "#{$1}/**/*.rb" : $1
|
159
|
+
files -= Dir[glob]
|
160
|
+
when /\A\+?(.*)/ then
|
161
|
+
glob = File.directory?(selector) ? "#{selector}/**/*.rb" : selector
|
162
|
+
files |= Dir[glob]
|
163
|
+
else
|
164
|
+
raise "Should never reach else - selector: #{selector.inspect}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
files = Dir[default_initial_positive_glob] if files.empty? && default_initial_positive_glob
|
168
|
+
files.map! do |path| File.expand_path(path) end
|
169
|
+
end
|
170
|
+
|
171
|
+
invalid_states = (include_states|exclude_states)-ValidStateSelectors
|
172
|
+
raise InvalidSelectors.new(invalid_states) unless invalid_states.empty?
|
173
|
+
|
174
|
+
return {
|
175
|
+
:files => files,
|
176
|
+
:include_tags => include_tags,
|
177
|
+
:exclude_tags => exclude_tags,
|
178
|
+
:include_states => include_states.empty? ? nil : include_states,
|
179
|
+
:exclude_states => exclude_states.empty? ? nil : exclude_states
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
64
183
|
# Initializes BareTest, is automatically called
|
65
184
|
#
|
66
185
|
# Needed for bootstrapped selftest
|
67
186
|
def self.init # :nodoc:
|
187
|
+
@components = {}
|
68
188
|
@format = {}
|
69
189
|
@extender = []
|
70
190
|
@toplevel_suite = BareTest::Suite.new
|
@@ -74,6 +194,17 @@ module BareTest
|
|
74
194
|
end
|
75
195
|
init
|
76
196
|
|
197
|
+
def self.component(name)
|
198
|
+
component = @components[name]
|
199
|
+
begin
|
200
|
+
require "baretest/use/#{name}"
|
201
|
+
rescue LoadError
|
202
|
+
else
|
203
|
+
component = @components[name]
|
204
|
+
end
|
205
|
+
component
|
206
|
+
end
|
207
|
+
|
77
208
|
# If no description was given, it adds the contained assertions and suites to the toplevel suite,
|
78
209
|
# if a description was given, a suite with the given description is created, added to the toplevel
|
79
210
|
# suite, and all the contained assertions and suites are added to the created suite.
|
@@ -87,26 +218,16 @@ module BareTest
|
|
87
218
|
end
|
88
219
|
end
|
89
220
|
|
90
|
-
#
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
def self.run_if_mainfile(description=nil, opts={}, &block)
|
96
|
-
suite(description, opts, &block)
|
97
|
-
if caller.first[/^[^:]*/] == $0 then # if is mainfile
|
98
|
-
run(:format => ENV['FORMAT'], :interactive => ENV['INTERACTIVE'])
|
99
|
-
end
|
221
|
+
# Create a new component for Suite's :use option (see BareTest::Suite::new)
|
222
|
+
def self.new_component(name, &block)
|
223
|
+
name = name.to_sym
|
224
|
+
raise ArgumentError, "Component named #{name.inspect} already exists" if @components.has_key?(name)
|
225
|
+
@components[name] = block
|
100
226
|
end
|
101
227
|
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
# Returns the Run instance.
|
106
|
-
def self.run(opts=nil)
|
107
|
-
runner = BareTest::Run.new(@toplevel_suite, opts)
|
108
|
-
runner.run_all
|
109
|
-
runner
|
228
|
+
# Shortcut for toplevel_suite.use. Preferably use the :use option instead.
|
229
|
+
def self.use(component)
|
230
|
+
@toplevel_suite.use(component)
|
110
231
|
end
|
111
232
|
end
|
112
233
|
|
data/lib/baretest/assertion.rb
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
require 'baretest/assertion/context'
|
10
10
|
require 'baretest/assertion/failure'
|
11
11
|
require 'baretest/assertion/skip'
|
12
|
+
require 'baretest/status'
|
12
13
|
|
13
14
|
|
14
15
|
|
@@ -30,42 +31,16 @@ module BareTest
|
|
30
31
|
# * Kernel#equal_unordered(a,b)
|
31
32
|
# * Enumerable#equal_unordered(other)
|
32
33
|
class Assertion
|
33
|
-
|
34
34
|
# The exceptions baretest will not rescue (NoMemoryError, SignalException, Interrupt
|
35
35
|
# and SystemExit)
|
36
36
|
PassthroughExceptions = [NoMemoryError, SignalException, Interrupt, SystemExit]
|
37
37
|
|
38
|
-
# An assertion has 5 possible states:
|
39
|
-
# :success:: The assertion passed. This means the block returned a trueish value.
|
40
|
-
# :failure:: The assertion failed. This means the block returned a falsish value.
|
41
|
-
# Alternatively it raised a Test::Failure (NOT YET IMPLEMENTED).
|
42
|
-
# The latter has the advantage that it can provide nicer diagnostics.
|
43
|
-
# :pending:: No block given to the assertion to be run
|
44
|
-
# :skipped:: If one of the parent suites is missing a dependency, its assertions
|
45
|
-
# will be skipped
|
46
|
-
# :error:: The assertion errored out. This means the block raised an exception
|
47
|
-
attr_reader :status
|
48
|
-
|
49
|
-
# If an exception occured in Assertion#execute, this will contain the
|
50
|
-
# Exception object raised.
|
51
|
-
attr_reader :exception
|
52
|
-
|
53
38
|
# The description of this assertion.
|
54
39
|
attr_reader :description
|
55
40
|
|
56
|
-
# The failure/error/skipping/pending reason.
|
57
|
-
attr_reader :reason
|
58
|
-
|
59
41
|
# The suite this assertion belongs to
|
60
42
|
attr_reader :suite
|
61
43
|
|
62
|
-
# The Context-instance the assertions setup, assert and teardown are run
|
63
|
-
attr_reader :context
|
64
|
-
|
65
|
-
# The Setup instances whose #block is to be executed before this assertion
|
66
|
-
# is ran
|
67
|
-
attr_accessor :setups
|
68
|
-
|
69
44
|
# The block specifying the assertion
|
70
45
|
attr_reader :block
|
71
46
|
|
@@ -85,90 +60,106 @@ module BareTest
|
|
85
60
|
# description:: A descriptive string about what this Assertion tests.
|
86
61
|
# &block:: The block definition. Without one, the Assertion will have a
|
87
62
|
# :pending status.
|
88
|
-
def initialize(suite, description, &block)
|
89
|
-
@suite
|
90
|
-
@description
|
91
|
-
@
|
92
|
-
@
|
93
|
-
|
63
|
+
def initialize(suite, description, opt=nil, &block)
|
64
|
+
@suite = suite
|
65
|
+
@description = (description || "No description given")
|
66
|
+
@block = block
|
67
|
+
@skipped = false
|
68
|
+
if opt then
|
69
|
+
skip_reason = opt[:skip]
|
70
|
+
skip(skip_reason == true ? "Tagged as skipped" : skip_reason) if skip_reason
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# An ID, usable for persistence
|
75
|
+
def id
|
76
|
+
@id ||= [
|
77
|
+
@description,
|
78
|
+
*(@suite && @suite.ancestors.map { |suite| suite.description })
|
79
|
+
].compact.join("\f")
|
94
80
|
end
|
95
81
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
@exception = nil
|
100
|
-
@context = ::BareTest::Assertion::Context.new(self)
|
82
|
+
# Returns whether this assertion has been marked as manually skipped.
|
83
|
+
def skipped?
|
84
|
+
!!@skipped
|
101
85
|
end
|
102
86
|
|
103
|
-
|
104
|
-
|
105
|
-
|
87
|
+
# Marks this assertion as manually skipped.
|
88
|
+
def skip(reason=nil)
|
89
|
+
@skipped ||= []
|
90
|
+
@skipped |= reason ? Array(reason) : ['Manually skipped']
|
91
|
+
end
|
92
|
+
|
93
|
+
# The description allows substitutes in the form ":identifier" and
|
94
|
+
# ":{identifier}" (the latter in case of ajanced characters that don't
|
95
|
+
# belong to the identifier, like ":{identifier}stuff").
|
96
|
+
# This method will interploate those substitutes.
|
97
|
+
# This is relevant with regards to setup variants.
|
98
|
+
def interpolated_description(substitutes)
|
99
|
+
if substitutes.empty? then
|
106
100
|
@description
|
107
101
|
else
|
108
|
-
substitutes = {}
|
109
|
-
setups.each do |setup| substitutes[setup.component] = setup.substitute end
|
110
102
|
@description.gsub(/:(?:#{substitutes.keys.join('|')})\b/) { |m|
|
111
103
|
substitutes[m[1..-1].to_sym]
|
112
104
|
}
|
113
105
|
end
|
114
106
|
end
|
115
107
|
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
108
|
+
# Returns a Status
|
109
|
+
# Executes with_setup, then the assertions defining block, and in the end
|
110
|
+
# and_teardown. Usually with_setup and and_teardown are supplied by the
|
111
|
+
# containing suite.
|
112
|
+
def execute(with_setup=nil, and_teardown=nil)
|
113
|
+
if @skipped then
|
114
|
+
status = Status.new(self, :manually_skipped)
|
115
|
+
elsif !@block
|
116
|
+
status = Status.new(self, :pending)
|
117
|
+
else
|
118
|
+
context = ::BareTest::Assertion::Context.new(self)
|
119
|
+
status = execute_phase(:setup, context, with_setup) if with_setup
|
120
|
+
status = execute_phase(:exercise, context, @block) unless status
|
121
|
+
status = execute_phase(:teardown, context, and_teardown) unless (status || !and_teardown)
|
122
|
+
status ||= Status.new(self, :success, context)
|
123
|
+
end
|
129
124
|
|
130
|
-
|
131
|
-
def teardown
|
132
|
-
@suite.ancestry_teardown.each do |teardown|
|
133
|
-
@context.instance_eval(&teardown)
|
134
|
-
end if @suite
|
135
|
-
rescue *PassthroughExceptions
|
136
|
-
raise # pass through exceptions must be passed through
|
137
|
-
rescue Exception => exception
|
138
|
-
@reason = "An error occurred during setup"
|
139
|
-
@exception = exception
|
140
|
-
@status = :error
|
125
|
+
status
|
141
126
|
end
|
142
127
|
|
143
|
-
#
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
rescue Exception => exception
|
162
|
-
@reason = "An error occurred during execution"
|
163
|
-
@exception = exception
|
164
|
-
@status = :error
|
128
|
+
# A phase can result in either success, skip, failure or error
|
129
|
+
# Execute_phase will simply return nil upon success, all other cases
|
130
|
+
# will generate a full Status instance.
|
131
|
+
# This is for practical reasons - it means you can go through several
|
132
|
+
# phases, looking for the first non-nil one.
|
133
|
+
def execute_phase(name, context, code)
|
134
|
+
status = nil
|
135
|
+
skip_reason = nil
|
136
|
+
failure_reason = nil
|
137
|
+
exception = nil
|
138
|
+
|
139
|
+
begin
|
140
|
+
if code.is_a?(Array) then
|
141
|
+
code.each do |block| context.instance_eval(&block) end
|
142
|
+
else
|
143
|
+
unless context.instance_eval(&code)
|
144
|
+
failure_reason = "Assertion failed"
|
145
|
+
status = :failure
|
165
146
|
end
|
166
147
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
148
|
+
rescue *PassthroughExceptions
|
149
|
+
raise # passthrough-exceptions must be passed through
|
150
|
+
rescue ::BareTest::Assertion::Failure => failure
|
151
|
+
status = :failure
|
152
|
+
failure_reason = failure.message
|
153
|
+
rescue ::BareTest::Assertion::Skip => skip
|
154
|
+
status = :manually_skipped
|
155
|
+
skip_reason = skip.message
|
156
|
+
rescue Exception => exception
|
157
|
+
status = :error
|
158
|
+
failure_reason = "An error occurred during #{name}: #{exception}"
|
159
|
+
exception = exception
|
170
160
|
end
|
171
|
-
|
161
|
+
|
162
|
+
status && Status.new(self, status, context, skip_reason, failure_reason, exception)
|
172
163
|
end
|
173
164
|
|
174
165
|
def to_s # :nodoc:
|