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
data/lib/baretest/run.rb CHANGED
@@ -6,15 +6,24 @@
6
6
 
7
7
 
8
8
 
9
+ require 'baretest/persistence'
10
+
11
+
12
+
9
13
  module BareTest
10
14
 
11
- # Run is the environment in which the suites and asserts are executed.
15
+ # Run is the environment in which the suites and assertions are executed.
12
16
  # Prior to the execution, the Run instance extends itself with the
13
- # formatter given.
17
+ # formatter that should be used and other runner related toolsets.
14
18
  # Your formatter can override:
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.
19
+ # :run_all:: Invoked once, before the first run_suite is ran. No
20
+ # arguments.
21
+ # :run_suite:: Invoked per suite. Takes the suite to run as argument.
22
+ # :run_test_variants:: Invoked per assertion. Takes the assertion to execute
23
+ # as argument.
24
+ # :run_test:: Invoked per setup variation of each assertion. Takes
25
+ # the assertion to execute and the setup blocks to use
26
+ # as arguments.
18
27
  #
19
28
  # Don't forget to call super within your overrides, or the tests won't be
20
29
  # executed.
@@ -26,13 +35,10 @@ module BareTest
26
35
  attr_reader :inits
27
36
 
28
37
  # Some statistics, standard count keys are:
29
- # * :test - the number of tests executed until now
30
- # * :suite - the number of suites executed until now
31
- # * :success - the number of tests with status :success
32
- # * :failure - the number of tests with status :failure
33
- # * :pending - the number of tests with status :pending
34
- # * :skipped - the number of tests with status :skipped
35
- # * :error - the number of tests with status :error
38
+ # :test:: the number of tests executed until now
39
+ # :suite:: the number of suites executed until now
40
+ # <status>:: the number of tests with that status (see
41
+ # BareTest::StatusOrder for a list of states)
36
42
  attr_reader :count
37
43
 
38
44
  # Run the passed suite.
@@ -53,19 +59,42 @@ module BareTest
53
59
  # * :format (extends with the formatter module)
54
60
  # * :interactive (extends with IRBMode)
55
61
  def initialize(suite, opts=nil)
56
- @suite = suite
57
- @inits = []
58
- @options = opts || {}
59
- @count = @options[:count] || Hash.new(0)
62
+ @suite = suite
63
+ @inits = []
64
+ @options = opts || {}
65
+ @count = @options[:count] || Hash.new(0)
66
+ @provided = [] # Array's set operations are the fastest
67
+ @include_tags = @options[:include_tags] # nil is ok here
68
+ @exclude_tags = @options[:exclude_tags] # nil is ok here
69
+ include_states = @options[:include_states] # nil is ok here
70
+ exclude_states = @options[:exclude_states] # nil is ok here
71
+ @states = [nil, :success, :failure, :skipped, :pending, :error]
72
+ @skipped = {}
73
+ @last_run_states = {}
74
+
75
+ @persistence = @options[:persistence]
76
+
77
+ if (include_states || exclude_states) && !((include_states && include_states.empty?) && (exclude_states && exclude_states.empty?)) then
78
+ [include_states, exclude_states].compact.each do |states|
79
+ states << nil if states.include?(:new)
80
+ states << :pending if states.include?(:skipped)
81
+ states.concat([:error, :skipped, :pending]) if states.include?(:failure)
82
+ states.delete(:new)
83
+ end
84
+ @states = (include_states || @states) - (exclude_states || [])
85
+ end
60
86
 
61
87
  (BareTest.extender+Array(@options[:extender])).each do |extender|
62
88
  extend(extender)
63
89
  end
64
90
 
65
91
  # Extend with the output formatter
66
- if format = @options[:format] then
67
- require "baretest/run/#{format}" if String === format
68
- extend(String === format ? BareTest.format["baretest/run/#{format}"] : format)
92
+ format = @options[:format]
93
+ if format.is_a?(String) then
94
+ require "baretest/run/#{format}"
95
+ extend(BareTest.format["baretest/run/#{format}"])
96
+ elsif format.is_a?(Module) then
97
+ extend(format)
69
98
  end
70
99
 
71
100
  # Extend with irb dropout code
@@ -93,7 +122,10 @@ module BareTest
93
122
  # Invoked once at the beginning.
94
123
  # Gets the toplevel suite as single argument.
95
124
  def run_all
125
+ @last_run_states = @persistence ? @persistence.read('final_states', {}) : {}
126
+ @skipped = {}
96
127
  run_suite(@suite)
