minitest-autotest 1.0.0.b.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6cddf1c52ee49b0c38525d052f9977d59e065700
4
+ data.tar.gz: e52a6ea329d68a421ae95c5ee7546b7c18628954
5
+ SHA512:
6
+ metadata.gz: b043108613648407ce21f435154e969787c3a7e54b81cb9c7fabc450a29835e8e0d2834b92942946204d682ec00f8147a25ad1b936278298c6bdef23d490430d
7
+ data.tar.gz: bcc85ee67027fa913a3440e7328593c5115ae478d73517510f823062476c8296218b1baa0287f93a297c40ec46ce9dcace7c0fc648d85c2172970afd9072f196
Binary file
@@ -0,0 +1,2 @@
1
+ FM��ۊIk��D����>��qz����u% �3��R��A���^
2
+ ���o��G��Q���r]�εK��\t���^��wvדg�p�[�[SּJ���m�[�s��|�<�pR�э#��J��G�����
@@ -0,0 +1,26 @@
1
+ # -*- ruby -*-
2
+
3
+ require "autotest/restart"
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.testlib = "minitest/autorun"
7
+ at.add_exception "tmp"
8
+
9
+ # at.extra_files << "../some/external/dependency.rb"
10
+ #
11
+ # at.libs << ":../some/external"
12
+ #
13
+ # at.add_exception "vendor"
14
+ #
15
+ # at.add_mapping(/dependency.rb/) do |f, _|
16
+ # at.files_matching(/test_.*rb$/)
17
+ # end
18
+ #
19
+ # %w(TestA TestB).each do |klass|
20
+ # at.extra_class_map[klass] = "test/test_misc.rb"
21
+ # end
22
+ end
23
+
24
+ # Autotest.add_hook :run_command do |at|
25
+ # system "rake build"
26
+ # end
File without changes
@@ -0,0 +1,6 @@
1
+ === 1.0.0.b.1 / 2014-09-16
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,21 @@
1
+ .autotest
2
+ History.rdoc
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/autotest
7
+ lib/autotest.rb
8
+ lib/autotest/autoupdate.rb
9
+ lib/autotest/bundler.rb
10
+ lib/autotest/fixtures.rb
11
+ lib/autotest/isolate.rb
12
+ lib/autotest/migrate.rb
13
+ lib/autotest/once.rb
14
+ lib/autotest/preload.rb
15
+ lib/autotest/rails.rb
16
+ lib/autotest/rcov.rb
17
+ lib/autotest/restart.rb
18
+ lib/autotest/timestamp.rb
19
+ lib/minitest/autotest.rb
20
+ test/test_minitest/test_autorun.rb
21
+ test/test_minitest/test_good.rb
@@ -0,0 +1,49 @@
1
+ = minitest-autotest
2
+
3
+ home :: https://github.com/seattlerb/minitest-autotest
4
+ rdoc :: http://docs.seattlerb.org/minitest-autotest
5
+
6
+ == DESCRIPTION:
7
+
8
+ FIX (describe your package)
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ * FIX (list of features or problems)
13
+
14
+ == SYNOPSIS:
15
+
16
+ FIX (code sample of usage)
17
+
18
+ == REQUIREMENTS:
19
+
20
+ * FIX (list of requirements)
21
+
22
+ == INSTALL:
23
+
24
+ * sudo gem install minitest-autotest
25
+
26
+ == LICENSE:
27
+
28
+ (The MIT License)
29
+
30
+ Copyright (c) Ryan Davis, seattle.rb
31
+
32
+ Permission is hereby granted, free of charge, to any person obtaining
33
+ a copy of this software and associated documentation files (the
34
+ 'Software'), to deal in the Software without restriction, including
35
+ without limitation the rights to use, copy, modify, merge, publish,
36
+ distribute, sublicense, and/or sell copies of the Software, and to
37
+ permit persons to whom the Software is furnished to do so, subject to
38
+ the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be
41
+ included in all copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
44
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
46
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
47
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
48
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
49
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require "rubygems"
4
+ require "hoe"
5
+
6
+ # Hoe.plugin :isolate
7
+ Hoe.plugin :seattlerb
8
+ Hoe.plugin :rdoc
9
+
10
+ Hoe.spec "minitest-autotest" do
11
+ developer "Ryan Davis", "ryand-ruby@zenspider.com"
12
+ license "MIT"
13
+
14
+ dependency "minitest-server", "~> 1.0"
15
+ end
16
+
17
+ # vim: syntax=ruby
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby -w
2
+
3
+ require 'autotest'
4
+
5
+ Autotest.parse_options
6
+ Autotest.run
@@ -0,0 +1,728 @@
1
+ require "find"
2
+ require "rbconfig"
3
+
4
+ ##
5
+ # Autotest continuously scans the files in your project for changes
6
+ # and runs the appropriate tests. Test failures are run until they
7
+ # have all passed. Then the full test suite is run to ensure that
8
+ # nothing else was inadvertantly broken.
9
+ #
10
+ # If you want Autotest to start over from the top, hit ^C once. If
11
+ # you want Autotest to quit, hit ^C twice.
12
+ #
13
+ # Rails:
14
+ #
15
+ # The autotest command will automatically discover a Rails directory
16
+ # by looking for config/environment.rb. When Rails is discovered,
17
+ # autotest uses RailsAutotest to perform file mappings and other work.
18
+ # See RailsAutotest for details.
19
+ #
20
+ # Plugins:
21
+ #
22
+ # Plugins are available by creating a .autotest file either in your
23
+ # project root or in your home directory. You can then write event
24
+ # handlers in the form of:
25
+ #
26
+ # Autotest.add_hook hook_name { |autotest| ... }
27
+ #
28
+ # The available hooks are listed in +ALL_HOOKS+.
29
+ #
30
+ # See example_dot_autotest.rb for more details.
31
+ #
32
+ # If a hook returns a true value, it signals to autotest that the hook
33
+ # was handled and should not continue executing hooks.
34
+ #
35
+ # Naming:
36
+ #
37
+ # Autotest uses a simple naming scheme to figure out how to map
38
+ # implementation files to test files following the Test::Unit naming
39
+ # scheme.
40
+ #
41
+ # * Test files must be stored in test/
42
+ # * Test files names must start with test_
43
+ # * Test class names must start with Test
44
+ # * Implementation files must be stored in lib/
45
+ # * Implementation files must match up with a test file named
46
+ # test_.*<impl-name>.rb
47
+ #
48
+ # Strategy:
49
+ #
50
+ # 1. Find all files and associate them from impl <-> test.
51
+ # 2. Run all tests.
52
+ # 3. Scan for failures.
53
+ # 4. Detect changes in ANY (ruby?. file, rerun all failures + changed files.
54
+ # 5. Until 0 defects, goto 3.
55
+ # 6. When 0 defects, goto 2.
56
+
57
+ class Autotest
58
+
59
+ TOPDIR = Dir.pwd + "/"
60
+
61
+ T0 = Time.at 0
62
+
63
+ ALL_HOOKS = [ :all_good, :died, :green, :initialize,
64
+ :post_initialize, :interrupt, :quit, :ran_command,
65
+ :red, :reset, :run_command, :updated, :waiting ]
66
+
67
+ def self.options
68
+ @@options ||= {}
69
+ end
70
+
71
+ def options
72
+ self.class.options
73
+ end
74
+
75
+ HOOKS = Hash.new { |h,k| h[k] = [] }
76
+
77
+ WINDOZE = /mswin|mingw/ =~ RbConfig::CONFIG['host_os']
78
+ SEP = WINDOZE ? '&' : ';'
79
+
80
+ def self.parse_options args = ARGV
81
+ require 'optparse'
82
+ options = {
83
+ :args => args.dup
84
+ }
85
+
86
+ OptionParser.new do |opts|
87
+ opts.banner = <<-BANNER.gsub(/^ /, '')
88
+ Continuous testing for your ruby app.
89
+
90
+ Autotest automatically tests code that has changed. It assumes
91
+ the code is in lib, and tests are in test/test_*.rb. Autotest
92
+ uses plugins to control what happens. You configure plugins
93
+ with require statements in the .autotest file in your
94
+ project base directory, and a default configuration for all
95
+ your projects in the .autotest file in your home directory.
96
+
97
+ Usage:
98
+ autotest [options]
99
+ BANNER
100
+
101
+ opts.on "-d", "--debug", "Debug mode, for reporting bugs." do
102
+ require "pp"
103
+ options[:debug] = true
104
+ end
105
+
106
+ opts.on "-v", "--verbose", "Be annoyingly verbose (debugs .autotest)." do
107
+ options[:verbose] = true
108
+ end
109
+
110
+ opts.on "-q", "--quiet", "Be quiet." do
111
+ options[:quiet] = true
112
+ end
113
+
114
+ opts.on("-r", "--rc CONF", String, "Override path to config file") do |o|
115
+ options[:rc] = Array(o)
116
+ end
117
+
118
+ opts.on("-w", "--warnings", "Turn on ruby warnings") do
119
+ $-w = true
120
+ end
121
+
122
+ opts.on "-h", "--help", "Show this." do
123
+ puts opts
124
+ exit 1
125
+ end
126
+ end.parse! args
127
+
128
+ Autotest.options.merge! options
129
+
130
+ options
131
+ end
132
+
133
+ ##
134
+ # Initialize and run the system.
135
+
136
+ def self.run
137
+ new.run
138
+ end
139
+
140
+ attr_writer :known_files
141
+ attr_accessor :extra_class_map
142
+ attr_accessor :extra_files
143
+ attr_accessor :failures
144
+ attr_accessor :files_to_test # TODO: remove in favor of failures?
145
+ attr_accessor :find_directories
146
+ attr_accessor :find_order
147
+ attr_accessor :interrupted
148
+ attr_accessor :last_mtime
149
+ attr_accessor :libs
150
+ attr_accessor :output
151
+ attr_accessor :prefix
152
+ attr_accessor :sleep
153
+ attr_accessor :tainted
154
+ attr_accessor :test_mappings
155
+ attr_accessor :testlib
156
+ attr_accessor :test_prefix
157
+ attr_accessor :wants_to_quit
158
+
159
+ alias tainted? tainted
160
+
161
+ ##
162
+ # Initialize the instance and then load the user's .autotest file, if any.
163
+
164
+ def initialize
165
+ # these two are set directly because they're wrapped with
166
+ # add/remove/clear accessor methods
167
+ @exception_list = []
168
+ @child = nil
169
+
170
+ self.extra_class_map = {}
171
+ self.extra_files = []
172
+ self.failures = Hash.new { |h,k| h[k] = Hash.new { |h2,k2| h2[k2] = [] } }
173
+ self.files_to_test = new_hash_of_arrays
174
+ reset_find_order
175
+ self.libs = %w[. lib test].join(File::PATH_SEPARATOR)
176
+ self.output = $stderr
177
+ self.prefix = nil
178
+ self.sleep = 1
179
+ self.test_mappings = []
180
+ self.test_prefix = "gem 'minitest'"
181
+ self.testlib = "minitest/autorun" # TODO: rename
182
+
183
+ specified_directories = ARGV.reject { |arg| arg.start_with?("-") } # options are not directories
184
+ self.find_directories = specified_directories.empty? ? ['.'] : specified_directories
185
+
186
+ # file in /lib -> run test in /test
187
+ self.add_mapping(/^lib\/.*\.rb$/) do |filename, _|
188
+ possible = File.basename(filename).gsub '_', '_?'
189
+ files_matching %r%^test/.*#{possible}$%
190
+ end
191
+
192
+ # file in /test -> run it (ruby & rails styles)
193
+ self.add_mapping(/^test.*\/(test_.*|.*_test)\.rb$/) do |filename, _|
194
+ filename
195
+ end
196
+
197
+ default_configs = [File.expand_path('~/.autotest'), './.autotest']
198
+ configs = options[:rc] || default_configs
199
+
200
+ configs.each do |f|
201
+ load f if File.exist? f
202
+ end
203
+ end
204
+
205
+ def debug
206
+ find_files_to_test
207
+
208
+ puts "Known test files:"
209
+ puts
210
+ pp files_to_test.keys.sort
211
+
212
+ class_map = self.class_map
213
+
214
+ puts
215
+ puts "Known class map:"
216
+ puts
217
+ pp class_map
218
+ end
219
+
220
+ def class_map
221
+ class_map = Hash[*self.find_order.grep(/^test/).map { |f| # TODO: ugly
222
+ [path_to_classname(f), f]
223
+ }.flatten]
224
+ class_map.merge! self.extra_class_map
225
+ class_map
226
+ end
227
+
228
+ ##
229
+ # Repeatedly run failed tests, then all tests, then wait for changes
230
+ # and carry on until killed.
231
+
232
+ def run
233
+ hook :initialize
234
+ hook :post_initialize
235
+
236
+ require "minitest/server"
237
+ Minitest::Server.run self
238
+
239
+ reset
240
+ add_sigint_handler
241
+
242
+ self.last_mtime = Time.now if options[:no_full_after_start]
243
+
244
+ self.debug if options[:debug]
245
+
246
+ loop do
247
+ begin # ^c handler
248
+ get_to_green
249
+ if tainted? and not options[:no_full_after_failed] then
250
+ rerun_all_tests
251
+ else
252
+ hook :all_good
253
+ end
254
+ wait_for_changes
255
+ rescue Interrupt
256
+ break if wants_to_quit
257
+ reset
258
+ end
259
+ end
260
+ hook :quit
261
+ puts
262
+ rescue Exception => err
263
+ hook(:died, err) or raise err
264
+ ensure
265
+ Minitest::Server.stop
266
+ end
267
+
268
+ ##
269
+ # Keep running the tests after a change, until all pass.
270
+
271
+ def get_to_green
272
+ begin
273
+ run_tests
274
+ wait_for_changes unless all_good
275
+ end until all_good
276
+ end
277
+
278
+ ##
279
+ # Look for files to test then run the tests and handle the results.
280
+
281
+ def run_tests
282
+ new_mtime = self.find_files_to_test
283
+ return unless new_mtime
284
+ self.last_mtime = new_mtime
285
+
286
+ cmd = self.make_test_cmd self.files_to_test
287
+ return if cmd.empty?
288
+
289
+ hook :run_command, cmd
290
+
291
+ puts cmd unless options[:quiet]
292
+
293
+ system cmd
294
+
295
+ hook :ran_command
296
+ end
297
+
298
+ ############################################################
299
+ # Utility Methods, not essential to reading of logic
300
+
301
+ ##
302
+ # Installs a sigint handler.
303
+
304
+ def add_sigint_handler
305
+ trap 'INT' do
306
+ Process.kill "KILL", @child if @child
307
+
308
+ if self.interrupted then
309
+ self.wants_to_quit = true
310
+ else
311
+ unless hook :interrupt then
312
+ puts "Interrupt a second time to quit"
313
+ self.interrupted = true
314
+ Kernel.sleep 1.5
315
+ end
316
+ raise Interrupt, nil # let the run loop catch it
317
+ end
318
+ end
319
+ end
320
+
321
+ ##
322
+ # Installs a sigquit handler
323
+
324
+ def add_sigquit_handler
325
+ trap 'QUIT' do
326
+ restart
327
+ end
328
+ end
329
+
330
+ def restart
331
+ Process.kill "KILL", @child if @child
332
+
333
+ cmd = [$0, *options[:args]]
334
+
335
+ index = $LOAD_PATH.index RbConfig::CONFIG["sitelibdir"]
336
+
337
+ if index then
338
+ extra = $LOAD_PATH[0...index]
339
+ cmd = [Gem.ruby, "-I", extra.join(":")] + cmd
340
+ end
341
+
342
+ puts cmd.join(" ") if options[:verbose]
343
+
344
+ exec(*cmd)
345
+ end
346
+
347
+ ##
348
+ # If there are no files left to test (because they've all passed),
349
+ # then all is good.
350
+
351
+ def all_good
352
+ failures.empty?
353
+ end
354
+
355
+ ##
356
+ # Convert a path in a string, s, into a class name, changing
357
+ # underscores to CamelCase, etc.
358
+
359
+ def path_to_classname s
360
+ sep = File::SEPARATOR
361
+ f = s.sub(/^test#{sep}/, '').sub(/\.rb$/, '').split sep
362
+ f = f.map { |path| path.split(/_|(\d+)/).map { |seg| seg.capitalize }.join }
363
+ f = f.map { |path| path =~ /^Test/ ? path : "Test#{path}" }
364
+
365
+ f.join '::'
366
+ end
367
+
368
+ ##
369
+ # Find the files to process, ignoring temporary files, source
370
+ # configuration management files, etc., and return a Hash mapping
371
+ # filename to modification time.
372
+
373
+ def find_files
374
+ result = {}
375
+ targets = self.find_directories + self.extra_files
376
+ reset_find_order
377
+
378
+ targets.each do |target|
379
+ order = []
380
+ Find.find target do |f|
381
+ Find.prune if f =~ self.exceptions
382
+ Find.prune if f =~ /^\.\/tmp/ # temp dir, used by isolate
383
+
384
+ next unless File.file? f
385
+ next if f =~ /(swp|~|rej|orig)$/ # temporary/patch files
386
+ next if f =~ /(,v)$/ # RCS files
387
+ next if f =~ /\/\.?#/ # Emacs autosave/cvs merge files
388
+
389
+ filename = f.sub(/^\.\//, '')
390
+
391
+ result[filename] = File.stat(filename).mtime rescue next
392
+ order << filename
393
+ end
394
+ self.find_order.push(*order.sort)
395
+ end
396
+
397
+ result
398
+ end
399
+
400
+ ##
401
+ # Find the files which have been modified, update the recorded
402
+ # timestamps, and use this to update the files to test. Returns
403
+ # the latest mtime of the files modified or nil when nothing was
404
+ # modified.
405
+
406
+ def find_files_to_test files = find_files
407
+ updated = files.select { |filename, mtime| self.last_mtime < mtime }
408
+
409
+ # nothing to update or initially run
410
+ unless updated.empty? || self.last_mtime.to_i == 0 then
411
+ p updated if options[:verbose]
412
+
413
+ hook :updated, updated
414
+ end
415
+
416
+ updated.map { |f,m| test_files_for f }.flatten.uniq.each do |filename|
417
+ self.failures[filename] # creates key with default value
418
+ self.files_to_test[filename] # creates key with default value
419
+ end
420
+
421
+ if updated.empty? then
422
+ nil
423
+ else
424
+ files.values.max
425
+ end
426
+ end
427
+
428
+ ##
429
+ # Lazy accessor for the known_files hash.
430
+
431
+ def known_files
432
+ unless @known_files then
433
+ @known_files = Hash[*find_order.map { |f| [f, true] }.flatten]
434
+ end
435
+ @known_files
436
+ end
437
+
438
+ ##
439
+ # Generate the commands to test the supplied files
440
+
441
+ def make_test_cmd files_to_test
442
+ if options[:debug] then
443
+ puts "Files to test:"
444
+ puts
445
+ pp files_to_test
446
+ puts
447
+ end
448
+
449
+ cmds = []
450
+ full, partial = reorder(failures).partition { |k,v| v.empty? }
451
+
452
+ unless full.empty? then
453
+ classes = full.map {|k,v| k}.flatten.uniq
454
+ classes.unshift testlib
455
+ classes = classes.join " "
456
+ cmds << "#{ruby_cmd} -e \"#{test_prefix}; %w[#{classes}].each { |f| require f }\" -- --server #{$$}"
457
+ end
458
+
459
+ unless partial.empty? then
460
+ files = partial.map(&:first).sort # no longer a hash because of partition
461
+ re = []
462
+
463
+ partial.each do |path, klasses|
464
+ klasses.each do |klass,methods|
465
+ re << /#{klass}##{Regexp.union(methods)}/
466
+ end
467
+ end
468
+
469
+ loader = "%w[#{files.join " "}].each do |f| load f; end"
470
+ re = Regexp.union(re).to_s.gsub(/-mix/, "")
471
+
472
+ cmds << "#{ruby_cmd} -e '#{loader}' -- -a #{$$} -n '/#{re}/'"
473
+ end
474
+
475
+ cmds.join "#{SEP} "
476
+ end
477
+
478
+ def new_hash_of_arrays
479
+ Hash.new { |h,k| h[k] = [] }
480
+ end
481
+
482
+ def reorder files_to_test
483
+ max = files_to_test.size
484
+ files_to_test.sort_by { |k,v| rand max }
485
+ end
486
+
487
+ ##
488
+ # Rerun the tests from cold (reset state)
489
+
490
+ def rerun_all_tests
491
+ reset
492
+ run_tests
493
+
494
+ hook :all_good if all_good
495
+ end
496
+
497
+ ##
498
+ # Clear all state information about test failures and whether
499
+ # interrupts will kill autotest.
500
+
501
+ def reset
502
+ self.files_to_test.clear
503
+ reset_find_order
504
+ self.failures.clear
505
+
506
+ self.interrupted = false
507
+ self.last_mtime = T0
508
+ self.tainted = false
509
+ self.wants_to_quit = false
510
+
511
+ hook :reset
512
+ end
513
+
514
+ def reset_find_order
515
+ self.find_order = []
516
+ self.known_files = nil
517
+ end
518
+
519
+ ##
520
+ # Determine and return the path of the ruby executable.
521
+
522
+ def ruby
523
+ ruby = ENV['RUBY']
524
+ ruby ||= File.join(RbConfig::CONFIG['bindir'],
525
+ RbConfig::CONFIG['ruby_install_name'])
526
+
527
+ ruby.gsub! File::SEPARATOR, File::ALT_SEPARATOR if File::ALT_SEPARATOR
528
+
529
+ return ruby
530
+ end
531
+
532
+ ##
533
+ # Returns the base of the ruby command.
534
+
535
+ def ruby_cmd
536
+ "#{prefix}#{ruby} -I#{libs} -rubygems"
537
+ end
538
+
539
+ ##
540
+ # Return the name of the file with the tests for filename by finding
541
+ # a +test_mapping+ that matches the file and executing the mapping's
542
+ # proc.
543
+
544
+ def test_files_for filename
545
+ result = []
546
+
547
+ self.test_mappings.each do |file_re, proc|
548
+ if filename =~ file_re then
549
+ result = [proc.call(filename, $~)].
550
+ flatten.sort.uniq.select { |f| known_files[f] }
551
+ break unless result.empty?
552
+ end
553
+ end
554
+
555
+ p :test_file_for => [filename, result.first] if result and options[:debug]
556
+
557
+ output.puts "No tests matched #{filename}" if
558
+ options[:verbose] and result.empty?
559
+
560
+ return result
561
+ end
562
+
563
+ ##
564
+ # Sleep then look for files to test, until there are some.
565
+
566
+ def wait_for_changes
567
+ hook :waiting
568
+ Kernel.sleep self.sleep until find_files_to_test
569
+ end
570
+
571
+ ############################################################
572
+ # File Mappings:
573
+
574
+ ##
575
+ # Returns all known files in the codebase matching +regexp+.
576
+
577
+ def files_matching regexp
578
+ self.find_order.select { |k| k =~ regexp }
579
+ end
580
+
581
+ ##
582
+ # Adds a file mapping, optionally prepending the mapping to the
583
+ # front of the list if +prepend+ is true. +regexp+ should match a
584
+ # file path in the codebase. +proc+ is passed a matched filename and
585
+ # Regexp.last_match. +proc+ should return an array of tests to run.
586
+ #
587
+ # For example, if test_helper.rb is modified, rerun all tests:
588
+ #
589
+ # at.add_mapping(/test_helper.rb/) do |f, _|
590
+ # at.files_matching(/^test.*rb$/)
591
+ # end
592
+
593
+ def add_mapping regexp, prepend = false, &proc
594
+ if prepend then
595
+ @test_mappings.unshift [regexp, proc]
596
+ else
597
+ @test_mappings.push [regexp, proc]
598
+ end
599
+ nil
600
+ end
601
+
602
+ ##
603
+ # Removed a file mapping matching +regexp+.
604
+
605
+ def remove_mapping regexp
606
+ @test_mappings.delete_if do |k,v|
607
+ k == regexp
608
+ end
609
+ nil
610
+ end
611
+
612
+ ##
613
+ # Clears all file mappings. This is DANGEROUS as it entirely
614
+ # disables autotest. You must add at least one file mapping that
615
+ # does a good job of rerunning appropriate tests.
616
+
617
+ def clear_mappings
618
+ @test_mappings.clear
619
+ nil
620
+ end
621
+
622
+ ############################################################
623
+ # Exceptions:
624
+
625
+ ##
626
+ # Adds +regexp+ to the list of exceptions for find_file. This must
627
+ # be called _before_ the exceptions are compiled.
628
+
629
+ def add_exception regexp
630
+ raise "exceptions already compiled" if defined? @exceptions
631
+
632
+ @exception_list << regexp
633
+ nil
634
+ end
635
+
636
+ ##
637
+ # Removes +regexp+ to the list of exceptions for find_file. This
638
+ # must be called _before_ the exceptions are compiled.
639
+
640
+ def remove_exception regexp
641
+ raise "exceptions already compiled" if defined? @exceptions
642
+ @exception_list.delete regexp
643
+ nil
644
+ end
645
+
646
+ ##
647
+ # Clears the list of exceptions for find_file. This must be called
648
+ # _before_ the exceptions are compiled.
649
+
650
+ def clear_exceptions
651
+ raise "exceptions already compiled" if defined? @exceptions
652
+ @exception_list.clear
653
+ nil
654
+ end
655
+
656
+ ##
657
+ # Return a compiled regexp of exceptions for find_files or nil if no
658
+ # filtering should take place. This regexp is generated from
659
+ # +exception_list+.
660
+
661
+ def exceptions
662
+ unless defined? @exceptions then
663
+ @exceptions = if @exception_list.empty? then
664
+ nil
665
+ else
666
+ Regexp.union(*@exception_list)
667
+ end
668
+ end
669
+
670
+ @exceptions
671
+ end
672
+
673
+ ############################################################
674
+ # Hooks:
675
+
676
+ ##
677
+ # Call the event hook named +name+, passing in optional args
678
+ # depending on the hook itself.
679
+ #
680
+ # Returns false if no hook handled the event.
681
+ #
682
+ # === Hook Writers!
683
+ #
684
+ # This executes all registered hooks <em>until one returns truthy</em>.
685
+ # Pay attention to the return value of your block!
686
+
687
+ def hook name, *args
688
+ deprecated = {
689
+ # none currently
690
+ }
691
+
692
+ if deprecated[name] and not HOOKS[name].empty? then
693
+ warn "hook #{name} has been deprecated, use #{deprecated[name]}"
694
+ end
695
+
696
+ HOOKS[name].any? { |plugin| plugin[self, *args] }
697
+ end
698
+
699
+ ##
700
+ # Add the supplied block to the available hooks, with the given
701
+ # name.
702
+
703
+ def self.add_hook name, &block
704
+ HOOKS[name] << block
705
+ end
706
+
707
+ add_hook :died do |at, err|
708
+ warn "Unhandled exception: #{err}"
709
+ warn err.backtrace.join("\n ")
710
+ warn "Quitting"
711
+ end
712
+
713
+ ############################################################
714
+ # Server Methods:
715
+
716
+ def minitest_start
717
+ self.failures.clear
718
+ end
719
+
720
+ def minitest_result file, klass, method, fails, assertions, time
721
+ fails.reject! { |fail| Minitest::Skip === fail }
722
+
723
+ unless fails.empty?
724
+ self.tainted = true
725
+ self.failures[file][klass] << method
726
+ end
727
+ end
728
+ end
@@ -0,0 +1,26 @@
1
+ module Autotest::AutoUpdate
2
+ @@sleep_time, @@update_cmd, @@updater = 60, "svn up", nil
3
+
4
+ def self.sleep_time= o
5
+ @@sleep_time = o
6
+ end
7
+
8
+ def self.update_cmd= o
9
+ @@update_cmd = o
10
+ end
11
+
12
+ Autotest.add_hook :run_command do |at|
13
+ @@updater.kill if @@updater
14
+ end
15
+
16
+ Autotest.add_hook :ran_command do |at|
17
+ @@updater = Thread.start do
18
+ loop do
19
+ puts "# Waiting for #{@@sleep_time} seconds before updating"
20
+ sleep @@sleep_time
21
+ puts "# Running #{@@update_cmd}"
22
+ system @@update_cmd
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ ##
2
+ # Prefix all test runs with `bundle exec` so the runs use the bundled
3
+ # environment.
4
+
5
+ module Autotest::Bundler
6
+ Autotest.add_hook :initialize do |at|
7
+ at.prefix = "bundle exec "
8
+ false
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # -*- ruby -*-
2
+
3
+ # This is an example of how to change the mappings of file that
4
+ # changed to tests to run for a project.
5
+
6
+ module Autotest::Fixtures
7
+ Autotest.add_hook :initialize do |at|
8
+ at.test_mappings['^test/fixtures/(.*)s.yml'] = proc { |filename, matches|
9
+ at.files_matching(/test\/\w+\/#{matches[1]}(_\w+)?.*_test.rb$/)
10
+ }
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ ##
2
+ # Run autotest with isolate support.
3
+
4
+ module Autotest::Isolate
5
+ @@dir = "tmp/isolate/#{Gem.ruby_engine}-#{RbConfig::CONFIG['ruby_version']}"
6
+
7
+ def self.dir= o
8
+ @@dir = o
9
+ end
10
+
11
+ Autotest.add_hook :initialize do |at|
12
+ ENV["GEM_HOME"] = @@dir
13
+ ENV["GEM_PATH"] = @@dir
14
+ ENV["PATH"] += ":#{@@dir}/bin"
15
+
16
+ Gem.clear_paths
17
+ false
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Migrate
4
+ Autotest.add_hook(:run) do |autotest|
5
+ system "rake db:migrate" if autotest.class.to_s == "RailsAutotest"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ ##
2
+ # this is for autotest plugin developers only...
3
+
4
+ module Autotest::Once
5
+ Autotest.add_hook :ran_command do |at|
6
+ exit 0
7
+ end
8
+ end
9
+
@@ -0,0 +1,56 @@
1
+ module Autotest::Preload
2
+ def self.glob
3
+ @glob
4
+ end
5
+
6
+ def self.glob= o
7
+ @glob = o
8
+ end
9
+
10
+ self.glob = "test/test_helper.rb"
11
+
12
+ Autotest.add_hook :post_initialize do |at, *args|
13
+ at.add_sigquit_handler
14
+
15
+ warn "pre-loading initializers"
16
+ t0 = Time.now
17
+ Dir[self.glob].each do |path|
18
+ require path
19
+ end
20
+ warn "done pre-loading initializers in %.2f seconds" % [Time.now - t0]
21
+
22
+ false
23
+ end
24
+ end
25
+
26
+ class Autotest
27
+ alias :old_run_tests :run_tests
28
+
29
+ def run_tests
30
+ hook :run_command
31
+
32
+ new_mtime = self.find_files_to_test
33
+ return unless new_mtime
34
+ self.last_mtime = new_mtime
35
+
36
+ begin
37
+ # TODO: deal with unit_diff and partial test runs later
38
+ original_argv = ARGV.dup
39
+ ARGV.clear
40
+
41
+ @child = fork do
42
+ trap "QUIT", "DEFAULT"
43
+ trap "INT", "DEFAULT"
44
+ files_to_test.keys.each do |file|
45
+ load file
46
+ end
47
+ end
48
+ Process.wait
49
+ ensure
50
+ @child = nil
51
+ ARGV.replace original_argv
52
+ end
53
+
54
+ hook :ran_command
55
+ end
56
+ end
@@ -0,0 +1,67 @@
1
+ require 'autotest'
2
+
3
+ module Autotest::Rails
4
+ Autotest.add_hook :initialize do |at|
5
+ at.add_exception %r%^\./(?:db|doc|log|public|script|tmp|vendor|app/assets)%
6
+
7
+ at.clear_mappings
8
+
9
+ at.add_mapping %r%^lib/(.*)\.rb$% do |_, m|
10
+ at.files_matching %r%^test/(lib|unit/lib)/#{m[1]}.*_test.rb$%
11
+ # TODO: (unit|functional|integration) maybe?
12
+ end
13
+
14
+ at.add_mapping %r%^test/fixtures/(.*)s.yml% do |_, m|
15
+ at.files_matching %r%^test/(models|controllers|views|unit|functional)/#{m[1]}.*_test.rb$%
16
+ end
17
+
18
+ at.add_mapping %r%^test/.*_test\.rb$% do |filename, _|
19
+ filename
20
+ end
21
+
22
+ at.add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
23
+ at.files_matching %r%^test/(models|unit)/#{m[1]}.*_test.rb$%
24
+ end
25
+
26
+ at.add_mapping %r%^app/helpers/(.*)_helper.rb% do |_, m|
27
+ if m[1] == "application" then
28
+ at.files_matching %r%^test/(helpers|controllers|views|unit/helpers/functional)/.*_test\.rb$%
29
+ else
30
+ at.files_matching %r%^test/(helpers|controllers|views|unit/helpers/functional)/#{m[1]}.*_test.rb$%
31
+ end
32
+ end
33
+
34
+ at.add_mapping %r%^app/views/(.*)/% do |_, m|
35
+ at.files_matching %r%^test/(controllers|views|functional)/#{m[1]}.*_test.rb$%
36
+ end
37
+
38
+ at.add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
39
+ if m[1] == "application" then
40
+ at.files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
41
+ else
42
+ at.files_matching %r%^test/(controllers|views|functional)/#{m[1]}.*_test.rb$%
43
+ end
44
+ end
45
+
46
+ at.add_mapping %r%^app/views/layouts/% do
47
+ "test/views/layouts_view_test.rb"
48
+ end
49
+
50
+ at.add_mapping %r%^test/test_helper.rb|config/((boot|environment(s/test)?).rb|database.yml|routes.rb)% do
51
+ at.files_matching %r%^test/(models|controllers|views|unit|functional)/.*_test.rb$%
52
+ end
53
+ end
54
+ end
55
+
56
+ class Autotest
57
+ alias old_path_to_classname path_to_classname
58
+
59
+ # Convert the pathname s to the name of class.
60
+ def path_to_classname s
61
+ sep = File::SEPARATOR
62
+ f = s.sub(/^test#{sep}((\w+)#{sep})?/, '').sub(/\.rb$/, '').split sep
63
+ f = f.map { |path| path.split(/_|(\d+)/).map { |seg| seg.capitalize }.join }
64
+ f = f.map { |path| path =~ /Test$/ ? path : "#{path}Test" }
65
+ f.join '::'
66
+ end
67
+ end
@@ -0,0 +1,27 @@
1
+ module Autotest::RCov
2
+ @@command, @@options = "rcov", nil
3
+
4
+ def self.command= o
5
+ @@command = o
6
+ end
7
+
8
+ def self.pattern= o
9
+ warn "RCov.pattern= no longer has any functionality. please remove."
10
+ end
11
+
12
+ def self.options= o
13
+ @@options = o
14
+ end
15
+
16
+ Autotest.add_hook :all_good do |at|
17
+ options = @@options ? "RCOVOPTS=\"#{@@options}\"" : ""
18
+ system "rake #{@@command} #{options}"
19
+ false
20
+ end
21
+
22
+ Autotest.add_hook :initialize do |at|
23
+ at.add_exception 'coverage'
24
+ at.add_exception 'coverage.info'
25
+ false
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module Autotest::Restart
2
+ Autotest.add_hook :initialize do |at|
3
+ configs = [File.expand_path('~/.autotest'), './.autotest'].select { |f|
4
+ File.exist? f
5
+ }
6
+ at.extra_files.concat configs
7
+ false
8
+ end
9
+
10
+ Autotest.add_hook :updated do |at, found|
11
+ unless found.flatten.grep(/\.autotest$/).empty? then
12
+ warn "Detected change to .autotest, restarting"
13
+ at.restart
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Timestamp
4
+ Autotest.add_hook :ran_command do
5
+ puts
6
+ puts "# Finished at #{Time.now.strftime "%Y-%m-%d %H:%M:%S"}"
7
+ puts
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Minitest; end
2
+
3
+ class Minitest::Autotest
4
+ VERSION = "1.0.0.b.1"
5
+ end
@@ -0,0 +1,15 @@
1
+ require "minitest/autorun"
2
+
3
+ class FooTest < Minitest::Test
4
+ def test_passes
5
+ assert true
6
+ end
7
+
8
+ def test_fails
9
+ flunk
10
+ end
11
+
12
+ def test_error
13
+ raise
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # require "./at_plugin.rb"
2
+
3
+ require "minitest/autorun"
4
+
5
+ class GoodTest < Minitest::Test
6
+ def test_passes
7
+ assert true
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minitest-autotest
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.b.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Davis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDPjCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
14
+ ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
15
+ GRYDY29tMB4XDTE0MDkxNzIzMDcwN1oXDTE1MDkxNzIzMDcwN1owRTETMBEGA1UE
16
+ AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
17
+ JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
18
+ b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
19
+ taCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT
20
+ oOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh
21
+ GiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt
22
+ qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
23
+ gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
24
+ HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB
25
+ AQAFoDJRokCQdxFfOrmsKX41KOFlU/zjrbDVM9hgB/Ur999M6OXGSi8FitXNtMwY
26
+ FVjsiAPeU7HaWVVcZkj6IhINelTkXsxgGz/qCzjHy3iUMuZWw36cS0fiWJ5rvH+e
27
+ hD7uXxJSFuyf1riDGI1aeWbQ74WMwvNstOxLUMiV5a1fzBhlxPqb537ubDjq/M/h
28
+ zPUFPVYeL5KjDHLCqI2FwIk2sEMOQgjpXHzl+3NlD2LUgUhHDMevmgVua0e2GT1B
29
+ xJcC6UN6NHMOVMyAXsr2HR0gRRx4ofN1LoP2KhXzSr8UMvQYlwPmE0N5GQv1b5AO
30
+ VpzF30vNaJK6ZT7xlIsIlwmH
31
+ -----END CERTIFICATE-----
32
+ date: 2014-09-18 00:00:00.000000000 Z
33
+ dependencies:
34
+ - !ruby/object:Gem::Dependency
35
+ name: minitest-server
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: minitest
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '5.4'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '5.4'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rdoc
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: hoe
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.12'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '3.12'
90
+ description: FIX (describe your package)
91
+ email:
92
+ - ryand-ruby@zenspider.com
93
+ executables:
94
+ - autotest
95
+ extensions: []
96
+ extra_rdoc_files:
97
+ - History.rdoc
98
+ - Manifest.txt
99
+ - README.rdoc
100
+ files:
101
+ - .autotest
102
+ - .gemtest
103
+ - History.rdoc
104
+ - Manifest.txt
105
+ - README.rdoc
106
+ - Rakefile
107
+ - bin/autotest
108
+ - lib/autotest.rb
109
+ - lib/autotest/autoupdate.rb
110
+ - lib/autotest/bundler.rb
111
+ - lib/autotest/fixtures.rb
112
+ - lib/autotest/isolate.rb
113
+ - lib/autotest/migrate.rb
114
+ - lib/autotest/once.rb
115
+ - lib/autotest/preload.rb
116
+ - lib/autotest/rails.rb
117
+ - lib/autotest/rcov.rb
118
+ - lib/autotest/restart.rb
119
+ - lib/autotest/timestamp.rb
120
+ - lib/minitest/autotest.rb
121
+ - test/test_minitest/test_autorun.rb
122
+ - test/test_minitest/test_good.rb
123
+ homepage: https://github.com/seattlerb/minitest-autotest
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options:
129
+ - --main
130
+ - README.rdoc
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - '>'
141
+ - !ruby/object:Gem::Version
142
+ version: 1.3.1
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.4.1
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: FIX (describe your package)
149
+ test_files:
150
+ - test/test_minitest/test_autorun.rb
151
+ - test/test_minitest/test_good.rb
Binary file