minitest-autotest 1.0.0.b.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.
@@ -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