128
+ @persistence.store('final_states', @last_run_states) if @persistence
97
129
  end
98
130
 
99
131
  # Formatter callback.
@@ -101,35 +133,97 @@ module BareTest
101
133
  # Gets the suite to run as single argument.
102
134
  # Runs all assertions and nested suites.
103
135
  def run_suite(suite)
104
- suite.assertions.each do |test|
105
- run_test_variants(test)
136
+ missing_tags = @include_tags && @include_tags - suite.tags
137
+ superfluous_tags = @exclude_tags && suite.tags & @exclude_tags
138
+ ignored = (missing_tags && !missing_tags.empty?) || (superfluous_tags && !superfluous_tags.empty?)
139
+
140
+ unless ignored then
141
+ unmet_dependencies = (suite.depends_on-@provided)
142
+ manually_skipped = suite.skipped?
143
+ recursively_skipped = !unmet_dependencies.empty? || manually_skipped
144
+ skipped = @skipped[suite] || recursively_skipped
145
+
146
+ if recursively_skipped then
147
+ skip_recursively(suite, "Skipped")
148
+ elsif skipped then
149
+ skip_suite(suite, "Skipped")
150
+ end
106
151
  end
107
- suite.suites.each do |(description, suite)|
108
- run_suite(suite)
152
+
153
+ if ignored then
154
+ states = []
155
+ else
156
+ states = suite.assertions.map do |test|
157
+ run_test_variants(test)
158
+ end
109
159
  end
160
+ states.concat(suite.suites.map { |(description, subsuite)|
161
+ run_suite(subsuite)
162
+ })
110
163
  @count[:suite] += 1
164
+
165
+ # || in case the suite contains no tests or suites
166
+ final_status = BareTest.most_important_status(states) || :pending
167
+
168
+ @provided |= suite.provides if final_status == :success
169
+
170
+ Status.new(suite, final_status)
111
171
  end
112
172
 
113
173
  # Invoked once for every assertion.
114
174
  # Iterates over all variants of an assertion and invokes run_test
115
175
  # for each.
116
- def run_test_variants(test)
117
- test.suite.each_component_variant do |setups|
118
- run_test(test, setups)
176
+ def run_test_variants(assertion)
177
+ ignored = !@states.include?(@last_run_states[assertion.id])
178
+ skipped = @skipped[assertion] || assertion.skipped?
179
+
180
+ if ignored then
181
+ overall_status = nil
182
+ elsif skipped then
183
+ Array.new(assertion.suite.component_variant_count) { run_test(assertion, []) }
184
+ @last_run_states[assertion.id] = :manually_skipped
185
+ overall_status = :manually_skipped
186
+ else
187
+ states = []
188
+ assertion.suite.each_component_variant do |setups|
189
+ rv = run_test(assertion, setups)
190
+ states << rv.status
191
+ end
192
+ overall_status = BareTest.most_important_status(states)
119
193
  end
194
+ @last_run_states[assertion.id] = overall_status if overall_status
195
+
196
+ overall_status
120
197
  end
121
198
 
122
199
  # Formatter callback.
123
200
  # Invoked once for every variation of an assertion.
124
201
  # Gets the assertion to run as single argument.
125
202
  def run_test(assertion, setup)
126
- assertion.setups = setup
127
- rv = assertion.execute
128
- @count[:test] += 1
129
- @count[assertion.status] += 1
203
+ rv = assertion.execute(setup.map { |s| s.block }, assertion.suite.ancestry_teardown)
204
+ @count[:test] += 1
205
+ @count[rv.status] += 1
206
+
130
207
  rv
131
208
  end
132
209
 
210
+ # Marks all assertion within this suite as skipped and the suite itself too.
211
+ def skip_suite(suite, reason) # :nodoc:
212
+ suite.skip(reason)
213
+ reason = suite.reason
214
+ suite.assertions.each do |test|
215
+ test.skip(reason)
216
+ end
217
+ end
218
+
219
+ # Marks all tests, suites and their subsuites within this suite as skipped.
220
+ def skip_recursively(suite, reason) # :nodoc:
221
+ skip_suite(suite, reason)
222
+ suite.suites.each do |description, subsuite|
223
+ skip_recursively(subsuite, reason)
224
+ end
225
+ end
226
+
133
227
  # Status over all tests ran up to now
134
228
  # Can be :error, :failure, :incomplete or :success
