ryanbriones-ZenTest 3.11.1

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 (70) hide show
  1. data/History.txt +523 -0
  2. data/Manifest.txt +69 -0
  3. data/README.txt +110 -0
  4. data/Rakefile +68 -0
  5. data/articles/Article.css +721 -0
  6. data/articles/getting_started_with_autotest.html +532 -0
  7. data/articles/how_to_use_zentest.txt +393 -0
  8. data/bin/autotest +55 -0
  9. data/bin/multiruby +40 -0
  10. data/bin/multiruby_setup +68 -0
  11. data/bin/rails_test_audit +80 -0
  12. data/bin/unit_diff +38 -0
  13. data/bin/zentest +28 -0
  14. data/example.txt +42 -0
  15. data/example1.rb +7 -0
  16. data/example2.rb +15 -0
  17. data/example_dot_autotest.rb +45 -0
  18. data/lib/autotest.rb +654 -0
  19. data/lib/autotest/autoupdate.rb +26 -0
  20. data/lib/autotest/camping.rb +37 -0
  21. data/lib/autotest/cctray.rb +57 -0
  22. data/lib/autotest/discover.rb +6 -0
  23. data/lib/autotest/emacs.rb +35 -0
  24. data/lib/autotest/email_notify.rb +66 -0
  25. data/lib/autotest/fixtures.rb +12 -0
  26. data/lib/autotest/growl.rb +28 -0
  27. data/lib/autotest/heckle.rb +14 -0
  28. data/lib/autotest/html_report.rb +31 -0
  29. data/lib/autotest/jabber_notify.rb +111 -0
  30. data/lib/autotest/kdenotify.rb +14 -0
  31. data/lib/autotest/menu.rb +51 -0
  32. data/lib/autotest/migrate.rb +7 -0
  33. data/lib/autotest/notify.rb +34 -0
  34. data/lib/autotest/once.rb +9 -0
  35. data/lib/autotest/pretty.rb +83 -0
  36. data/lib/autotest/rails.rb +81 -0
  37. data/lib/autotest/rcov.rb +22 -0
  38. data/lib/autotest/redgreen.rb +21 -0
  39. data/lib/autotest/restart.rb +11 -0
  40. data/lib/autotest/screen.rb +73 -0
  41. data/lib/autotest/shame.rb +45 -0
  42. data/lib/autotest/snarl.rb +51 -0
  43. data/lib/autotest/timestamp.rb +9 -0
  44. data/lib/functional_test_matrix.rb +92 -0
  45. data/lib/multiruby.rb +401 -0
  46. data/lib/test/rails.rb +295 -0
  47. data/lib/test/rails/controller_test_case.rb +382 -0
  48. data/lib/test/rails/functional_test_case.rb +79 -0
  49. data/lib/test/rails/helper_test_case.rb +64 -0
  50. data/lib/test/rails/ivar_proxy.rb +31 -0
  51. data/lib/test/rails/pp_html_document.rb +74 -0
  52. data/lib/test/rails/rake_tasks.rb +50 -0
  53. data/lib/test/rails/render_tree.rb +93 -0
  54. data/lib/test/rails/test_case.rb +28 -0
  55. data/lib/test/rails/view_test_case.rb +597 -0
  56. data/lib/test/zentest_assertions.rb +134 -0
  57. data/lib/unit_diff.rb +259 -0
  58. data/lib/zentest.rb +566 -0
  59. data/lib/zentest_mapping.rb +99 -0
  60. data/test/test_autotest.rb +449 -0
  61. data/test/test_help.rb +36 -0
  62. data/test/test_rails_autotest.rb +229 -0
  63. data/test/test_rails_controller_test_case.rb +58 -0
  64. data/test/test_rails_helper_test_case.rb +48 -0
  65. data/test/test_rails_view_test_case.rb +275 -0
  66. data/test/test_unit_diff.rb +319 -0
  67. data/test/test_zentest.rb +566 -0
  68. data/test/test_zentest_assertions.rb +128 -0
  69. data/test/test_zentest_mapping.rb +222 -0
  70. metadata +151 -0
