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.
Files changed (85) hide show
  1. data/LICENSE.txt +6 -6
  2. data/MANIFEST.txt +40 -18
  3. data/README.rdoc +8 -1
  4. data/bin/baretest +126 -118
  5. data/doc/baretest.rdoc +1 -1
  6. data/doc/mocking_stubbing_test_doubles.rdoc +31 -3
  7. data/doc/news/news-0.3.0.rdoc +7 -0
  8. data/doc/quickref.rdoc +74 -28
  9. data/doc/whats_going_on.rdoc +5 -0
  10. data/doc/writing_tests.rdoc +25 -13
  11. data/examples/components/rack-test.rb +17 -0
  12. data/examples/{tests/irb_mode → irb_mode}/failures.rb +0 -0
  13. data/examples/rake/test.rake +40 -0
  14. data/examples/tests/01_basics_I.rb +34 -0
  15. data/examples/tests/02_basics_II_helpers.rb +25 -0
  16. data/examples/tests/03_basics_III_setup_and_teardown.rb +53 -0
  17. data/examples/tests/04_advanced_I_dependencies.rb +31 -0
  18. data/examples/tests/05_advanced_II_tags.rb +12 -0
  19. data/examples/tests/06_advanced_III_requires.rb +21 -0
  20. data/examples/tests/07_advanced_IV_components.rb +48 -0
  21. data/examples/tests/08_expert_I_setup_variants.rb +46 -0
  22. data/lib/baretest.rb +142 -21
  23. data/lib/baretest/assertion.rb +83 -92
  24. data/lib/baretest/assertion/context.rb +9 -0
  25. data/lib/baretest/assertion/support.rb +88 -61
  26. data/lib/baretest/commandline.rb +268 -0
  27. data/lib/baretest/formatter.rb +58 -0
  28. data/lib/baretest/invalidselectors.rb +24 -0
  29. data/lib/baretest/irb_mode.rb +100 -58
  30. data/lib/baretest/persistence.rb +94 -0
  31. data/lib/baretest/run.rb +138 -37
  32. data/lib/baretest/run/cli.rb +97 -43
  33. data/lib/baretest/run/minimal.rb +2 -1
  34. data/lib/baretest/run/none.rb +21 -0
  35. data/lib/baretest/run/xml.rb +21 -19
  36. data/lib/baretest/setup.rb +2 -0
  37. data/lib/baretest/status.rb +93 -0
  38. data/lib/baretest/suite.rb +185 -59
  39. data/lib/baretest/uid.rb +51 -0
  40. data/lib/baretest/use/mocha.rb +24 -0
  41. data/lib/baretest/use/rack_test.rb +9 -0
  42. data/lib/baretest/use/rr.rb +17 -0
  43. data/lib/baretest/version.rb +18 -4
  44. data/lib/command.rb +36 -0
  45. data/lib/command/argument.rb +11 -0
  46. data/lib/command/decoratinghash.rb +31 -0
  47. data/lib/command/definition.rb +294 -0
  48. data/lib/command/directorynotfounderror.rb +11 -0
  49. data/lib/command/env.rb +11 -0
  50. data/lib/command/filenotfounderror.rb +11 -0
  51. data/lib/command/kernel.rb +14 -0
  52. data/lib/command/nodirectoryerror.rb +11 -0
  53. data/lib/command/nofileerror.rb +11 -0
  54. data/lib/command/option.rb +16 -0
  55. data/lib/command/parser.rb +145 -0
  56. data/lib/command/result.rb +11 -0
  57. data/lib/command/types.rb +33 -0
  58. data/lib/command/version.rb +28 -0
  59. data/test/setup.rb +3 -0
  60. data/test/suite/lib/baretest.rb +0 -178
  61. data/test/suite/lib/baretest/assertion.rb +133 -112
  62. data/test/suite/lib/baretest/assertion/context.rb +40 -0
  63. data/test/suite/lib/baretest/assertion/failure.rb +19 -0
  64. data/test/suite/lib/baretest/assertion/skip.rb +19 -0
  65. data/test/suite/lib/baretest/assertion/support.rb +366 -84
  66. data/test/suite/lib/baretest/run.rb +114 -15
  67. data/test/suite/lib/baretest/suite.rb +70 -29
  68. metadata +46 -24
  69. data/examples/test.rake +0 -65
  70. data/examples/tests/mock_developer/test/helper/mocks.rb +0 -0
  71. data/examples/tests/mock_developer/test/setup.rb +0 -57
  72. data/examples/tests/mock_developer/test/suite/mock_demo.rb +0 -19
  73. data/examples/tests/overview/test.rb +0 -89
  74. data/examples/tests/variations/variations_01.rb +0 -14
  75. data/examples/tests/variations/variations_02.rb +0 -19
  76. data/examples/tests/variations/variations_03.rb +0 -19
  77. data/lib/baretest/mocha.rb +0 -18
  78. data/lib/baretest/rr.rb +0 -16
  79. data/lib/baretest/run/errors.rb +0 -49
  80. data/lib/baretest/skipped.rb +0 -15
  81. data/lib/baretest/skipped/assertion.rb +0 -20
  82. data/lib/baretest/skipped/suite.rb +0 -49
  83. data/test/external/bootstraptest.rb +0 -5
  84. data/test/external/bootstrapwrap.rb +0 -2
  85. data/test/helper/mocks.rb +0 -0
