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,51 @@
1
+ # special thanks to: Patrick Hurley <phurley@gmail.com>
2
+ # requires the ruby-snarl gem.
3
+
4
+ begin require 'rubygems'; rescue LoadError; end
5
+ require 'snarl'
6
+
7
+ module Autotest::Snarl
8
+ def self.icon
9
+ # icons from http://www.famfamfam.com/lab/icons/silk/
10
+ path = File.join(File.dirname(__FILE__), "/../icons")
11
+ {
12
+ :green => "#{path}/accept.png",
13
+ :red => "#{path}/exclamation.png",
14
+ :info => "#{path}/information.png"
15
+ }
16
+ end
17
+
18
+ def self.snarl title, msg, ico = nil
19
+ Snarl.show_message(title, msg, icon[ico])
20
+ end
21
+
22
+ Autotest.add_hook :run do |at|
23
+ snarl "Run", "Run" unless $TESTING
24
+ end
25
+
26
+ Autotest.add_hook :red do |at|
27
+ failed_tests = at.files_to_test.inject(0){ |s,a| k,v = a; s + v.size}
28
+ snarl "Tests Failed", "#{failed_tests} tests failed", :red
29
+ end
30
+
31
+ Autotest.add_hook :green do |at|
32
+ snarl "Tests Passed", "All tests passed", :green #if at.tainted
33
+ end
34
+
35
+ Autotest.add_hook :run do |at|
36
+ snarl "autotest", "autotest was started", :info unless $TESTING
37
+ end
38
+
39
+ Autotest.add_hook :interrupt do |at|
40
+ snarl "autotest", "autotest was reset", :info unless $TESTING
41
+ end
42
+
43
+ Autotest.add_hook :quit do |at|
44
+ snarl "autotest", "autotest is exiting", :info unless $TESTING
45
+ end
46
+
47
+ Autotest.add_hook :all do |at|_hook
48
+ snarl "autotest", "Tests have fully passed", :green unless $TESTING
49
+ end
50
+
51
+ end
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Timestamp
4
+ Autotest.add_hook :waiting do
5
+ puts
6
+ puts "# Waiting since #{Time.now.strftime "%Y-%m-%d %H:%M:%S"}"
7
+ puts
8
+ end
9
+ end
@@ -0,0 +1,92 @@
1
+
2
+ ########################################################################
3
+ # The Idea:
4
+ #
5
+ # This is supposed to get us thinking about the various dimensions our
6
+ # testing should address. If there are states orthogonal to each other
7
+ # (eg. readable vs unreadable, logged in vs not logged in) each of
8
+ # those states should comprise a dimension in the matrix. By
9
+ # addressing it this way, we should be able to minimize the amount of
10
+ # setup/teardown code and get full coverage across our actions for all
11
+ # these edge cases and as a result have extremely clear tests.
12
+ #
13
+ ########################################################################
14
+ # Example Test Matrix Specification:
15
+ #
16
+ # matrix :example, :edge1, :edge2, :edge3, ...
17
+ # action :action1, :OK, :e_NF, :mod, ...
18
+ # action :action2, :OK, :e_RO, :na, ...
19
+ # action ...
20
+ #
21
+ ########################################################################
22
+ # Matrix:
23
+ #
24
+ # I envision the setups being a code that combines the different
25
+ # dimensions of edge case state.
26
+ #
27
+ # Something for a CMS might look like: `[df]_[ugo]_[rRwW]` where:
28
+ #
29
+ # + `[df]` for dir/file.
30
+ # + and the rest is in the style of symbolic args to chmod:
31
+ # + u/g/o = user, group, or other
32
+ # + lowercase `X` == `X`able, uppercase `X` == un`X`able, where `X`
33
+ # is read/write.
34
+ #
35
+ ########################################################################
36
+ # Action:
37
+ #
38
+ # :new/:err/:del are just examples, they should have semantic info
39
+ # attached to them.
40
+ #
41
+ # Use :na to specify an inapplicable edge case for that action.
42
+ #
43
+ # Use :OK to specify the standard positive state. It is equivalent to
44
+ # a result with the same name as the action. (eg
45
+ # matrix_test_index). This cleans up the matrix a lot and allows for
46
+ # narrower and more readable columns.
47
+ #
48
+ # Edge cases specific to an action that fall outside the matrix are
49
+ # regular tests.
50
+ #
51
+ ########################################################################
52
+ # Matrix Methods (the legos):
53
+ #
54
+ # Everything else basically equates to lego pieces:
55
+ #
56
+ # + There is one "init" method per matrix: matrix_init_#{descr}(setup_args)
57
+ # + There is one "setup" method per action: matrix_setup_#{action}(setup, expect)
58
+ # + There is one "test" method per result: matrix_test_#{result}(setup)
59
+ #
60
+ # Thus, for the matrix "example" above, the top left-most test will
61
+ # end up calling:
62
+ #
63
+ # matrix_init_example(:edge1)
64
+ # matrix_setup_action1(:edge1, :new)
65
+ # matrix_test_new(:edge1)
66
+ #
67
+ # Read the action method for exact details.
68
+ ########################################################################
69
+
70
+ module FunctionalTestMatrix
71
+ def matrix(name, *setups)
72
+ @@matrix, @@setups = name, setups
73
+ end
74
+
75
+ def action(action, *results)
76
+ testcases = @@setups.zip(results).reject { |a,b| b == :na }
77
+ testcases = Hash[*testcases.flatten]
78
+ matrix = @@matrix # bind to local scope for define_method closure
79
+
80
+ testcases.each do |setup, expected|
81
+ expected_action = expected == :OK ? action : expected
82
+ define_method "test_#{matrix}_#{action}_#{setup}" do
83
+ @action = action
84
+ send "matrix_init_#{matrix}", *setup.to_s.split(/_/).map {|c| c.intern }
85
+ send "matrix_setup_#{action}", setup, expected
86
+ send "matrix_test_#{expected_action}", setup
87
+ end
88
+ end
89
+ end
90
+
91
+ module_function :matrix, :action
92
+ end
data/lib/multiruby.rb ADDED
@@ -0,0 +1,401 @@
1
+ require 'fileutils'
2
+ require 'open-uri'
3
+
4
+ ##
5
+ # multiruby_setup is a script to help you manage multiruby.
6
+ #
7
+ # usage: multiruby_setup [-h|cmd|spec...]
8
+ #
9
+ # cmds:
10
+ #
11
+ # h, help - show this help.
12
+ # list - print installed versions.
13
+ # update - update svn builds.
14
+ # update:rubygems - update rubygems and nuke install dirs.
15
+ # rubygems:merge - symlink all rubygem dirs to one dir.
16
+ # rm:$version - remove a particular version.
17
+ # clean - clean scm build dirs and remove non-scm build dirs.
18
+ #
19
+ # specs:
20
+ #
21
+ # mri:svn:current - alias for mri:svn:releases and mri:svn:branches.
22
+ # mri:svn:releases - alias for supported releases of mri ruby.
23
+ # mri:svn:branches - alias for active branches of mri ruby.
24
+ # mri:svn:branch:$branch - install a specific $branch of mri from svn.
25
+ # mri:svn:tag:$tag - install a specific $tag of mri from svn.
26
+ # mri:tar:$version - install a specific $version of mri from tarball.
27
+ # rbx:ln:$dir - symlink your rbx $dir
28
+ # rbx:git:current - install rbx from git
29
+ #
30
+ # NOTES:
31
+ #
32
+ # * you can add a symlink to your rubinius build into ~/.multiruby/install
33
+ # * I'll get to adding support for other implementations soon.
34
+ #
35
+ module Multiruby
36
+ MRI_SVN = "http://svn.ruby-lang.org/repos/ruby"
37
+ RBX_GIT = "git://git.rubini.us"
38
+
39
+ TAGS = %w( 1_8_6 1_8_7 1_9 )
40
+ BRANCHES = %w(1_8 1_8_6 1_8_7 trunk)
41
+
42
+ HELP = []
43
+
44
+ File.readlines(__FILE__).each do |line|
45
+ next unless line =~ /^#( |$)/
46
+ HELP << line.sub(/^# ?/, '')
47
+ end
48
+
49
+ def self.build_and_install
50
+ root_dir = self.root_dir
51
+ versions = []
52
+
53
+ Dir.chdir root_dir do
54
+ self.setup_dirs
55
+
56
+ rubygems = Dir["versions/rubygems*.tgz"]
57
+ abort "You should delete all but one rubygem tarball" if rubygems.size > 1
58
+ rubygem_tarball = File.expand_path rubygems.last rescue nil
59
+
60
+ Dir.chdir "build" do
61
+ Dir["../versions/*"].each do |tarball|
62
+ next if tarball =~ /rubygems/
63
+
64
+ build_dir = File.basename tarball, ".tar.gz"
65
+ version = build_dir.sub(/^ruby-?/, '')
66
+ versions << version
67
+ inst_dir = "#{root_dir}/install/#{version}"
68
+
69
+ unless test ?d, inst_dir then
70
+ unless test ?d, build_dir then
71
+ if test ?d, tarball then
72
+ dir = File.basename tarball
73
+ FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
74
+ else
75
+ puts "creating #{inst_dir}"
76
+ Dir.mkdir inst_dir
77
+ run "tar zxf #{tarball}"
78
+ end
79
+ end
80
+ Dir.chdir build_dir do
81
+ puts "building and installing #{version}"
82
+ if test ?f, "configure.in" then
83
+ gnu_utils_build inst_dir
84
+ elsif test ?f, "Rakefile" then
85
+ rake_build inst_dir
86
+ else
87
+ raise "dunno how to build"
88
+ end
89
+
90
+ if rubygem_tarball and version !~ /1[._-]9|mri_trunk|rubinius/ then
91
+ rubygems = File.basename rubygem_tarball, ".tgz"
92
+ run "tar zxf #{rubygem_tarball}" unless test ?d, rubygems
93
+
94
+ Dir.chdir rubygems do
95
+ run "../ruby ./setup.rb --no-rdoc --no-ri &> ../log.rubygems"
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ versions
105
+ end
106
+
107
+ def self.clean
108
+ self.each_scm_build_dir do |style|
109
+ case style
110
+ when :svn, :git then
111
+ if File.exist? "Rakefile" then
112
+ run "rake clean"
113
+ elsif File.exist? "Makefile" then
114
+ run "make clean"
115
+ end
116
+ else
117
+ FileUtils.rm_rf Dir.pwd
118
+ end
119
+ end
120
+ end
121
+
122
+ def self.each_scm_build_dir
123
+ Multiruby.in_build_dir do
124
+ Dir["*"].each do |dir|
125
+ next unless File.directory? dir
126
+ Dir.chdir dir do
127
+ if File.exist?(".svn") || File.exist?(".git") then
128
+ scm = File.exist?(".svn") ? :svn : :git
129
+ yield scm
130
+ else
131
+ yield :none
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ def self.extract_latest_version url, matching=nil
139
+ file = URI.parse(url).read
140
+ versions = file.scan(/href="(ruby.*tar.gz)"/).flatten.reject { |s|
141
+ s =~ /preview/
142
+ }.sort_by { |s|
143
+ s.split(/\D+/).map { |i| i.to_i }
144
+ }.flatten
145
+ versions = versions.grep(/#{Regexp.escape(matching)}/) if matching
146
+ versions.last
147
+ end
148
+
149
+ def self.fetch_tar v
150
+ require 'open-uri'
151
+ base_url = "http://ftp.ruby-lang.org/pub/ruby"
152
+
153
+ in_versions_dir do
154
+ warn " Determining latest version for #{v}"
155
+ ver = v[/\d+\.\d+/]
156
+ base = extract_latest_version("#{base_url}/#{ver}/", v)
157
+ abort "Could not determine release for #{v}" unless base
158
+ url = File.join base_url, ver, base
159
+ warn " Fetching #{base} via HTTP... this might take a while."
160
+ open(url) do |f|
161
+ File.open base, 'w' do |out|
162
+ out.write f.read
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ def self.git_clone url, dir
169
+ Multiruby.in_versions_dir do
170
+ Multiruby.run "git clone #{url} #{dir}" unless File.directory? dir
171
+ FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
172
+ end
173
+ end
174
+
175
+ def self.gnu_utils_build inst_dir
176
+ run "autoconf" unless test ?f, "configure"
177
+ run "./configure --prefix #{inst_dir} &> log.configure" unless test ?f, "Makefile"
178
+ run "nice make -j4 &> log.build"
179
+ run "make install &> log.install"
180
+ end
181
+
182
+ def self.rake_build inst_dir
183
+ run "rake &> log.build"
184
+ FileUtils.ln_sf "../build/#{File.basename Dir.pwd}", inst_dir
185
+ end
186
+
187
+ def self.help
188
+ puts HELP.join
189
+ end
190
+
191
+ def self.in_build_dir
192
+ Dir.chdir File.join(self.root_dir, "build") do
193
+ yield
194
+ end
195
+ end
196
+
197
+ def self.in_install_dir
198
+ Dir.chdir File.join(self.root_dir, "install") do
199
+ yield
200
+ end
201
+ end
202
+
203
+ def self.in_root_dir
204
+ Dir.chdir self.root_dir do
205
+ yield
206
+ end
207
+ end
208
+
209
+ def self.in_tmp_dir
210
+ Dir.chdir File.join(self.root_dir, "tmp") do
211
+ yield
212
+ end
213
+ end
214
+
215
+ def self.in_versions_dir
216
+ Dir.chdir File.join(self.root_dir, "versions") do
217
+ yield
218
+ end
219
+ end
220
+
221
+ def self.list
222
+ puts "Known versions:"
223
+ in_install_dir do
224
+ Dir["*"].sort.each do |d|
225
+ puts " #{d}"
226
+ end
227
+ end
228
+ end
229
+
230
+ def self.merge_rubygems
231
+ in_install_dir do
232
+ gems = Dir["*/lib/ruby/gems"]
233
+
234
+ unless test ?d, "../gems" then
235
+ FileUtils.mv gems.first, ".."
236
+ end
237
+
238
+ gems.each do |d|
239
+ FileUtils.rm_rf d
240
+ FileUtils.ln_sf "../../../../gems", d
241
+ end
242
+ end
243
+ end
244
+
245
+ def self.mri_latest_tag v
246
+ Multiruby.tags.grep(/#{v}/).last
247
+ end
248
+
249
+ def self.rbx_ln dir
250
+ dir = File.expand_path dir
251
+ Multiruby.in_versions_dir do
252
+ FileUtils.ln_sf dir, "rubinius"
253
+ FileUtils.ln_sf "../versions/rubinius", "../install/rubinius"
254
+ end
255
+ end
256
+
257
+ def self.rm name
258
+ Multiruby.in_root_dir do
259
+ FileUtils.rm_rf Dir["*/#{name}"]
260
+ f = "versions/ruby-#{name}.tar.gz"
261
+ File.unlink f if test ?f, f
262
+ end
263
+ end
264
+
265
+ def self.root_dir
266
+ root_dir = File.expand_path(ENV['MULTIRUBY'] ||
267
+ File.join(ENV['HOME'], ".multiruby"))
268
+
269
+ unless test ?d, root_dir then
270
+ puts "creating #{root_dir}"
271
+ Dir.mkdir root_dir, 0700
272
+ end
273
+
274
+ root_dir
275
+ end
276
+
277
+ def self.run(cmd)
278
+ puts "Running command: #{cmd}"
279
+ raise "ERROR: Command failed with exit code #{$?}" unless system cmd
280
+ end
281
+
282
+ def self.setup_dirs(download = true)
283
+ %w(build install versions tmp).each do |dir|
284
+ unless test ?d, dir then
285
+ puts "creating #{dir}"
286
+ Dir.mkdir dir
287
+ if dir == "versions" && download then
288
+ warn " Downloading initial ruby tarballs to ~/.multiruby/versions:"
289
+ %w(1.8 1.9).each do |v|
290
+ self.fetch_tar v
291
+ end
292
+ warn " ...done"
293
+ warn " Put other ruby tarballs in ~/.multiruby/versions to use them."
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ def self.svn_co url, dir
300
+ Multiruby.in_versions_dir do
301
+ Multiruby.run "svn co #{url} #{dir}" unless File.directory? dir
302
+ FileUtils.ln_sf "../versions/#{dir}", "../build/#{dir}"
303
+ end
304
+ end
305
+
306
+ def self.tags
307
+ tags = nil
308
+ Multiruby.in_tmp_dir do
309
+ cache = "svn.tag.cache"
310
+ File.unlink cache if Time.now - File.mtime(cache) > 3600 rescue nil
311
+
312
+ File.open cache, "w" do |f|
313
+ f.write `svn ls #{MRI_SVN}/tags/`
314
+ end unless File.exist? cache
315
+
316
+ tags = File.read(cache).split(/\n/).grep(/^v/).reject {|s| s =~ /preview/}
317
+ end
318
+
319
+ tags = tags.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }
320
+ end
321
+
322
+ def self.update
323
+ # TODO:
324
+ # update will look at the dir name and act accordingly rel_.* will
325
+ # figure out latest tag on that name and svn sw to it trunk and
326
+ # others will just svn update
327
+
328
+ clean = []
329
+
330
+ self.each_scm_build_dir do |style|
331
+ dir = File.basename(Dir.pwd)
332
+ warn dir
333
+
334
+ case style
335
+ when :svn then
336
+ case dir
337
+ when /mri_\d/ then
338
+ system "svn cleanup" # just in case
339
+ svn_up = `svn up`
340
+ in_build_dir do
341
+ if svn_up =~ /^[ADUCG] / then
342
+ clean << dir
343
+ else
344
+ warn " no update"
345
+ end
346
+ FileUtils.ln_sf "../build/#{dir}", "../versions/#{dir}"
347
+ end
348
+ when /mri_rel_(.+)/ then
349
+ ver = $1
350
+ url = `svn info`[/^URL: (.*)/, 1]
351
+ latest = self.mri_latest_tag(ver).chomp('/')
352
+ new_url = File.join(File.dirname(url), latest)
353
+ if new_url != url then
354
+ run "svn sw #{new_url}"
355
+ clean << dir
356
+ else
357
+ warn " no update"
358
+ end
359
+ else
360
+ warn " update in this svn dir not supported yet: #{dir}"
361
+ end
362
+ when :git then
363
+ case dir
364
+ when /rubinius/ then
365
+ run "rake git:update build" # minor cheat by building here
366
+ else
367
+ warn " update in this git dir not supported yet: #{dir}"
368
+ end
369
+ else
370
+ warn " update in non-svn dir not supported yet: #{dir}"
371
+ end
372
+ end
373
+
374
+ in_install_dir do
375
+ clean.each do |dir|
376
+ warn "removing install/#{dir}"
377
+ FileUtils.rm_rf dir
378
+ end
379
+ end
380
+ end
381
+
382
+ def self.update_rubygems
383
+ url = "http://files.rubyforge.rubyuser.de/rubygems/"
384
+ html = URI.parse(url).read
385
+
386
+ versions = html.scan(/href="rubygems-update-(\d+(?:\.\d+)+).gem/).flatten
387
+ latest = versions.sort_by { |s| s.scan(/\d+/).map { |s| s.to_i } }.last
388
+
389
+ Multiruby.in_versions_dir do
390
+ File.unlink(*Dir["rubygems*"])
391
+ file = "rubygems-#{latest}.tgz"
392
+ File.open file, 'w' do |f|
393
+ f.write URI.parse(url+file).read
394
+ end
395
+ end
396
+
397
+ Multiruby.in_install_dir do
398
+ FileUtils.rm_rf Dir["*"]
399
+ end
400
+ end
401
+ end