baretest 0.1.0 → 0.2.3

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 (69) hide show
  1. data/LICENSE.txt +52 -0
  2. data/MANIFEST.txt +50 -31
  3. data/README.rdoc +260 -0
  4. data/bin/baretest +82 -24
  5. data/doc/baretest.rdoc +98 -0
  6. data/doc/mocking_stubbing_test_doubles.rdoc +5 -0
  7. data/doc/quickref.rdoc +261 -0
  8. data/doc/writing_tests.rdoc +148 -0
  9. data/examples/test.rake +58 -30
  10. data/examples/tests/irb_mode/failures.rb +26 -0
  11. data/examples/tests/mock_developer/test/helper/mocks.rb +0 -0
  12. data/examples/tests/mock_developer/test/setup.rb +57 -0
  13. data/examples/tests/mock_developer/test/suite/mock_demo.rb +19 -0
  14. data/examples/tests/overview/test.rb +89 -0
  15. data/examples/tests/variations/variations_01.rb +14 -0
  16. data/examples/tests/variations/variations_02.rb +19 -0
  17. data/examples/tests/variations/variations_03.rb +19 -0
  18. data/lib/baretest/assertion/context.rb +20 -0
  19. data/lib/baretest/assertion/failure.rb +22 -0
  20. data/lib/baretest/assertion/skip.rb +21 -0
  21. data/lib/{test → baretest}/assertion/support.rb +174 -39
  22. data/lib/baretest/assertion.rb +182 -0
  23. data/lib/baretest/irb_mode.rb +263 -0
  24. data/lib/{test/assertion/failure.rb → baretest/layout.rb} +6 -5
  25. data/lib/baretest/mocha.rb +18 -0
  26. data/lib/baretest/run/cli.rb +104 -0
  27. data/lib/{test → baretest}/run/errors.rb +12 -7
  28. data/lib/{test → baretest}/run/minimal.rb +8 -3
  29. data/lib/baretest/run/profile.rb +151 -0
  30. data/lib/{test → baretest}/run/spec.rb +10 -4
  31. data/lib/baretest/run/tap.rb +44 -0
  32. data/lib/baretest/run/xml.rb +80 -0
  33. data/lib/{test → baretest}/run.rb +31 -18
  34. data/lib/baretest/setup.rb +15 -0
  35. data/lib/baretest/skipped/assertion.rb +20 -0
  36. data/lib/baretest/skipped/suite.rb +49 -0
  37. data/lib/baretest/skipped.rb +15 -0
  38. data/lib/baretest/suite.rb +234 -0
  39. data/lib/baretest/utilities.rb +43 -0
  40. data/lib/{test → baretest}/version.rb +12 -3
  41. data/lib/baretest.rb +112 -0
  42. data/test/external/bootstraptest.rb +1 -1
  43. data/test/setup.rb +1 -1
  44. data/test/{lib/test → suite/lib/baretest}/assertion/support.rb +78 -24
  45. data/test/suite/lib/baretest/assertion.rb +192 -0
  46. data/test/{lib/test → suite/lib/baretest}/irb_mode.rb +0 -0
  47. data/test/{lib/test → suite/lib/baretest}/run/cli.rb +0 -0
  48. data/test/{lib/test → suite/lib/baretest}/run/errors.rb +0 -0
  49. data/test/{lib/test → suite/lib/baretest}/run/interactive.rb +0 -0
  50. data/test/{lib/test → suite/lib/baretest}/run/spec.rb +0 -0
  51. data/test/{lib/test → suite/lib/baretest}/run/tap.rb +0 -0
  52. data/test/{lib/test → suite/lib/baretest}/run/xml.rb +0 -0
  53. data/test/{lib/test → suite/lib/baretest}/run.rb +63 -61
  54. data/test/{lib/test → suite/lib/baretest}/suite.rb +77 -54
  55. data/test/{lib/test.rb → suite/lib/baretest.rb} +37 -37
  56. metadata +61 -40
  57. data/README.markdown +0 -229
  58. data/examples/test.rb +0 -93
  59. data/lib/test/assertion.rb +0 -117
  60. data/lib/test/debug.rb +0 -34
  61. data/lib/test/irb_mode.rb +0 -104
  62. data/lib/test/run/cli.rb +0 -79
  63. data/lib/test/run/interactive.rb +0 -60
  64. data/lib/test/run/tap.rb +0 -32
  65. data/lib/test/run/xml.rb +0 -56
  66. data/lib/test/suite.rb +0 -95
  67. data/lib/test.rb +0 -118
  68. data/test/lib/test/assertion.rb +0 -142
  69. data/test/lib/test/debug.rb +0 -63
