ryanbriones-ZenTest 3.11.1

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