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,263 @@
1
+ #--
2
+ # Copyright 2009 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'stringio' # for silencing HAX
10
+
11
+
12
+
13
+ module Kernel
14
+ alias lv! local_variables
15
+ private :lv!
16
+ end
17
+
18
+ module BareTest
19
+
20
+ # For internal use only.
21
+ #
22
+ # This module extends BareTest::Run if --interactive/-i is used
23
+ #
24
+ # See BareTest::IRBMode::AssertionContext for some methods IRBMode adds to Assertion for
25
+ # use within the irb session.
26
+ module IRBMode # :nodoc:
27
+ @irb_setup = false
28
+
29
+ def self.irb_setup! # :nodoc:
30
+ @irb_setup = true
31
+ end
32
+
33
+ def self.irb_setup? # :nodoc:
34
+ @irb_setup
35
+ end
36
+
37
+ # The class used to recreate the failed/errored assertion's context.
38
+ # Adds several methods over plain Assertion.
39
+ module IRBContext
40
+
41
+ attr_accessor :__original__
42
+
43
+ # Prints a list of available helper methods
44
+ def help
45
+ puts "Available methods:",
46
+ "s! - the original assertions' status",
47
+ "e! - prints the error message and full backtrace",
48
+ "em! - prints the error message",
49
+ "bt! - prints the full backtrace",
50
+ "iv! - lists all available instance variables",
51
+ "cv! - lists all available class variables",
52
+ "gv! - lists all available global variables",
53
+ "file - the file this assertion was defined in",
54
+ "line - the line number in the file where this assertion's definition starts",
55
+ "nesting - a >-separated list of suite descriptions this assertion is nested in",
56
+ "description - this assertion's description",
57
+ "code - the code of this assertion",
58
+ #"restart! - Restart this irb session, resetting everything",
59
+ "irb_help - irb's original help",
60
+ "help - this text you're reading right now"
61
+ end
62
+
63
+ def to_s # :nodoc:
64
+ "Context"
65
+ end
66
+
67
+ # Returns the original assertion's status
68
+ def s!
69
+ p @__original__.status
70
+ end
71
+
72
+ # Prints the original assertion's error message and backtrace
73
+ def e!
74
+ em!
75
+ bt!(caller.size+3)
76
+ end
77
+
78
+ # Prints the original assertion's error message
79
+ def em!
80
+ if @__original__.exception then
81
+ puts @__original__.exception.message
82
+ elsif @__original__.reason
83
+ puts @__original__.reason
84
+ else
85
+ puts "No exception occurred, therefore no error message is available"
86
+ end
87
+ end
88
+
89
+ # Prints the original assertion's backtrace
90
+ def bt!(size=nil)
91
+ if @__assertion__.exception then
92
+ size ||= caller.size+3
93
+ puts @__assertion__.exception.backtrace[0..-size]
94
+ else
95
+ puts "No exception occurred, therefore no backtrace is available"
96
+ end
97
+ end
98
+
99
+ # Returns an array of all instance variable names
100
+ def iv!
101
+ puts *instance_variables.sort
102
+ end
103
+
104
+ # Returns an array of all class variable names
105
+ def cv!
106
+ puts *self.class.class_variables.sort
107
+ end
108
+
109
+ # Returns an array of all global variable names
110
+ def gv!
111
+ puts *global_variables.sort
112
+ end
113
+
114
+ # Prints a string of the original assertion's nesting within suites
115
+ def description
116
+ puts @__assertion__.description
117
+ end
118
+
119
+ # Prints a string of the original assertion's nesting within suites
120
+ def nesting
121
+ puts @__assertion__.suite.ancestors[0..-2].reverse.map { |s| s.description }.join(' > ')
122
+ end
123
+
124
+ # Prints the code of the assertion
125
+ # Be aware that this relies on your code being properly indented.
126
+ def code!
127
+ if code = @__assertion__.code then
128
+ puts(insert_line_numbers(code, @__assertion__.line-1))
129
+ else
130
+ puts "Code could not be extracted"
131
+ end
132
+ end
133
+
134
+ def insert_line_numbers(code, start_line=1)
135
+ digits = Math.log10(start_line+code.count("\n")).floor+1
136
+ current_line = start_line-1
137
+ code.gsub(/^/) { sprintf ' %0*d ', digits, current_line+=1 }
138
+ end
139
+ end
140
+
141
+ # Install the init handler
142
+ def self.extended(by) # :nodoc:
143
+ by.init do
144
+ require 'irb'
145
+ require 'pp'
146
+ require 'yaml'
147
+ IRB.setup(nil) unless ::BareTest::IRBMode.irb_setup? # must only be called once
148
+ ::BareTest::IRBMode.irb_setup!
149
+ end
150
+ end
151
+
152
+ # Formatter callback.
153
+ # Invoked once for every assertion.
154
+ # Gets the assertion to run as single argument.
155
+ def run_test(assertion, setup)
156
+ rv = super
157
+ # drop into irb if assertion failed
158
+ case rv.status
159
+ when :failure
160
+ start_irb_failure_mode(assertion)
161
+ irb_mode_for_assertion(assertion)
162
+ stop_irb_mode(assertion)
163
+ when :error
164
+ start_irb_error_mode(assertion)
165
+ irb_mode_for_assertion(assertion)
166
+ stop_irb_mode(assertion)
167
+ end
168
+
169
+ rv
170
+ end
171
+
172
+ # Invoked when we have to drop into irb mode due to a failure
173
+ def start_irb_failure_mode(assertion) # :nodoc:
174
+ ancestry = assertion.suite.ancestors.reverse.map { |suite| suite.description }
175
+
176
+ puts
177
+ puts "#{assertion.status.to_s.capitalize} in: #{ancestry[1..-1].join(' > ')}"
178
+ puts "Description: #{assertion.description}"
179
+ if file = assertion.file then
180
+ code = irb_code_reindented(file, assertion.line-1,20)
181
+ match = code.match(/\n^ [^ ]/)
182
+ code[-(match.post_match.size-3)..-1] = ""
183
+ assertion.code = code
184
+ puts "Code (#{file}):", insert_line_numbers(code, assertion.line-1)
185
+ end
186
+ end
187
+
188
+ # Invoked when we have to drop into irb mode due to an error
189
+ def start_irb_error_mode(assertion) # :nodoc:
190
+ ancestry = assertion.suite.ancestors.reverse.map { |suite| suite.description }
191
+
192
+ puts
193
+ puts "#{assertion.status.to_s.capitalize} in: #{ancestry[1..-1].join(' > ')}"
194
+ puts "Description: #{assertion.description}"
195
+ puts "Exception: #{assertion.exception} in file #{assertion.exception.backtrace.first}"
196
+ if assertion.file && match = assertion.exception.backtrace.first.match(/^([^:]+):(\d+)(?:$|:in .*)/) then
197
+ file, line = match.captures
198
+ file = File.expand_path(file)
199
+ if assertion.file == file then
200
+ code = irb_code_reindented(file, (assertion.line-1)..(line.to_i))
201
+ assertion.code = code
202
+ puts "Code (#{file}):", insert_line_numbers(code, assertion.line-1)
203
+ end
204
+ end
205
+ end
206
+
207
+ # Nicely reformats the assertion's code
208
+ def irb_code_reindented(file, *slice) # :nodoc:
209
+ lines = File.readlines(file)
210
+ string = lines[*slice].join("").sub(/[\r\n]*\z/, '')
211
+ string.gsub!(/^\t+/) { |m| " "*m.size }
212
+ indent = string[/^ +/]
213
+ string.gsub!(/^#{indent}/, ' ')
214
+
215
+ string
216
+ end
217
+
218
+ def insert_line_numbers(code, start_line=1)
219
+ digits = Math.log10(start_line+code.count("\n")).floor+1
220
+ current_line = start_line-1
221
+ code.gsub(/^/) { sprintf ' %0*d ', digits, current_line+=1 }
222
+ end
223
+
224
+ # This method is highlevel hax, try to add necessary API to Test::Assertion
225
+ # Drop into an irb shell in the context of the assertion passed as an argument.
226
+ # Uses Assertion#clean_copy(AssertionContext) to create the context.
227
+ # Adds the code into irb's history.
228
+ def irb_mode_for_assertion(original_assertion) # :nodoc:
229
+ assertion = original_assertion.clone
230
+ assertion.reset
231
+ irb_context = assertion.context
232
+ irb_context.extend IRBContext
233
+ irb_context.__original__ = original_assertion
234
+ assertion.setup
235
+
236
+ $stdout = StringIO.new # HAX - silencing 'irb: warn: can't alias help from irb_help.' - find a better way
237
+ irb = IRB::Irb.new(IRB::WorkSpace.new(irb_context))
238
+ $stdout = STDOUT # /HAX
239
+ # HAX - cargo cult, taken from irb.rb, not yet really understood.
240
+ IRB.conf[:IRB_RC].call(irb.context) if IRB.conf[:IRB_RC] # loads the irbrc?
241
+ IRB.conf[:MAIN_CONTEXT] = irb.context # why would the main context be set here?
242
+ # /HAX
243
+
244
+ trap("SIGINT") do irb.signal_handle end
245
+
246
+ if code = original_assertion.code then
247
+ #irb_context.code = code
248
+ Readline::HISTORY.push(*code.split("\n")[1..-2])
249
+ end
250
+
251
+ catch(:IRB_EXIT) do irb.eval_input end
252
+
253
+ assertion.teardown
254
+ end
255
+
256
+ # Invoked when we leave the irb session
257
+ def stop_irb_mode(assertion) # :nodoc:
258
+ puts
259
+ super
260
+ rescue NoMethodError # HAX, not happy about that. necessary due to order of extend
261
+ end
262
+ end
263
+ end
@@ -6,9 +6,10 @@
6
6
 
7
7
 
8
8
 
9
- module Test
10
- class Assertion
11
- class Failure < StandardError
12
- end
13
- end
9
+ module BareTest
10
+ # :stopdoc:
11
+ Layout = Struct.new(
12
+ :foo
13
+ )
14
+ # :startdoc:
14
15
  end
@@ -0,0 +1,18 @@
1
+ # Created by dominikh
2
+
3
+ # This file provides integration with the "mocha" mocking framework.
4
+
5
+ require 'mocha'
6
+
7
+ BareTest.extend Mocha::API
8
+
9
+ BareTest.toplevel_suite.teardown do
10
+ begin
11
+ BareTest.mocha_verify
12
+ rescue Mocha::ExpectationError => e
13
+ @reason = e.message
14
+ @status = :failure
15
+ ensure
16
+ BareTest.mocha_teardown
17
+ end
18
+ end
@@ -0,0 +1,104 @@
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
+ # CLI runner is invoked with `-f cli` or `--format cli`.
13
+ # It is intended for use with an interactive shell, to provide a comfortable, human
14
+ # readable output.
15
+ # It prints colored output (requires ANSI colors compatible terminal).
16
+ #
17
+ module CLI # :nodoc:
18
+ Formats = {
19
+ :pending => "\e[43m%9s\e[0m %s%s\n",
20
+ :skipped => "\e[43m%9s\e[0m %s%s\n",
21
+ :success => "\e[42m%9s\e[0m %s%s\n",
22
+ :failure => "\e[41m%9s\e[0m %s%s\n",
23
+ :error => "\e[37;40;1m%9s\e[0m %s%s\n" # ]]]]]]]] - bbedit hates open brackets...
24
+ }
25
+
26
+ FooterFormats = {
27
+ :incomplete => "\e[43m%9s\e[0m\n",
28
+ :success => "\e[42m%9s\e[0m\n",
29
+ :failure => "\e[41m%9s\e[0m\n",
30
+ :error => "\e[37;40;1m%9s\e[0m\n" # ]]]]]]]] - bbedit hates open brackets...
31
+ }
32
+
33
+ def run_all(*args)
34
+ @depth = 0
35
+ puts "Running all tests#{' verbosly' if $VERBOSE}"
36
+ start = Time.now
37
+ super # run all suites
38
+ status = global_status
39
+ printf "\n%2$d tests run in %1$.1fs\n%3$d successful, %4$d pending, %5$d failures, %6$d errors\n",
40
+ Time.now-start, *@count.values_at(:test, :success, :pending, :failure, :error)
41
+ print "Final status: "
42
+ printf FooterFormats[status], status_label(status)
43
+ end
44
+
45
+ def run_suite(suite)
46
+ return super unless suite.description
47
+ skipped = suite.skipped.size
48
+ case size = suite.assertions.size
49
+ when 0
50
+ if skipped.zero? then
51
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m"
52
+ else
53
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{skipped} skipped)"
54
+ end
55
+ when 1
56
+ if skipped.zero? then
57
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (1 test)"
58
+ else
59
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (1 test/#{skipped} skipped)"
60
+ end
61
+ else
62
+ if skipped.zero? then
63
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{size} tests)"
64
+ else
65
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{size} tests/#{skipped} skipped)"
66
+ end
67
+ end
68
+ @depth += 1
69
+ super(suite) # run the suite
70
+ @depth -= 1
71
+ end
72
+
73
+ def run_test(assertion, setup)
74
+ rv = super # run the assertion
75
+ indent = ' '+' '*@depth
76
+ message = []
77
+ deeper = []
78
+
79
+ printf(Formats[rv.status], status_label(rv.status), ' '*@depth, rv.interpolated_description)
80
+ if rv.status == :error then
81
+ message = (rv.exception.message || "no error message given").split("\n")
82
+ deeper = $VERBOSE ? rv.exception.backtrace : rv.exception.backtrace.first(1)
83
+ elsif rv.status == :failure
84
+ message = (rv.reason || "no failure reason given").split("\n")
85
+ deeper = ["#{rv.file}:#{rv.line}"]
86
+ end
87
+ message.each do |line| print(indent, line, "\n") end
88
+ deeper.each do |line| print(indent, ' ', line, "\n") end
89
+
90
+ rv
91
+ end
92
+
93
+ def word_wrap(string, cols)
94
+ str.scan(/[^ ]+ /)
95
+ end
96
+
97
+ def status_label(status)
98
+ status.to_s.capitalize.center(9)
99
+ end
100
+ end
101
+ end
102
+
103
+ @format["baretest/run/cli"] = Run::CLI # register the extender
104
+ end
@@ -6,9 +6,14 @@
6
6
 