@@ -0,0 +1,80 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ module BareTest
10
+ class Run
11
+
12
+ # XML runner is invoked with `-f xml` or `--format xml`.
13
+ # This runner provides xml output as a simple machine readable format.
14
+ # The schema is relatively simple:
15
+ # <tests>
16
+ # <suite description="the suites description">
17
+ # <test>
18
+ # <file>the file the test was defined in</file>
19
+ # <line>the line the assertion starts on</line>
20
+ # <status>one of: success, pending, skipped, failure, error</status>
21
+ # <description>the description of the test</test>
22
+ # </test>
23
+ # ...many tests and/or suites
24
+ # </suite>
25
+ # </tests>
26
+ # <report>
27
+ # <duration>the duration in seconds as a float</duration>
28
+ # <count type="the counters name, see BareTest::Run#count">integer</count>
29
+ # ...many counts
30
+ # </report>
31
+ # <status>The final status, one of: success, incomplete, failure, error</status>
32
+ #
33
+ module XML # :nodoc:
34
+ def run_all
35
+ @depth = 1
36
+
37
+ puts '<?xml version="1.0" encoding="utf-8"?>',
38
+ '<tests>'
39
+ start = Time.now
40
+ super
41
+ 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
+ puts %{</tests>},
50
+ %{<report>},
51
+ %{\t<duration>#{stop-start}</duration>}
52
+ @count.each { |key, value|
53
+ puts %{\t<count type="#{key}">#{value}</count>}
54
+ }
55
+ puts %{</report>},
56
+ %{<status>#{status}</status>}
57
+ end
58
+
59
+ def run_suite(suite)
60
+ puts %{#{"\t"*@depth}<suite description="#{suite.description}">}
61
+ @depth += 1
62
+ super
63
+ @depth -= 1
64
+ puts %{#{"\t"*@depth}</suite>}
65
+ end
66
+
67
+ def run_test(assertion, setup)
68
+ 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>}
75
+ end
76
+ end
77
+ end
78
+
79
+ @format["baretest/run/xml"] = Run::XML
80
+ end
@@ -6,15 +6,18 @@
6
6
 
7
7
 
8
8
 
9
- module Test
9
+ module BareTest
10
10
 
11
- # Run is the envorionment in which the suites and asserts are executed.
11
+ # Run is the environment in which the suites and asserts are executed.
12
12
  # Prior to the execution, the Run instance extends itself with the
13
13
  # formatter given.
14
14
  # Your formatter can override:
15
- # * run_all
16
- # * run_suite
17
- # * run_test
15
+ # :run_all:: Invoked once, before the first run_suite is ran. No arguments.
16
+ # :run_suite:: Invoked per suite. Takes the suite to run as argument.
17
+ # :run_test:: Invoked per assertion. Takes the assertion to execute as argument.
18
+ #
19
+ # Don't forget to call super within your overrides, or the tests won't be
20
+ # executed.
18
21
  class Run
19
22
  # The toplevel suite.
20
23
  attr_reader :suite
@@ -38,12 +41,12 @@ module Test
38
41
  # suite).
39
42
  # Options accepted:
40
43
  # * :extenders: An Array of Modules, will be used as argument to self.extend, useful e.g. for
41
- # mock integration
44
+ # mock integration
42
45
  # * :format: A string with the basename (without suffix) of the formatter to use - or a
43
- # Module
46
+ # Module
44
47
  # * :interactive: true/false, will switch this Test::Run instance into IRB mode, where an error
45
- # will cause an irb session to be started in the context of a clean copy of
46
- # the assertion with all setup callbacks invoked
48
+ # will cause an irb session to be started in the context of a clean copy of
49
+ # the assertion with all setup callbacks invoked
47
50
  #
48
51
  # The order of extensions is:
49
52
  # * :extender
@@ -55,18 +58,18 @@ module Test
55
58
  @options = opts || {}
56
59
  @count = @options[:count] || Hash.new(0)
57
60
 
58
- (Test.extender+Array(@options[:extender])).each do |extender|
61
+ (BareTest.extender+Array(@options[:extender])).each do |extender|
59
62
  extend(extender)
60
63
  end
61
64
 
62
65
  # Extend with the output formatter
63
66
  if format = @options[:format] then
64
- require "test/run/#{format}" if String === format
65
- extend(String === format ? Test.format["test/run/#{format}"] : format)
67
+ require "baretest/run/#{format}" if String === format
68
+ extend(String === format ? BareTest.format["baretest/run/#{format}"] : format)
66
69
  end
67
70
 
68
71
  # Extend with irb dropout code
69
- extend(Test::IRBMode) if @options[:interactive]
72
+ extend(BareTest::IRBMode) if @options[:interactive]
70
73
 
71
74
  # Initialize extenders
72
75
  @inits.each { |init| instance_eval(&init) }
@@ -98,19 +101,29 @@ module Test
98
101
  # Gets the suite to run as single argument.
99
102
  # Runs all assertions and nested suites.
100
103
  def run_suite(suite)
101
- suite.tests.each do |test|
102
- run_test(test)
104
+ suite.assertions.each do |test|
105
+ run_test_variants(test)
103
106
  end
104
- suite.suites.each do |suite|
107
+ suite.suites.each do |(description, suite)|
105
108
  run_suite(suite)
106
109
  end
107
110
  @count[:suite] += 1
108
111
  end
109
112
 
110
- # Formatter callback.
111
113
  # Invoked once for every assertion.
114
+ # Iterates over all variants of an assertion and invokes run_test
115
+ # for each.
116
+ def run_test_variants(test)
117
+ test.suite.each_component_variant do |setups|
118
+ run_test(test, setups)
119
+ end
120
+ end
121
+
122
+ # Formatter callback.
123
+ # Invoked once for every variation of an assertion.
112
124
  # Gets the assertion to run as single argument.
113
- def run_test(assertion)
125
+ def run_test(assertion, setup)
126
+ assertion.setups = setup
114
127
  rv = assertion.execute
115
128
  @count[:test] += 1
116
129
  @count[assertion.status] += 1
@@ -0,0 +1,15 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ module BareTest
10
+ Setup = Struct.new(:component, :substitute, :value, :block) do
11
+ def inspect
12
+ sprintf "#<Setup component=%s substitute=%p value=%p>", component, substitute, value
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ module BareTest
10
+ module Skipped
11
+
12
+ # Like Test::Assertion, but fakes execution and sets status always to
13
+ # skipped.
14
+ class Assertion < ::BareTest::Assertion
15
+ def execute(setup=nil) # :nodoc:
16
+ @status = :skipped and self
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'baretest/skipped/assertion'
10
+
11
+
12
+
13
+ module BareTest
14
+
15
+ module Skipped
16
+
17
+ # Like Test::Suite, but all Assertions are defined as Skipped::Assertion
18
+ class Suite < ::BareTest::Suite
19
+ def self.create(description=nil, parent=nil, opts={}, &block) # :nodoc:
20
+ new(description, parent, &block) # Skipped::Suite always
21
+ end
22
+
23
+ # All Assertions use Skipped::Assertion instead of Test::Assertion.
24
+ def assert(description=nil, &block) # :nodoc:
25
+ @skipped << Skipped::Assertion.new(self, description, &block)
26
+ end
27
+
28
+ # All setup blocks are disabled
29
+ def ancestry_setup # :nodoc:
30
+ []
31
+ end
32
+
33
+ # All teardown blocks are disabled
34
+ def ancestry_teardown # :nodoc:
35
+ []
36
+ end
37
+
38
+ # All setup blocks are disabled
39
+ def setup(&block) # :nodoc:
40
+ []
41
+ end
42
+
43
+ # All teardown blocks are disabled
44
+ def teardown(&block) # :nodoc:
45
+ []
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ module BareTest
10
+
11
+ # Skipped contains variants of Suite and Assertion.
12
+ # See Skipped::Suite and Skipped::Assertion
13
+ module Skipped
14
+ end
15
+ end
@@ -0,0 +1,234 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'baretest/setup'
10
+
11
+
12
+
13
+ module BareTest
14
+
15
+ # A Suite is a container for multiple assertions.
16
+ # You can give a suite a description, also a suite can contain
17
+ # setup and teardown blocks that are executed before (setup) and after
18
+ # (teardown) every assertion.
19
+ #
20
+ # Suites can also be nested. Nested suites will inherit setup and teardown.
21
+ class Suite
22
+
23
+ # Nested suites, in the order of definition
24
+ attr_reader :suites
25
+
26
+ # All assertions in this suite
27
+ attr_reader :assertions
28
+
29
+ # All skipped assertions in this suite
30
+ attr_reader :skipped
31
+
32
+ # This suites description. Toplevel suites usually don't have a description.
33
+ attr_reader :description
34
+
35
+ # This suites direct parent. Nil if toplevel suite.
36
+ attr_reader :parent
37
+
38
+ # An Array containing the suite itself (first element), then its direct
39
+ # parent suite, then that suite's parent and so on
40
+ attr_reader :ancestors
41
+
42
+ # Create a new suite.
43
+ #
44
+ # The arguments 'description', 'parent' and '&block' are the same as on Suite::new,
45
+ # 'opts' is an additional options hash.
46
+ #
47
+ # 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.
62
+ #
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)
70
+ @description = description
71
+ @parent = parent
72
+ @suites = [] # [["description", subsuite, skipped], ["description2", ...], ...] - see Array#assoc
73
+ @assertions = []
74
+ @skipped = []
75
+ @setup = {nil => []}
76
+ @components = []
77
+ @teardown = []
78
+ @ancestors = [self] + (@parent ? @parent.ancestors : [])
79
+ instance_eval(&block) if block
80
+ end
81
+
82
+ # Define a nested suite.
83
+ #
84
+ # Nested suites inherit setup & teardown methods.
85
+ # Also if an outer suite is skipped, all inner suites are skipped too.
86
+ #
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)
94
+ else
95
+ @suites << [description, suite]
96
+ end
97
+ suite
98
+ end
99
+
100
+ # Performs a recursive merge with the given suite.
101
+ #
102
+ # Used to merge suites with the same description.
103
+ 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
118
+ self
119
+ end
120
+
121
+ # All setups in the order of their definition and nesting (outermost first,
122
+ # innermost last)
123
+ def ancestry_setup
124
+ @parent ? @parent.ancestry_setup.merge(@setup) { |k,v1,v2|
125
+ v1+v2
126
+ } : @setup
127
+ end
128
+
129
+ # All setup-components in the order of their definition and nesting
130
+ # (outermost first, innermost last)
131
+ def ancestry_components
132
+ @parent ? @parent.ancestry_components|@components : @components
133
+ end
134
+
135
+ # All teardowns in the order of their nesting (innermost first, outermost last)
136
+ def ancestry_teardown
137
+ ancestors.map { |suite| suite.teardown }.flatten
138
+ end
139
+
140
+ # Define a setup block for this suite. The block will be ran before every
141
+ # assertion once, even for nested suites.
142
+ def setup(component=nil, multiplexed=nil, &block)
143
+ if component.nil? && block then
144
+ @setup[nil] << ::BareTest::Setup.new(nil, nil, nil, block)
145
+ elsif block then
146
+ @components << component unless @setup.has_key?(component)
147
+ @setup[component] ||= []
148
+
149
+ case multiplexed
150
+ when String
151
+ @setup[component] << ::BareTest::Setup.new(component, multiplexed, nil, block)
152
+ when Array
153
+ multiplexed.each do |substitute|
154
+ @setup[component] << BareTest::Setup.new(component, substitute.to_s, substitute, block)
155
+ end
156
+ when Hash
157
+ multiplexed.each do |substitute, value|
158
+ @setup[component] << BareTest::Setup.new(component, substitute, value, block)
159
+ end
160
+ end
161
+ elsif component || multiplexed
162
+ raise ArgumentError, "With component or multiplexed given, a block must be provided too."
163
+ end
164
+
165
+ @setup
166
+ end
167
+
168
+ # Define a teardown block for this suite. The block will be ran after every
169
+ # assertion once, even for nested suites.
170
+ def teardown(&block)
171
+ block ? @teardown << block : @teardown
172
+ end
173
+
174
+ def each_component_variant
175
+ setups = ancestry_setup
176
+ components = ancestry_components
177
+ base = setups[nil]
178
+
179
+ if components.empty?
180
+ yield(base)
181
+ else
182
+ setup_in_order = setups.values_at(*components)
183
+ maximums = setup_in_order.map { |i| i.size }
184
+ iterations = maximums.inject { |r,f| r*f } || 0
185
+
186
+ iterations.times do |i|
187
+ process = maximums.map { |e| i,e=i.divmod(e); e }
188
+ yield base+setup_in_order.zip(process).map { |variants, current|
189
+ variants[current]
190
+ }
191
+ end
192
+ end
193
+
194
+ self
195
+ end
196
+
197
+ def first_component_variant
198
+ setups, *comps = ancestry_setup.values_at(nil, *ancestry_components)
199
+ setups = setups+comps.map { |comp| comp.first }
200
+ yield(setups) if block_given?
201
+
202
+ setups
203
+ end
204
+
205
+ # Define an assertion. The block is supposed to return a trueish value
206
+ # (anything but nil or false).
207
+ #
208
+ # See Assertion for more info.
209
+ def assert(description=nil, &block)
210
+ assertion = Assertion.new(self, description, &block)
211
+ if match = caller.first.match(/^(.*):(\d+)(?::.+)?$/) then
212
+ file, line = match.captures
213
+ file = File.expand_path(file)
214
+ if File.exist?(file) then
215
+ assertion.file = file
216
+ assertion.line = line.to_i
217
+ end
218
+ end
219
+ @assertions << assertion
220
+ end
221
+
222
+ def to_s #:nodoc:
223
+ sprintf "%s %s", self.class, @description
224
+ end
225
+
226
+ def inspect #:nodoc:
227
+ sprintf "#<%s:%08x %p>", self.class, object_id>>1, @description
228
+ end
229
+ end
230
+ end
231
+
232
+
233
+
234
+ require 'baretest/skipped/suite' # TODO: determine why this require is on the bottom and document it.
@@ -0,0 +1,43 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ module Kernel
10
+ # All extensions Kernel#require_path and Kernel#expanded_require_path will try
11
+ # for a given filename
12
+ RequireExtensions = %w[.rb .so .dll .bundle .dylib]
13
+
14
+ # Returns the path to the file require would load, also see Kernel#expanded_require_path
15
+ def require_path(name, extensions=nil)
16
+ extensions = (extensions || ::Kernel::RequireExtensions).join(',')
17
+ Dir.glob("{#{$LOAD_PATH.join(',')}}/#{name}{#{extensions}}") { |path|
18
+ return path
19
+ }
20
+ nil
21
+ end
22
+
23
+ # Returns the absolute path to the file require would load, also see Kernel#require_path
24
+ def expanded_require_path(name, extensions=nil)
25
+ path = require_path(name, extensions)
26
+ path && File.expand_path(path)
27
+ end
28
+
29
+ # Will load the given file like load (but accepts files without .rb in the end, like require),
30
+ # but evaluate it into the module given with the second arg (defaulting to Module.new).
31
+ # It uses Kernel#expanded_require_path with '' and '.rb' as extensions to determine the file to
32
+ # load uses the returned path for error messages (second argument to Module#modul_eval).
33
+ def load_into(name, mod=nil)
34
+ mod ||= Module.new
35
+ path = expanded_require_path(name, ['', '.rb'])
36
+ raise LoadError, "No such file to load -- #{name}" unless path
37
+ mod.module_eval(File.read(path), path)
38
+
39
+ mod
40
+ end
41
+
42
+ module_function :require_path, :expanded_require_path, :load_into
43
+ end
@@ -6,12 +6,21 @@
6
6
 
7
7
 
8
8
 
9
- module Test
9
+ module BareTest
10
+
11
+ # The version of the baretest library
10
12
  module VERSION
13
+
14
+ # The major version number
11
15
  MAJOR = 0
12
- MINOR = 1
13
- TINY = 0
14
16
 
17
+ # The minor version number
18
+ MINOR = 2
19
+
20
+ # The tiny version number
21
+ TINY = 3
22
+
23
+ # The version as a string
15
24
  def self.to_s
16
25
  "#{MAJOR}.#{MINOR||0}.#{TINY||0}"
17
26
  end
data/lib/baretest.rb ADDED
@@ -0,0 +1,112 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'baretest/assertion'
10
+ require 'baretest/irb_mode'
11
+ require 'baretest/run'
12
+ require 'baretest/suite'
13
+ require 'baretest/utilities'
14
+ require 'baretest/version'
15
+ # See bottom for more requires
16
+
17
+
18
+
19
+ module BareTest
20
+ class << self
21
+ # A hash of formatters (require-string => module) to be used with Test::Run.
22
+ attr_reader :format
23
+
24
+ # For mock integration and others, append modules that should extend the Test::Run instance.
25
+ attr_reader :extender
26
+
27
+ # The toplevel suite. That's the one run_if_mainfile and define add suites
28
+ # and assertions to.
29
+ attr_reader :toplevel_suite
30
+
31
+ # The full path to this file
32
+ # Needed to test baretest itself using baretest
33
+ attr_reader :required_file # :nodoc:
34
+ end
35
+
36
+ # Loads all files in a test directory in order to load the suites and
37
+ # assertions. Used by the 'baretest' executable and the standard rake task.
38
+ #
39
+ # Options:
40
+ # :verbose:: Will print information about the load process (default: false)
41
+ # :setup_path:: The path to the setup file, the first loaded file (default: 'test/setup.rb')
42
+ # :chdir:: The directory this routine chdirs before loading, will jump back to the original
43
+ # directory after loading (default: '.')
44
+ def self.load_standard_test_files(opts={})
45
+ verbose = opts.delete(:verbose)
46
+ setup_path = opts.delete(:setup_path) || 'test/setup.rb'
47
+ chdir = opts.delete(:chdir) || '.'
48
+ Dir.chdir(chdir) do
49
+ load(setup_path) if File.exist?(setup_path)
50
+ Dir.glob('test/{suite,unit,integration,system}/**/*.rb') { |path|
51
+ helper_path = path.sub(%r{^test/(suite|unit|integration|system)/}, 'test/helper/\1/')
52
+ puts(File.exist?(helper_path) ? "Loading helper file #{helper_path}" : "No helper file #{helper_path} to load") if verbose
53
+ load(helper_path) if File.exist?(helper_path)
54
+ puts "Loading test file #{path}" if verbose
55
+ load(path)
56
+ }
57
+ end
58
+ end
59
+
60
+ # Initializes BareTest, is automatically called
61
+ #
62
+ # Needed for bootstrapped selftest
63
+ def self.init # :nodoc:
64
+ @format = {}
65
+ @extender = []
66
+ @toplevel_suite = BareTest::Suite.new
67
+ @required_file = ["", *$LOAD_PATH].map { |path|
68
+ File.expand_path(File.join(path, __FILE__))
69
+ }.find { |full| File.exist?(full) }
70
+ end
71
+ init
72
+
73
+ # If no description was given, it adds the contained assertions and suites to the toplevel suite,
74
+ # if a description was given, a suite with the given description is created, added to the toplevel
75
+ # suite, and all the contained assertions and suites are added to the created suite.
76
+ def self.suite(description=nil, opts={}, &block)
77
+ if description then
78
+ @toplevel_suite.suite(description, opts, &block)
79
+ elsif opts && !opts.empty?
80
+ raise ArgumentError, "Suites with options must have names"
81
+ else
82
+ @toplevel_suite.instance_eval(&block)
83
+ end
84
+ end
85
+
86
+ # Creates a Test::Run instance, adds the assertions and suites defined in its
87
+ # own block to that Test::Run instance's toplevel suite and if $PROGRAM_NAME
88
+ # (aka $0) is equal to \_\_FILE__ (means the current file is the file directly
89
+ # executed by ruby, and not just required/loaded/evaled by another file),
90
+ # subsequently also runs that suite.
91
+ def self.run_if_mainfile(description=nil, opts={}, &block)
92
+ suite(description, opts, &block)
93
+ if caller.first[/^[^:]*/] == $0 then # if is mainfile
94
+ run(:format => ENV['FORMAT'], :interactive => ENV['INTERACTIVE'])
95
+ end
96
+ end
97
+
98
+ # Runs the toplevel suite (which usually contains all suites and assertions
99
+ # defined in all loaded test files).
100
+ #
101
+ # Returns the Run instance.
102
+ def self.run(opts=nil)
103
+ runner = BareTest::Run.new(@toplevel_suite, opts)
104
+ runner.run_all
105
+ runner
106
+ end
107
+ end
108
+
109
+
110
+
111
+ # At bottom due to dependencies
112
+ require 'baretest/assertion/support' # Needs Test.extender to be defined