@@ -31,47 +31,49 @@ module BareTest
31
31
  # <status>The final status, one of: success, incomplete, failure, error</status>
32
32
  #
33
33
  module XML # :nodoc:
34
+ extend Formatter
35
+ option_defaults :indent => "\t"
36
+ text "Options for 'XML' formatter:\n"
37
+ option :indent, '--indent STRING', :String, 'String to use for indenting'
38
+ text "\nEnvironment variables for 'XML' formatter:\n"
39
+ env_option :indent, 'INDENT'
40
+
34
41
  def run_all
35
- @depth = 1
42
+ @depth = 1
43
+ @indent = @options[:indent]
36
44
 
37
45
  puts '<?xml version="1.0" encoding="utf-8"?>',
38
46
  '<tests>'
39
47
  start = Time.now
40
48
  super
41
49
  stop = Time.now
42
- status = case
43
- when @count[:error] > 0 then 'error'
44
- when @count[:failure] > 0 then 'failure'
45
- when @count[:pending] > 0 then 'incomplete'
46
- when @count[:skipped] > 0 then 'incomplete'
47
- else 'success'
48
- end
49
50
  puts %{</tests>},
50
51
  %{<report>},
51
- %{\t<duration>#{stop-start}</duration>}
52
+ %{#{@indent}<duration>#{stop-start}</duration>}
52
53
  @count.each { |key, value|
53
- puts %{\t<count type="#{key}">#{value}</count>}
54
+ puts %{#{@indent}<count type="#{key}">#{value}</count>}
54
55
  }
55
56
  puts %{</report>},
56
- %{<status>#{status}</status>}
57
+ %{<status>#{global_status}</status>}
57
58
  end
58
59
 
59
60
  def run_suite(suite)
60
- puts %{#{"\t"*@depth}<suite description="#{suite.description}">}
61
+ puts %{#{@indent*@depth}<suite description="#{suite.description}">}
61
62
  @depth += 1
62
63
  super
63
64
  @depth -= 1
64
- puts %{#{"\t"*@depth}</suite>}
65
+ puts %{#{@indent*@depth}</suite>}
65
66
  end
66
67
 
67
68
  def run_test(assertion, setup)
68
69
  rv = super
69
- puts %{#{"\t"*@depth}<test>},
70
- %{#{"\t"*@depth}\t<file>#{rv.file}</file>},
71
- %{#{"\t"*@depth}\t<line>#{rv.line}</line>},
72
- %{#{"\t"*@depth}\t<status>#{rv.status}</status>},
73
- %{#{"\t"*@depth}\t<description>#{rv.description}</description>},
74
- %{#{"\t"*@depth}</test>}
70
+ puts %{#{@indent*@depth}<test>},
71
+ %{#{@indent*@depth}#{@indent}<file>#{assertion.file}</file>},
72
+ %{#{@indent*@depth}#{@indent}<line>#{assertion.line}</line>},
73
+ %{#{@indent*@depth}#{@indent}<status>#{rv.status}</status>},
74
+ %{#{@indent*@depth}#{@indent}<description>#{assertion.description}</description>},
75
+ %{#{@indent*@depth}</test>}
76
+ rv
75
77
  end
76
78
  end
77
79
  end
@@ -7,6 +7,8 @@
7
7
 
8
8
 
9
9
  module BareTest
10
+ # Encapsulates a single setup block and associated information.
11
+ # Relevant for setup variants.
10
12
  Setup = Struct.new(:component, :substitute, :value, :block) do
11
13
  def inspect
12
14
  sprintf "#<Setup component=%s substitute=%p value=%p>", component, substitute, value
@@ -0,0 +1,93 @@
1
+ #--
2
+ # Copyright 2009-2010 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ module BareTest
10
+
11
+ # The status of an Assertion or Suite, including failure- and skipreasons,
12
+ # or in case of exceptions, the exception itself and in what phase it occurred
13
+ # An assertion or suite has 9 possible states:
14
+ # :success:: The assertion passed. This means the block returned a trueish value.
15
+ # :failure:: The assertion failed. This means the block returned a falsish value.
16
+ # Alternatively it raised an Assertion::Failure.
17
+ # The latter has the advantage that it can provide nicer diagnostics.
18
+ # :pending:: No block given to the assertion to be run
19
+ # :skipped:: If one of the parent suites is missing a dependency, its assertions
20
+ # will be skipped
21
+ # Alternatively it raised an Assertion::Skip.
22
+ # :error:: The assertion errored out. This means the block raised an exception
23
+ class Status
24
+
25
+ # The assertion or suite this status belongs to. Assertion or Suite.
26
+ attr_reader :entity
27
+
28
+ # The assertions execute context.
29
+ attr_reader :context
30
+
31
+ # The status identifier, see BareTest::Status. Symbol.
32
+ attr_reader :status
33
+
34
+ # Detailed reason for skipping. Array or nil.
35
+ attr_reader :skip_reason
36
+
37
+ # Detailed reason for failing. Array or nil.
38
+ attr_reader :failure_reason
39
+
40
+ # If an exception occured in Assertion#execute, this will contain the
41
+ # Exception object raised.
42
+ attr_reader :exception
43
+
44
+ # entity:: The suite or Assertion this Status belongs to
45
+ # status:: The status identifier
46
+ # skip_reason:: Why the Assertion or Suite failed.
47
+ # Array, String or nil.
48
+ # failure_reason:: Why the Assertion or Suite was skipped.
49
+ # Array, String or nil.
50
+ def initialize(entity, status, context=nil, skip_reason=nil, failure_reason=nil, exception=nil)
51
+ @entity = entity
52
+ @status = status
53
+ @context = context
54
+ @skip_reason = skip_reason
55
+ @failure_reason = failure_reason
56
+ @exception = exception
57
+ end
58
+
59
+ # The failure/error/skipping/pending reason.
60
+ # Returns nil if there's no reason, a string otherwise
61
+ # Options:
62
+ # :default:: Reason to return if no reason is present
63
+ # :separator:: String used to separate multiple reasons
64
+ # :indent:: A String, the indentation to use. Prefixes every line.
65
+ # :first_indent: A String, used to indent the first line only (replaces indent).
66
+ def reason(opt=nil)
67
+ if opt then
68
+ default, separator, indent, first_indent =
69
+ *opt.values_at(:default, :separator, :indent, :first_indent)
70
+ reason = @skip_reason || @failure_reason || default
71
+ return nil unless reason
72
+ reason = Array(reason)
73
+ reason = reason.join(separator || "\n")
74
+ reason = reason.gsub(/^/, indent) if indent
75
+ reason = reason.gsub(/^#{Regexp.escape(indent)}/, first_indent) if first_indent
76
+ reason
77
+ else
78
+ @reason.empty? ? nil : @reason.join("\n")
79
+ end
80
+ end
81
+
82
+ def inspect # :nodoc:
83
+ sprintf "#<%s:0x%08x status=%p exception=%p skip_reason=%p failure_reason=%p entity=%p>",
84
+ self.class,
85
+ object_id>>1,
86
+ @status,
87
+ @exception,
88
+ @skip_reason,
89
+ @failure_reason,
90
+ @entity
91
+ end
92
+ end
93
+ end
@@ -21,76 +21,181 @@ module BareTest
21
21
  class Suite
22
22
 
23
23
  # Nested suites, in the order of definition
24
- attr_reader :suites
24
+ attr_reader :suites
25
25
 
26
26
  # All assertions in this suite
27
- attr_reader :assertions
27
+ attr_reader :assertions
28
28
 
29
- # All skipped assertions in this suite
30
- attr_reader :skipped
29
+ # Whether this suite has been manually skipped (either via
30
+ # Suite.new(..., :skip => reason) or via Suite#skip)
31
+ attr_reader :skipped
31
32
 
32
33
  # This suites description. Toplevel suites usually don't have a description.
33
- attr_reader :description
34
+ attr_reader :description
34
35
 
35
36
  # This suites direct parent. Nil if toplevel suite.
36
- attr_reader :parent
37
+ attr_reader :parent
37
38
 
38
39
  # An Array containing the suite itself (first element), then its direct
39
40
  # parent suite, then that suite's parent and so on
40
- attr_reader :ancestors
41
+ attr_reader :ancestors
42
+
43
+ # All things this suite depends on, see Suite::new for more information
44
+ attr_reader :depends_on
45
+
46
+ # All things this suite provides, see Suite::new for more information
47
+ attr_reader :provides
48
+
49
+ # All things this suite is tagged with, see Suite::new for more information
50
+ attr_reader :tags
51
+
52
+ # A list of valid options Suite::new accepts
53
+ ValidOptions = [:skip, :requires, :use, :provides, :depends_on, :tags]
41
54
 
42
55
  # Create a new suite.
43
56
  #
44
- # The arguments 'description', 'parent' and '&block' are the same as on Suite::new,
45
- # 'opts' is an additional options hash.
57
+ # Arguments:
58
+ # description:: A string with a human readable description of this suite,
59
+ # preferably less than 60 characters and without newlines
60
+ # parent:: The suite that nests this suite. Ancestry plays a role in
61
+ # execution of setup and teardown blocks (all ancestors setups
62
+ # and teardowns are executed too).
63
+ # opts:: An additional options hash.
46
64
  #
47
65
  # Keys the options hash accepts:
48
- # :requires:: A string or array of strings with requires that have to be done in order to run
49
- # this suite. If a require fails, the suite is created as a Skipped::Suite instead.
50
- #
51
- def self.create(description=nil, parent=nil, opts={}, &block)
52
- Array(opts[:requires]).each { |file| require file } if opts[:requires]
53
- rescue LoadError
54
- # A suite is skipped if requirements are not met
55
- Skipped::Suite.new(description, parent, &block)
56
- else
57
- # All suites within Skipped::Suite are Skipped::Suite
58
- (block ? self : Skipped::Suite).new(description, parent, &block)
59
- end
60
-
61
- # Create a new suite.
66
+ # :skip:: Skips the suite if true or a String is passed. If a String
67
+ # is passed, it is used as the reason.
68
+ # :requires:: A string or array of strings with requires that have to be
69
+ # done in order to run this suite. If a require fails, the
70
+ # assertions will all be skipped with reason "Missing
71
+ # dependency".
72
+ # :use:: A symbol or array of symbols with components this suite
73
+ # should load prior to running.
74
+ # :provides:: A symbol or array of symbols with dependencies this suite
75
+ # resolves, see 'depends_on'.
76
+ # :depends_on:: A symbol or array of symbols with dependencies of this
77
+ # suite, see 'provides'.
78
+ # :tags:: A symbol or array of symbols, useful to run only suites
79
+ # having/not having specific tags
62
80
  #
63
- # Arguments:
64
- # description:: A string with a human readable description of this suite, preferably
65
- # less than 60 characters and without newlines
66
- # parent:: The suite that nests this suite. Ancestry plays a role in execution of setup
67
- # and teardown blocks (all ancestors setups and teardowns are executed too).
68
- # &block:: The given block is instance evaled.
69
- def initialize(description=nil, parent=nil, &block)
81
+ # &block:: The given block is instance evaled and can contain further
82
+ # definition of this assertion. See Suite#suite and
83
+ # Suite#assert.
84
+ def initialize(description=nil, parent=nil, opts=nil, &block)
70
85
  @description = description
71
86
  @parent = parent
72
87
  @suites = [] # [["description", subsuite, skipped], ["description2", ...], ...] - see Array#assoc
73
88
  @assertions = []
74
- @skipped = []
89
+ @skipped = false
75
90
  @setup = {nil => []}
76
91
  @components = []
77
92
  @teardown = []
78
- @ancestors = [self] + (@parent ? @parent.ancestors : [])
93
+ if @parent then
94
+ @ancestors = [self, *@parent.ancestors]
95
+ @depends_on = @parent.depends_on
96
+ @tags = @parent.tags
97
+ else
98
+ @ancestors = [self]
99
+ @depends_on = []
100
+ @tags = []
101
+ end
102
+ @provides = []
103
+ @reason = [] # skip reason
104
+ if opts then
105
+ raise ArgumentError, "Invalid option(s): #{(opts.keys - ValidOptions).inspect}" unless (opts.keys - ValidOptions).empty?
106
+ skip, requires, use, provides, depends_on, tags = opts.values_at(*ValidOptions)
107
+ skip(skip == true ? nil : skip) if skip
108
+ use(*use) if use
109
+ requires(*requires) if requires
110
+ @depends_on |= Array(depends_on) if depends_on
111
+ @provides |= Array(provides) if provides
112
+ @tags |= Array(tags) if tags
113
+ end
79
114
  instance_eval(&block) if block
80
115
  end
81
116
 
117
+ # An ID, usable for persistence
118
+ def id
119
+ @id ||= ancestors.map { |suite| suite.description }.join("\f")
120
+ end
121
+
122
+ # Instruct this suite to use the given components.
123
+ # The suite is skipped if a component is not available.
124
+ def use(*components)
125
+ components.each do |name|
126
+ component = BareTest.component(name)
127
+ if component then
128
+ instance_eval(&component)
129
+ else
130
+ skip("Missing component: #{name.inspect}")
131
+ end
132
+ end
133
+ end
134
+
135
+ # Instruct this suite to require the given files.
136
+ # The suite is skipped if a file can't be loaded.
137
+ def requires(*paths)
138
+ paths.each do |file|
139
+ begin
140
+ require file
141
+ rescue LoadError => e
142
+ skip("Missing source file: #{file} (#{e})")
143
+ end
144
+ end
145
+ end
146
+
147
+ # Returns whether this suite has all the passed tags
148
+ def tagged?(tags)
149
+ (@tags-tags).empty?
150
+ end
151
+
152
+ # Marks this suite as manually skipped.
153
+ def skip(reason=nil)
154
+ @skipped = true
155
+ @reason |= reason ? Array(reason) : ['Manually skipped']
156
+ true
157
+ end
158
+
159
+ # Returns whether this assertion has been marked as manually skipped.
160
+ def skipped?
161
+ @skipped
162
+ end
163
+
164
+ # The failure/error/skipping/pending reason.
165
+ # Returns nil if there's no reason, a string otherwise
166
+ # Options:
167
+ # :default:: Reason to return if no reason is present
168
+ # :separator:: String used to separate multiple reasons
169
+ # :indent:: A String, the indentation to use. Prefixes every line.
170
+ # :first_indent: A String, used to indent the first line only (replaces indent).
171
+ def reason(opt=nil)
172
+ if opt then
173
+ default, separator, indent, first_indent =
174
+ *opt.values_at(:default, :separator, :indent, :first_indent)
175
+ reason = @reason
176
+ reason = Array(default) if reason.empty? && default
177
+ return nil if reason.empty?
178
+ reason = reason.join(separator || "\n")
179
+ reason = reason.gsub(/^/, indent) if indent
180
+ reason = reason.gsub(/^#{Regexp.escape(indent)}/, first_indent) if first_indent
181
+ reason
182
+ else
183
+ @reason.empty? ? nil : @reason.join("\n")
184
+ end
185
+ end
186
+
82
187
  # Define a nested suite.
83
188
  #
84
189
  # Nested suites inherit setup & teardown methods.
85
190
  # Also if an outer suite is skipped, all inner suites are skipped too.
86
191
  #
87
- # Valid values for opts:
88
- # :requires:: A list of files to require, if one of the requires fails,
89
- # the suite will be skipped. Accepts a String or an Array
90
- def suite(description=nil, opts={}, &block)
91
- suite = self.class.create(description, self, opts, &block)
92
- if append_to = @suites.assoc(description) then
93
- append_to.last.update(suite)
192
+ # See Suite::new - all arguments are passed to it verbatim, and self is
193
+ # added as parent.
194
+ def suite(description=nil, *args, &block)
195
+ suite = self.class.new(description, self, *args, &block)
196
+ existing_suite = @suites.assoc(description)
197
+ if existing_suite then
198
+ existing_suite.last.update(suite)
94
199
  else
95
200
  @suites << [description, suite]
96
201
  end
@@ -101,20 +206,23 @@ module BareTest
101
206
  #
102
207
  # Used to merge suites with the same description.
103
208
  def update(with_suite)
104
- if ::BareTest::Skipped::Suite === with_suite then
105
- @skipped.concat(with_suite.skipped)
106
- else
107
- @assertions.concat(with_suite.assertions)
108
- @setup.update(with_suite.setup) do |k,v1,v2| v1+v2 end
109
- @teardown.concat(with_suite.teardown)
110
- with_suite.suites.each { |description, suite|
111
- if append_to = @suites.assoc(description) then
112
- append_to.last.update(suite)
113
- else
114
- @suites << [description, suite]
115
- end
116
- }
117
- end
209
+ assertions, setup, teardown, provides, depends_on, skipped, reason, suites =
210
+ *with_suite.merge_attributes
211
+ @assertions.concat(assertions)
212
+ @setup.update(setup) do |k,v1,v2| v1+v2 end
213
+ @teardown.concat(teardown)
214
+ @provides |= provides
215
+ @depends_on |= depends_on
216
+ @skipped ||= skipped
217
+ @reason.concat(reason)
218
+ suites.each { |description, suite|
219
+ if append_to = @suites.assoc(description) then
220
+ append_to.last.update(suite)
221
+ else
222
+ @suites << [description, suite]
223
+ end
224
+ }
225
+
118
226
  self
119
227
  end
120
228
 
@@ -173,6 +281,13 @@ module BareTest
173
281
  block ? @teardown << block : @teardown
174
282
  end
175
283
 
284
+ # Returns the number of possible setup variations.
285
+ # See #each_component_variant
286
+ def component_variant_count
287
+ ancestry_setup.values_at(*ancestry_components).inject(1) { |r,f| r*f.size }
288
+ end
289
+
290
+ # Yields all possible permutations of setup components.
176
291
  def each_component_variant
177
292
  setups = ancestry_setup
178
293
  components = ancestry_components
@@ -196,6 +311,7 @@ module BareTest
196
311
  self
197
312
  end
198
313
 
314
+ # Return only the first of all possible setup variation permutations.
199
315
  def first_component_variant
200
316
  setups, *comps = ancestry_setup.values_at(nil, *ancestry_components)
201
317
  setups = setups+comps.map { |comp| comp.first }
@@ -208,8 +324,8 @@ module BareTest
208
324
  # (anything but nil or false).
209
325
  #
210
326
  # See Assertion for more info.
211
- def assert(description=nil, &block)
212
- assertion = Assertion.new(self, description, &block)
327
+ def assert(description=nil, opts=nil, &block)
328
+ assertion = Assertion.new(self, description, opts, &block)
213
329
  if match = caller.first.match(/^(.*):(\d+)(?::.+)?$/) then
214
330
  file, line = match.captures
215
331
  file = File.expand_path(file)
@@ -220,6 +336,7 @@ module BareTest
220
336
  end
221
337
  @assertions << assertion
222
338
  end
339
+ alias guard assert # TODO: This is temporary, guards should become first class citizens
223
340
 
224
341
  def to_s #:nodoc:
225
342
  sprintf "%s %s", self.class, @description
@@ -228,9 +345,18 @@ module BareTest
228
345
  def inspect #:nodoc:
229
346
  sprintf "#<%s:%08x %p>", self.class, object_id>>1, @description
230
347
  end
348
+
349
+ protected
350
+ # All attributes that are required when merging two suites
351
+ def merge_attributes
352
+ return @assertions,
353
+ @setup,
354
+ @teardown,
355
+ @provides,
356
+ @depends_on,
357
+ @skipped,
358
+ @reason,
359
+ @suites
360
+ end
231
361
  end
232
362
  end
233
-
234
-
235
-
236
- require 'baretest/skipped/suite' # TODO: determine why this require is on the bottom and document it.