135
229
  # The algorithm is a simple fall through:
@@ -138,13 +232,20 @@ module BareTest
138
232
  # if not, then if any test was pending or skipped, global_status is :incomplete,
139
233
  # if not, then global_status is success
140
234
  def global_status
141
- case
142
- when @count[:error] > 0 then :error
143
- when @count[:failure] > 0 then :failure
144
- when @count[:pending] > 0 then :incomplete
145
- when @count[:skipped] > 0 then :incomplete
146
- else :success
147
- end
235
+ status_counts = @count.values_at(*BareTest::StatusOrder)
236
+ most_important_status = BareTest::StatusOrder.zip(status_counts) { |status, count|
237
+ break status if count > 0
238
+ } || :success
239
+ end
240
+
241
+ # Get an assertions' interpolated description for a given Array of Setup
242
+ # instances.
243
+ # See Assertion#interpolated_description
244
+ def interpolated_description(assertion, setup)
245
+ setups = setups ? setups.select { |s| s.component } : []
246
+ substitutes = {}
247
+ setups.each do |setup| substitutes[setup.component] = setup.substitute end
248
+ assertion.interpolated_description(substitutes)
148
249
  end
149
250
  end
150
251
  end
@@ -15,14 +15,57 @@ module BareTest
15
15
  # It prints colored output (requires ANSI colors compatible terminal).
16
16
  #
17
17
  module CLI # :nodoc:
18
+ extend Formatter
19
+
20
+ option_defaults :color => true,
21
+ :profile => false
22
+
23
+ text "Options for 'CLI' formatter:\n"
24
+
25
+ option :color, '-c', '--[no-]color', :Boolean, 'Enable/disable output coloring'
26
+ option :profile, '-p', '--[no-]profile', :Boolean, 'Enable/disable profiling assertions'
27
+
28
+ text "\nEnvironment variables for 'CLI' formatter:\n"
29
+
30
+ env_option :color, 'COLOR'
31
+ env_option :profile, 'PROFILE'
32
+
18
33
  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...
34
+ :pending => "\e[43m%9s\e[0m %s%s\n",
35
+ :manually_skipped => "\e[43m%9s\e[0m %s%s\n",
36
+ :dependency_missing => "\e[43m%9s\e[0m %s%s\n",
37
+ :library_missing => "\e[43m%9s\e[0m %s%s\n",
38
+ :component_missing => "\e[43m%9s\e[0m %s%s\n",
39
+ :ignored => "\e[43m%9s\e[0m %s%s\n",
40
+ :skipped => "\e[43m%9s\e[0m %s%s\n",
41
+ :success => "\e[42m%9s\e[0m %s%s\n",
42
+ :failure => "\e[41m%9s\e[0m %s%s\n",
43
+ :error => "\e[37;40;1m%9s\e[0m %s%s\n" # ]]]]]]]]]]]]]]]]]]]] - bbedit hates open brackets...
44
+ }
45
+ StatusLabel = {
46
+ :pending => " Pending ",
47
+ :manually_skipped => " Skipped ",
48
+ :dependency_missing => " Skipped ",
49
+ :library_missing => " Skipped ",
50
+ :component_missing => " Skipped ",
51
+ :ignored => " Skipped ",
52
+ :skipped => " Skipped ",
53
+ :success => " Success ",
54
+ :failure => " Failure ",
55
+ :error => " Error ",
56
+ }
57
+ Map = {
58
+ :pending => :incomplete,
59
+ :manually_skipped => :incomplete,
60
+ :dependency_missing => :incomplete,
61
+ :library_missing => :incomplete,
62
+ :component_missing => :incomplete,
63
+ :ignored => :incomplete,
64
+ :skipped => :incomplete,
65
+ :success => :success,
66
+ :failure => :failure,
67
+ :error => :error,
24
68
  }
25
-
26
69
  FooterFormats = {
27
70
  :incomplete => "\e[43m%9s\e[0m\n",
28
71
  :success => "\e[42m%9s\e[0m\n",
@@ -31,61 +74,63 @@ module BareTest
31
74
  }
32
75
 
33
76
  def run_all(*args)
34
- @depth = 0
35
77
  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)