@@ -0,0 +1,99 @@
1
+ ##
2
+ # ZenTestMapping - mapping method names from impl to test.
3
+ #
4
+ # Method names are mapped bidirectionally in the following way:
5
+ #
6
+ # method test_method
7
+ # method? test_method_eh (too much exposure to Canadians :)
8
+ # method! test_method_bang
9
+ # method= test_method_equals
10
+ # [] test_index
11
+ # * test_times
12
+ # == test_equals2
13
+ # === test_equals3
14
+ #
15
+ # Further, any of the test methods should be able to have arbitrary
16
+ # extensions put on the name to distinguish edge cases:
17
+ #
18
+ # method test_method
19
+ # method test_method_simple
20
+ # method test_method_no_network
21
+ #
22
+ # To allow for unmapped test methods (ie, non-unit tests), name them:
23
+ #
24
+ # test_integration_.*
25
+
26
+ module ZenTestMapping
27
+
28
+ @@orig_method_map = {
29
+ '!' => 'bang',
30
+ '%' => 'percent',
31
+ '&' => 'and',
32
+ '*' => 'times',
33
+ '**' => 'times2',
34
+ '+' => 'plus',
35
+ '-' => 'minus',
36
+ '/' => 'div',
37
+ '<' => 'lt',
38
+ '<=' => 'lte',
39
+ '<=>' => 'spaceship',
40
+ "<\<" => 'lt2',
41
+ '==' => 'equals2',
42
+ '===' => 'equals3',
43
+ '=~' => 'equalstilde',
44
+ '>' => 'gt',
45
+ '>=' => 'ge',
46
+ '>>' => 'gt2',
47
+ '+@' => 'unary_plus',
48
+ '-@' => 'unary_minus',
49
+ '[]' => 'index',
50
+ '[]=' => 'index_equals',
51
+ '^' => 'carat',
52
+ '|' => 'or',
53
+ '~' => 'tilde',
54
+ }
55
+
56
+ @@method_map = @@orig_method_map.merge(@@orig_method_map.invert)
57
+
58
+ # Generates a test method name from a normal method,
59
+ # taking into account names composed of metacharacters
60
+ # (used for arithmetic, etc
61
+ def normal_to_test(name)
62
+ name = name.to_s.dup # wtf?
63
+ is_cls_method = name.sub!(/^self\./, '')
64
+ name = @@method_map[name] if @@method_map.has_key? name
65
+ name = name.sub(/=$/, '_equals')
66
+ name = name.sub(/\?$/, '_eh')
67
+ name = name.sub(/\!$/, '_bang')
68
+ name = "class_" + name if is_cls_method
69
+ "test_#{name}"
70
+ end
71
+
72
+ # Converts a method name beginning with test to its
73
+ # corresponding normal method name, taking into account
74
+ # symbolic names which may have been anglicised by
75
+ # #normal_to_test().
76
+ def test_to_normal(name, klassname=nil)
77
+ name = name.to_s
78
+
79
+ known_methods = (@inherited_methods[klassname] || {}).keys.sort.reverse
80
+
81
+ mapped_re = @@orig_method_map.values.sort_by { |k| k.length }.map {|s| Regexp.escape(s)}.reverse.join("|")
82
+ known_methods_re = known_methods.map {|s| Regexp.escape(s)}.join("|")
83
+
84
+ name = name.sub(/^test_/, '')
85
+ name = name.sub(/_equals/, '=') unless name =~ /index/
86
+ name = name.sub(/_bang.*$/, '!') # FIX: deal w/ extensions separately
87
+ name = name.sub(/_eh/, '?')
88
+ is_cls_method = name.sub!(/^class_/, '')
89
+ name = name.sub(/^(#{mapped_re})(_.*)?$/) {$1}
90
+ name = name.sub(/^(#{known_methods_re})(.*)$/) {$1} unless known_methods_re.empty?
91
+
92
+ # look up in method map
93
+ name = @@method_map[name] if @@method_map.has_key? name
94
+
95
+ name = 'self.' + name if is_cls_method
96
+
97
+ name
98
+ end
99
+ end
@@ -0,0 +1,449 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ $TESTING = true
4
+
5
+ require 'test/unit/testcase'
6
+ require 'test/unit' if $0 == __FILE__
7
+ require 'stringio'
8
+ require 'autotest'
9
+
10
+ # NOT TESTED:
11
+ # class_run
12
+ # add_sigint_handler
13
+ # all_good
14
+ # get_to_green
15
+ # reset
16
+ # ruby
17
+ # run
18
+ # run_tests
19
+
20
+ class Autotest
21
+ attr_reader :test_mappings, :exception_list
22
+
23
+ def self.clear_hooks
24
+ HOOKS.clear
25
+ end
26
+ end
27
+
28
+ class TestAutotest < Test::Unit::TestCase
29
+
30
+ def deny test, msg=nil
31
+ if msg then
32
+ assert ! test, msg
33
+ else
34
+ assert ! test
35
+ end
36
+ end unless respond_to? :deny
37
+
38
+ RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) unless defined? RUBY
39
+
40
+ def setup
41
+ @test_class = 'TestBlah'
42
+ @test = 'test/test_blah.rb'
43
+ @other_test = 'test/test_blah_other.rb'
44
+ @impl = 'lib/blah.rb'
45
+ @inner_test = 'test/outer/test_inner.rb'
46
+ @outer_test = 'test/test_outer.rb'
47
+ @inner_test_class = "TestOuter::TestInner"
48
+
49
+ klassname = self.class.name.sub(/^Test/, '')
50
+ klassname.sub!(/^(\w+)(Autotest)$/, '\2::\1') unless klassname == "Autotest"
51
+ @a = klassname.split(/::/).inject(Object) { |k,n| k.const_get(n) }.new
52
+ @a.output = StringIO.new
53
+ @a.last_mtime = Time.at(2)
54
+
55
+ @files = {}
56
+ @files[@impl] = Time.at(1)
57
+ @files[@test] = Time.at(2)
58
+
59
+ @a.find_order = @files.keys.sort
60
+ end
61
+
62
+ def test_add_exception
63
+ current = util_exceptions
64
+ @a.add_exception 'blah'
65
+
66
+ actual = util_exceptions
67
+ expect = current + ["blah"]
68
+
69
+ assert_equal expect, actual
70
+ end
71
+
72
+ def test_add_mapping
73
+ current = util_mappings
74
+ @a.add_mapping(/blah/) do 42 end
75
+
76
+ actual = util_mappings
77
+ expect = current + [/blah/]
78
+
79
+ assert_equal expect, actual
80
+ end
81
+
82
+ def test_clear_exceptions
83
+ test_add_exception
84
+ @a.clear_exceptions
85
+
86
+ actual = util_exceptions
87
+ expect = []
88
+
89
+ assert_equal expect, actual
90
+ end
91
+
92
+ def test_clear_mapping
93
+ @a.clear_mappings
94
+
95
+ actual = util_mappings
96
+ expect = []
97
+
98
+ assert_equal expect, actual
99
+ end
100
+
101
+ def test_consolidate_failures_experiment
102
+ @files.clear
103
+ @files[@impl] = Time.at(1)
104
+ @files[@test] = Time.at(2)
105
+
106
+ @a.find_order = @files.keys.sort
107
+
108
+ input = [['test_fail1', @test_class], ['test_fail2', @test_class], ['test_error1', @test_class], ['test_error2', @test_class]]
109
+ result = @a.consolidate_failures input
110
+ expected = { @test => %w( test_fail1 test_fail2 test_error1 test_error2 ) }
111
+ assert_equal expected, result
112
+ end
113
+
114
+ def test_consolidate_failures_green
115
+ result = @a.consolidate_failures([])
116
+ expected = {}
117
+ assert_equal expected, result
118
+ end
119
+
120
+ def test_consolidate_failures_multiple_possibilities
121
+ @files[@other_test] = Time.at(42)
122
+ result = @a.consolidate_failures([['test_unmatched', @test_class]])
123
+ expected = { @test => ['test_unmatched']}
124
+ assert_equal expected, result
125
+ expected = ""
126
+ assert_equal expected, @a.output.string
127
+ end
128
+
129
+ def test_consolidate_failures_nested_classes
130
+ @files.clear
131
+ @files['lib/outer.rb'] = Time.at(5)
132
+ @files['lib/outer/inner.rb'] = Time.at(5)
133
+ @files[@inner_test] = Time.at(5)
134
+ @files[@outer_test] = Time.at(5)
135
+
136
+ @a.find_order = @files.keys.sort
137
+
138
+ result = @a.consolidate_failures([['test_blah1', @inner_test_class]])
139
+ expected = { @inner_test => ['test_blah1'] }
140
+ assert_equal expected, result
141
+ expected = ""
142
+ assert_equal expected, @a.output.string
143
+ end
144
+
145
+ def test_consolidate_failures_no_match
146
+ result = @a.consolidate_failures([['test_blah1', @test_class], ['test_blah2', @test_class], ['test_blah1', 'TestUnknown']])
147
+ expected = {@test => ['test_blah1', 'test_blah2']}
148
+ assert_equal expected, result
149
+ expected = "Unable to map class TestUnknown to a file\n"
150
+ assert_equal expected, @a.output.string
151
+ end
152
+
153
+ def test_consolidate_failures_red
154
+ result = @a.consolidate_failures([['test_blah1', @test_class], ['test_blah2', @test_class]])
155
+ expected = {@test => ['test_blah1', 'test_blah2']}
156
+ assert_equal expected, result
157
+ end
158
+
159
+ def test_exceptions
160
+ @a.clear_exceptions
161
+ test_add_exception
162
+ assert_equal(/blah/, @a.exceptions)
163
+ end
164
+
165
+ def test_exceptions_nil
166
+ @a.clear_exceptions
167
+ assert_nil @a.exceptions
168
+ end
169
+
170
+ # TODO: lots of filename edgecases for find_files_to_test
171
+ def test_find_files_to_test
172
+ @a.last_mtime = Time.at(0)
173
+ assert @a.find_files_to_test(@files)
174
+
175
+ @a.last_mtime = @files.values.sort.last + 1
176
+ deny @a.find_files_to_test(@files)
177
+ end
178
+
179
+ def test_find_files_to_test_dunno
180
+ empty = {}
181
+
182
+ files = { "fooby.rb" => Time.at(42) }
183
+ assert @a.find_files_to_test(files) # we find fooby,
184
+ assert_equal empty, @a.files_to_test # but it isn't something to test
185
+ assert_equal "No tests matched fooby.rb\n", @a.output.string
186
+ end
187
+
188
+ def test_find_files_to_test_lib
189
+ # ensure we add test_blah.rb when blah.rb updates
190
+ util_find_files_to_test(@impl, @test => [])
191
+ end
192
+
193
+ def test_find_files_to_test_no_change
194
+ empty = {}
195
+
196
+ # ensure world is virginal
197
+ assert_equal empty, @a.files_to_test
198
+
199
+ # ensure we do nothing when nothing changes...
200
+ files = { @impl => @files[@impl] } # same time
201
+ deny @a.find_files_to_test(files)
202
+ assert_equal empty, @a.files_to_test
203
+ assert_equal "", @a.output.string
204
+
205
+ files = { @impl => @files[@impl] } # same time
206
+ assert(! @a.find_files_to_test(files))
207
+ assert_equal empty, @a.files_to_test
208
+ assert_equal "", @a.output.string
209
+ end
210
+
211
+ def test_find_files_to_test_test
212
+ # ensure we add test_blah.rb when test_blah.rb itself updates
213
+ util_find_files_to_test(@test, @test => [])
214
+ end
215
+
216
+ def test_reorder_alpha
217
+ @a.order = :alpha
218
+ expected = @files.sort
219
+
220
+ assert_equal expected, @a.reorder(@files)
221
+ end
222
+
223
+ def test_reorder_reverse
224
+ @a.order = :reverse
225
+ expected = @files.sort.reverse
226
+
227
+ assert_equal expected, @a.reorder(@files)
228
+ end
229
+
230
+ def test_reorder_random
231
+ @a.order = :random
232
+
233
+ srand 42
234
+ expected, size = @files.dup, @files.size
235
+ expected = expected.sort_by { rand(size) }
236
+
237
+ srand 42
238
+ result = @a.reorder(@files.dup)
239
+
240
+ assert_equal expected, result
241
+ end
242
+
243
+ def test_reorder_natural
244
+ srand 42
245
+
246
+ @files['lib/untested_blah.rb'] = Time.at(2)
247
+ @a.find_order = @files.keys.sort_by { rand }
248
+
249
+ @a.order = :natural
250
+ expected = @a.find_order.map { |f| [f, @files[f]] }
251
+
252
+ assert_equal expected, @a.reorder(@files)
253
+ end
254
+
255
+ def test_handle_results
256
+ @a.files_to_test.clear
257
+ @files.clear
258
+ @files[@impl] = Time.at(1)
259
+ @files[@test] = Time.at(2)
260
+
261
+ @a.find_order = @files.keys.sort
262
+
263
+ empty = {}
264
+ assert_equal empty, @a.files_to_test, "must start empty"
265
+
266
+ s1 = "Loaded suite -e
267
+ Started
268
+ ............
269
+ Finished in 0.001655 seconds.
270
+
271
+ 12 tests, 18 assertions, 0 failures, 0 errors
272
+ "
273
+
274
+ @a.handle_results(s1)
275
+ assert_equal empty, @a.files_to_test, "must stay empty"
276
+
277
+ s2 = "
278
+ 1) Failure:
279
+ test_fail1(#{@test_class}) [#{@test}:59]:
280
+ 2) Failure:
281
+ test_fail2(#{@test_class}) [#{@test}:60]:
282
+ 3) Error:
283
+ test_error1(#{@test_class}):
284
+ 3) Error:
285
+ test_error2(#{@test_class}):
286
+
287
+ 12 tests, 18 assertions, 2 failures, 2 errors
288
+ "
289
+
290
+ @a.handle_results(s2)
291
+ expected = { @test => %w( test_fail1 test_fail2 test_error1 test_error2 ) }
292
+ assert_equal expected, @a.files_to_test
293
+ assert @a.tainted
294
+
295
+ @a.handle_results(s1)
296
+ assert_equal empty, @a.files_to_test
297
+
298
+ s3 = '
299
+ /opt/bin/ruby -I.:lib:test -rtest/unit -e "%w[#{@test}].each { |f| require f }" | unit_diff -u
300
+ -e:1:in `require\': ./#{@test}:23: parse error, unexpected tIDENTIFIER, expecting \'}\' (SyntaxError)
301
+ settings_fields.each {|e| assert_equal e, version.send e.intern}
302
+ ^ from -e:1
303
+ from -e:1:in `each\'
304
+ from -e:1
305
+ '
306
+ @a.files_to_test[@test] = Time.at(42)
307
+ @files[@test] = []
308
+ expected = { @test => Time.at(42) }
309
+ assert_equal expected, @a.files_to_test
310
+ @a.handle_results(s3)
311
+ assert_equal expected, @a.files_to_test
312
+ assert @a.tainted
313
+ @a.tainted = false
314
+
315
+ @a.handle_results(s1)
316
+ assert_equal empty, @a.files_to_test
317
+ deny @a.tainted
318
+ end
319
+
320
+ def test_hook_overlap_returning_false
321
+ util_reset_hooks_returning false
322
+
323
+ @a.hook :blah
324
+
325
+ assert @a.instance_variable_get(:@blah1), "Hook1 should work on blah"
326
+ assert @a.instance_variable_get(:@blah2), "Hook2 should work on blah"
327
+ assert @a.instance_variable_get(:@blah3), "Hook3 should work on blah"
328
+ end
329
+
330
+ def test_hook_overlap_returning_true
331
+ util_reset_hooks_returning true
332
+
333
+ @a.hook :blah
334
+
335
+ assert @a.instance_variable_get(:@blah1), "Hook1 should work on blah"
336
+ deny @a.instance_variable_get(:@blah2), "Hook2 should NOT work on blah"
337
+ deny @a.instance_variable_get(:@blah3), "Hook3 should NOT work on blah"
338
+ end
339
+
340
+ def test_hook_response
341
+ Autotest.clear_hooks
342
+ deny @a.hook(:blah)
343
+
344
+ Autotest.add_hook(:blah) { false }
345
+ deny @a.hook(:blah)
346
+
347
+ Autotest.add_hook(:blah) { false }
348
+ deny @a.hook(:blah)
349
+
350
+ Autotest.add_hook(:blah) { true }
351
+ assert @a.hook(:blah)
352
+ end
353
+
354
+ def test_make_test_cmd
355
+ f = {
356
+ @test => [],
357
+ 'test/test_fooby.rb' => [ 'test_something1', 'test_something2' ]
358
+ }
359
+
360
+ expected = [ "#{RUBY} -I.:lib:test -rtest/unit -e \"%w[#{@test}].each { |f| require f }\" | unit_diff -u",
361
+ "#{RUBY} -I.:lib:test test/test_fooby.rb -n \"/^(test_something1|test_something2)$/\" | unit_diff -u" ].join("; ")
362
+
363
+ result = @a.make_test_cmd f
364
+ assert_equal expected, result
365
+ end
366
+
367
+ def test_path_to_classname
368
+ # non-rails
369
+ util_path_to_classname 'TestBlah', 'test/test_blah.rb'
370
+ util_path_to_classname 'TestOuter::TestInner', 'test/outer/test_inner.rb'
371
+ util_path_to_classname 'TestRuby2Ruby', 'test/test_ruby2ruby.rb'
372
+ end
373
+
374
+ def test_remove_exception
375
+ test_add_exception
376
+ current = util_exceptions
377
+ @a.remove_exception 'blah'
378
+
379
+ actual = util_exceptions
380
+ expect = current - ["blah"]
381
+
382
+ assert_equal expect, actual
383
+ end
384
+
385
+ def test_remove_mapping
386
+ current = util_mappings
387
+ @a.remove_mapping(/^lib\/.*\.rb$/)
388
+
389
+ actual = util_mappings
390
+ expect = current - [/^lib\/.*\.rb$/]
391
+
392
+ assert_equal expect, actual
393
+ end
394
+
395
+ def test_test_files_for
396
+ assert_equal [@test], @a.test_files_for(@impl)
397
+ assert_equal [@test], @a.test_files_for(@test)
398
+
399
+ assert_equal [], @a.test_files_for('test/test_unknown.rb')
400
+ assert_equal [], @a.test_files_for('lib/unknown.rb')
401
+ assert_equal [], @a.test_files_for('unknown.rb')
402
+ assert_equal [], @a.test_files_for('test_unknown.rb')
403
+ end
404
+
405
+ def util_exceptions
406
+ @a.exception_list.sort_by { |r| r.to_s }
407
+ end
408
+
409
+ def util_find_files_to_test(f, expected)
410
+ t = @a.last_mtime
411
+ files = { f => t + 1 }
412
+
413
+ assert @a.find_files_to_test(files)
414
+ assert_equal expected, @a.files_to_test
415
+ assert_equal t, @a.last_mtime
416
+ assert_equal "", @a.output.string
417
+ end
418
+
419
+ def util_mappings
420
+ @a.test_mappings.map { |k,v| k }.sort_by { |x| x.to_s }
421
+ end
422
+
423
+ def util_path_to_classname(e,i)
424
+ assert_equal e, @a.path_to_classname(i)
425
+ end
426
+
427
+ def util_reset_hooks_returning val
428
+ Autotest.clear_hooks
429
+
430
+ @a.instance_variable_set :@blah1, false
431
+ @a.instance_variable_set :@blah2, false
432
+ @a.instance_variable_set :@blah3, false
433
+
434
+ Autotest.add_hook(:blah) do |at|
435
+ at.instance_variable_set :@blah1, true
436
+ val
437
+ end
438
+
439
+ Autotest.add_hook(:blah) do |at|
440
+ at.instance_variable_set :@blah2, true
441
+ val
442
+ end
443
+
444
+ Autotest.add_hook(:blah) do |at|
445
+ at.instance_variable_set :@blah3, true
446
+ val
447
+ end
448
+ end
449
+ end