baretest 0.2.4 → 0.4.0.pre1

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