78
+
79
+ @depth = 0
80
+ @deferred = []
81
+ start = Time.now
82
+ rv = super # run all suites
83
+ duration = Time.now-start
84
+ status = global_status
85
+ test, success, pending, manually_skipped, dependency_missing,
86
+ library_missing, component_missing, ignored, skipped, failure, error =
87
+ *@count.values_at(:test, :success, :pending, :manually_skipped,
88
+ :dependency_missing, :library_missing,
89
+ :component_missing, :ignored, :skipped, :failure,
90
+ :error)
91
+
92
+ printf "\n%2$d tests run in %1$.1fs\n%3$d successful, %4$d pending, %5$d skipped, %6$d failures, %7$d errors\n",
93
+ duration, test, success, pending, (skipped+manually_skipped+
94
+ dependency_missing+library_missing+component_missing), failure, error
41
95
  print "Final status: "
42
- printf FooterFormats[status], status_label(status)
96
+ printf FooterFormats[Map[status]], StatusLabel[status]
97
+
98
+ rv
43
99
  end
44
100
 
45
101
  def run_suite(suite)
46
102
  return super unless suite.description
47
- skipped = suite.skipped.size
48
103
  case size = suite.assertions.size
49
104
  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
105
+ defer "\n \e[1m#{' '*@depth+suite.description}\e[0m"
55
106
  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
107
+ defer "\n \e[1m#{' '*@depth+suite.description}\e[0m (1 test)"
61
108
  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
109
+ defer "\n \e[1m#{' '*@depth+suite.description}\e[0m (#{size} tests)"
67
110
  end
68
111
  @depth += 1
69
- super(suite) # run the suite
112
+ rv = super(suite) # run the suite
113
+ pop_deferred
70
114
  @depth -= 1
115
+
116
+ rv
71
117
  end
72
118
 
73
119
  def run_test(assertion, setup)
74
- rv = super # run the assertion
75
- indent = ' '+' '*@depth
76
- message = []
77
- deeper = []
120
+ clear_deferred
121
+ rv = super # run the assertion
122
+ indent = ' '+' '*@depth
123
+ backtrace = []
124
+ reason = rv.reason(:indent => indent)
78
125
 
79
- printf(Formats[rv.status], status_label(rv.status), ' '*@depth, rv.interpolated_description)
126
+ printf(Formats[rv.status], StatusLabel[rv.status], ' '*@depth, interpolated_description(assertion, setup))
80
127
  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)
128
+ backtrace = $VERBOSE ? rv.exception.backtrace : rv.exception.backtrace.first(1)
83
129
  elsif rv.status == :failure
84
- message = (rv.reason || "no failure reason given").split("\n")
85
- deeper = ["#{rv.file}:#{rv.line}"]
130
+ backtrace = ["#{assertion.file}:#{assertion.line}"]
86
131
  end
87
- message.each do |line| print(indent, line, "\n") end
88
- deeper.each do |line| print(indent, ' ', line, "\n") end
132
+ puts reason if reason
133
+ backtrace.each do |line| print(indent, ' ', line, "\n") end
89
134
 
90
135
  rv
91
136
  end
@@ -94,8 +139,17 @@ module BareTest
94
139
  str.scan(/[^ ]+ /)
95
140
  end
96
141
 
97
- def status_label(status)
98
- status.to_s.capitalize.center(9)
142
+ def defer(output)
143
+ @deferred << output
144
+ end
145
+
146
+ def pop_deferred
147
+ @deferred.pop
148
+ end
149
+
150
+ def clear_deferred
151
+ puts *@deferred unless @deferred.empty?
152
+ @deferred.clear
99
153
  end
100
154
  end
101
155
  end
@@ -18,11 +18,12 @@ module BareTest
18
18
  start = Time.now
19
19
  super # run all suites
20
20
  stop = Time.now
21
- values = @count.values_at(:test, :success, :pending, :failure, :error)
21
+ values = @count.values_at(:test, :success, :pending, :skipped, :failure, :error)
22
22
  values.push(stop-start, global_status)
23
23
  printf "Tests: %d\n" \
24
24
  "Success: %d\n" \
25
25
  "Pending: %d\n" \
26
+ "Skipped: %d\n" \
26
27
  "Failures: %d\n" \
27
28
  "Errors: %d\n" \
28
29
  "Time: %f\n" \
@@ -0,0 +1,21 @@
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
+ class Run
11
+
12
+ # None runner is invoked with `-f none` or `--format none`.
13
+ # This runner produces NO output at all. You can use it if you're only
14
+ # interested in baretests exit status.
15
+ #
16
+ module None # :nodoc:
17
+ end
18
+ end
19
+
20
+ @format["baretest/run/none"] = Run::None # register the extender
21
+ end