7
7
 
8
8
 
9
- module Test
9
+ module BareTest
10
10
  class Run
11
- module Errors
11
+
12
+ # Errors runner is invoked with `-f errors` or `--format errors`.
13
+ # This runner is specifically built to provide the most possible information about
14
+ # errors in the suite.
15
+ #
16
+ module Errors # :nodoc:
12
17
  def run_all
13
18
  @depth = 0
14
19
  puts "Running all tests, reporting errors"
@@ -19,24 +24,24 @@ module Test
19
24
 
20
25
  def run_suite(suite)
21
26
  return super unless suite.description
22
- puts "#{' '*@depth+suite.description} (#{suite.tests.size} tests)"
27
+ puts "#{' '*@depth+suite.description} (#{suite.assertions.size} tests, #{suite.skipped.size} skipped)"
23
28
  @depth += 1
24
29
  super # run the suite
25
30
  @depth -= 1
26
31
  end
27
32
 
28
- def run_test(assertion)
33
+ def run_test(assertion, setup)
29
34
  rv = super # run the assertion
30
35
  puts(' '*@depth+rv.description)
31
36
  if rv.exception then
32
37
  size = caller.size+5
33
- puts((['-'*80, rv.exception]+rv.exception.backtrace[0..-size]+['-'*80, '']).map { |l|
34
- (' '*(@depth+1))+l
38
+ puts((['-'*80, rv.exception.message]+rv.exception.backtrace[0..-size]+['-'*80, '']).map { |l|
39
+ (' '*(@depth+1))+l
35
40
  })
36
41
  end
37
42
  end
38
43
  end
39
44
  end
40
45
 
41
- @format["test/run/errors"] = Run::Errors # register the extender
46
+ @format["baretest/run/errors"] = Run::Errors # register the extender
42
47
  end
@@ -6,9 +6,14 @@
6
6
 
7
7
 
8
8
 
9
- module Test
9
+ module BareTest
10
10
  class Run
11
- module Minimal
11
+
12
+ # Minimal runner is invoked with `-f minimal` or `--format minimal`.
13
+ # This runner is mainly written as an example. It will provide the final
14
+ # statistics (number of tests, successes, etc.).
15
+ #
16
+ module Minimal # :nodoc:
12
17
  def run_all(*args)
13
18
  start = Time.now
14
19
  super # run all suites
@@ -27,5 +32,5 @@ module Test
27
32
  end
28
33
  end
29
34
 
30
- @format["test/run/minimal"] = Run::Minimal # register the extender
35
+ @format["baretest/run/minimal"] = Run::Minimal # register the extender
31
36
  end
@@ -0,0 +1,151 @@
1
+ # encoding: utf-8
2
+ #--
3
+ # Copyright 2009 by Stefan Rusterholz.
4
+ # All rights reserved.
5
+ # See LICENSE.txt for permissions.
6
+ #++
7
+
8
+
9
+
10
+ module BareTest
11
+ class Run
12
+
13
+ # CLI runner is invoked with `-f cli` or `--format cli`.
14
+ # It is intended for use with an interactive shell, to provide a comfortable, human
15
+ # readable output.
16
+ # It prints colored output (requires ANSI colors compatible terminal).
17
+ #
18
+ module Profile # :nodoc:
19
+ Formats = {
20
+ :pending => "\e[43m%9s\e[0m %s%s (%s)\n",
21
+ :skipped => "\e[43m%9s\e[0m %s%s (%s)\n",
22
+ :success => "\e[42m%9s\e[0m %s%s (%s)\n",
23
+ :failure => "\e[41m%9s\e[0m %s%s (%s)\n",
24
+ :error => "\e[37;40;1m%9s\e[0m %s%s (%s)\n" # ]]]]]]]] - bbedit hates open brackets...
25
+ }
26
+
27
+ FooterFormats = {
28
+ :incomplete => "\e[43m%9s\e[0m\n",
29
+ :success => "\e[42m%9s\e[0m\n",
30
+ :failure => "\e[41m%9s\e[0m\n",
31
+ :error => "\e[37;40;1m%9s\e[0m\n" # ]]]]]]]] - bbedit hates open brackets...
32
+ }
33
+
34
+ def run_all(*args)
35
+ @depth = 0
36
+ puts "Running all tests#{' verbosly' if $VERBOSE}"
37
+ start = Time.now
38
+ super # run all suites
39
+ status = global_status
40
+ printf "\n%2$d tests run in %1$.1fs\n%3$d successful, %4$d pending, %5$d failures, %6$d errors\n",
41
+ Time.now-start, *@count.values_at(:test, :success, :pending, :failure, :error)
42
+ print "Final status: "
43
+ printf FooterFormats[status], status_label(status)
44
+ end
45
+
46
+ def run_suite(suite)
47
+ return super unless suite.description
48
+ skipped = suite.skipped.size
49
+ case size = suite.assertions.size
50
+ when 0
51
+ if skipped.zero? then
52
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m"
53
+ else
54
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{skipped} skipped)"
55
+ end
56
+ when 1
57
+ if skipped.zero? then
58
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (1 test)"
59
+ else
60
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (1 test/#{skipped} skipped)"
61
+ end
62
+ else
63
+ if skipped.zero? then
64
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{size} tests)"
65
+ else
66
+ puts "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{size} tests/#{skipped} skipped)"
67
+ end
68
+ end
69
+ @depth += 1
70
+ super(suite) # run the suite
71
+ @depth -= 1
72
+ end
73
+
74
+ def run_test(assertion, setup)
75
+ start = Time.now
76
+ rv = super # run the assertion
77
+ times = [Time.now-start]
78
+
79
+ if times.first < 1e-3 then
80
+ iters = 19
81
+ elsif times.first < 1
82
+ iters = 2
83
+ else
84
+ iters = 0
85
+ end
86
+
87
+ iters.times do
88
+ assertion.reset
89
+ start = Time.now
90
+ assertion.execute
91
+ times << (Time.now-start)
92
+ end
93
+
94
+ time = times.inject{ |a,b| a+b }/iters
95
+
96
+ indent = ' '+' '*@depth
97
+ message = []
98
+ deeper = []
99
+
100
+ printf(
101
+ Formats[rv.status],
102
+ status_label(rv.status),
103
+ ' '*@depth,
104
+ rv.description,
105
+ humanized_duration(time)
106
+ )
107
+ if rv.status == :error then
108
+ message = (rv.exception.message || "no error message given").split("\n")
109
+ deeper = $VERBOSE ? rv.exception.backtrace : rv.exception.backtrace.first(1)
110
+ elsif rv.status == :failure
111
+ message = (rv.reason || "no failure reason given").split("\n")
112
+ deeper = ["#{rv.file}:#{rv.line}"]
113
+ end
114
+ message.each do |line| print(indent, line, "\n") end
115
+ deeper.each do |line| print(indent, ' ', line, "\n") end
116
+
117
+ rv
118
+ end
119
+
120
+ def word_wrap(string, cols)
121
+ str.scan(/[^ ]+ /)
122
+ end
123
+
124
+ def status_label(status)
125
+ status.to_s.capitalize.center(9)
126
+ end
127
+
128
+ def humanized_duration(duration)
129
+ case
130
+ when duration < 1e-3
131
+ "%dµs" % (duration*1e6)
132
+ when duration < 1
133
+ "%.1fms" % (duration*1e3)
134
+ when duration < 60
135
+ "%.1fs" % duration
136
+ else
137
+ minutes, seconds = *duration.divmod(60)
138
+ hours, minutes = *minutes.divmod(60)
139
+ # lets assume unit tests don't take more than a day :)
140
+ if hours > 0 then
141
+ "#{hours}h #{minutes}m #{seconds}s"
142
+ else
143
+ "#{minutes}m #{seconds}s"
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ @format["baretest/run/profile"] = Run::Profile # register the extender
151
+ end
@@ -6,9 +6,15 @@
6
6
 
7
7
 
8
8
 
9
- module Test
9
+ module BareTest
10
10
  class Run
11
- module Spec
11
+
12
+ # Spec runner is invoked with `-f spec` or `--format spec`.
13
+ # This runner will not actually run the tests. It only extracts the descriptions and
14
+ # prints them. Handy if you just want an overview over what a library is supposed to do
15
+ # and be capable of.
16
+ #
17
+ module Spec # :nodoc:
12
18
  def run_all
13
19
  @depth = 0
14
20
  super
@@ -22,11 +28,11 @@ module Test
22
28
  @depth -= 1
23
29
  end
24
30
 
25
- def run_test(assertion)
31
+ def run_test(assertion, setup)
26
32
  puts(' '*@depth+assertion.description)
27
33
  end
28
34
  end
29
35
  end
30
36
 
31
- @format["test/run/spec"] = Run::Spec
37
+ @format["baretest/run/spec"] = Run::Spec
32
38
  end
@@ -0,0 +1,44 @@
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
+ # TAP runner is invoked with `-f tap` or `--format tap`.
13
+ # TAP (Test Anything Protocol) output is intended as a universal, machine readable
14
+ # output format of test frameworks. The are various tools that can further process
15
+ # that information and leverage it in various ways of automation.
16
+ # This runner currently implements the TA Protocol in version 13.
17
+ #
18
+ module TAP # :nodoc:
19
+ def run_all
20
+ puts "TAP version 13"
21
+ count = proc { |acc,csuite|
22
+ acc+
23
+ csuite.assertions.size+
24
+ csuite.skipped.size+
25
+ csuite.suites.map { |d,suite| suite }.inject(0, &count)
26
+ }
27
+ puts "1..#{count[0, suite]}"
28
+ @current = 0
29
+ super
30
+ end
31
+
32
+ def run_test(assertion, setup)
33
+ rv = super
34
+ printf "%sok %d - %s%s\n",
35
+ rv.status == :success ? '' : 'not ',
36
+ @current+=1,
37
+ rv.description,
38
+ rv.status == :success ? '' : " # #{rv.status}"
39
+ end
40
+ end
41
+ end
42
+
43
+ @format["baretest/run/tap"] = Run::TAP
44
+ end