test-loop 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.md +41 -2
  2. data/bin/test-loop +83 -39
  3. metadata +3 -4
  4. data/LICENSE +0 -15
data/README.md CHANGED
@@ -24,7 +24,7 @@ Features
24
24
  * Supports Test::Unit, RSpec, or any other testing framework that is utilized
25
25
  by your application's `test/test_helper.rb` and `spec/spec_helper.rb` files.
26
26
 
27
- * Implemented in less than 40 (SLOC) lines of code! :-)
27
+ * Implemented in less than 60 (SLOC) lines of code! :-)
28
28
 
29
29
 
30
30
  Installation
@@ -63,7 +63,46 @@ Operation
63
63
  * Press Control-C (or send the SIGINT signal) to quit the test loop.
64
64
 
65
65
 
66
+ Configuration
67
+ -------------
68
+
69
+ test-loop looks for a configuration file named `.test-loop` in the current
70
+ working directory. This configuration file is a normal Ruby script which can
71
+ define the following instance variables:
72
+
73
+ * `@overhead_file_globs` is an array of file globbing patterns that describe a
74
+ set of Ruby scripts that are loaded into the main Ruby process as overhead.
75
+
76
+ * `@reabsorb_file_globs` is an array of file globbing patterns that describe a
77
+ set of files which cause the overhead to be reabsorbed whenever they change.
78
+
79
+ * `@source_file_to_test_file_mapping` is a hash that maps a file globbing
80
+ pattern describing a set of source files to a [Rake pathmap expression](
81
+ http://rake.rubyforge.org/classes/String.html#M000017 ) yielding a file
82
+ globbing pattern describing a set of test files that need to be run. In
83
+ other words, whenever the source files (the hash key; left-hand side of the
84
+ mapping) change, their associated test files (the hash value; right-hand
85
+ side of the mapping) are run.
86
+
87
+ * `@after_test_execution` is a proc/lambda object that is executed after tests
88
+ are run. It is passed three things: the status of the test execution
89
+ subprocess, the time when the tests were run, and the list of test files
90
+ that were run.
91
+
92
+ For example, to get on-screen-display notifications through libnotify,
93
+ add the following to your `.test-loop` file:
94
+
95
+ @after_test_execution = lambda do |status, ran_at, files|
96
+ if status.success?
97
+ result, icon = 'PASS', 'apple-green'
98
+ else
99
+ result, icon = 'FAIL', 'apple-red'
100
+ end
101
+ system 'notify-send', '-i', icon, "#{result} at #{ran_at}", files.join("\n")
102
+ end
103
+
104
+
66
105
  License
67
106
  -------
68
107
 
69
- See the LICENSE file for details.
108
+ See the `bin/test-loop` file.
data/bin/test-loop CHANGED
@@ -1,54 +1,98 @@
1
1
  #!/usr/bin/env ruby
2
- require 'rake' # for String#pathmap
2
+ # Continuous testing for Ruby with fork/eval
3
+ # https://github.com/sunaku/test-loop#readme
4
+ #-----------------------------------------------------------------------------
5
+ # (the ISC license)
6
+ #
7
+ # Copyright 2010 Suraj N. Kurapati <sunaku@gmail.com>
8
+ #
9
+ # Permission to use, copy, modify, and/or distribute this software for any
10
+ # purpose with or without fee is hereby granted, provided that the above
11
+ # copyright notice and this permission notice appear in all copies.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
+ # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
+ # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
+ # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
+ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
+ #-----------------------------------------------------------------------------
3
21
 
4
- # absorb test execution overhead into master process
5
- overhead_file_glob = '{test,spec}/*{test,spec}_helper.rb'
6
- $LOAD_PATH.unshift 'lib' # for non-Rails applications
22
+ require 'rake' # for String#pathmap
7
23
 
8
- puts 'test-loop: Absorbing overhead...'
9
- Dir[overhead_file_glob].each do |file|
10
- $LOAD_PATH.insert 1, file.pathmap('%d')
11
- require file.pathmap('%n')
24
+ def notify message
25
+ puts "test-loop: #{message}"
12
26
  end
13
27
 
14
- # continuously watch for and test changed code
15
- started_at = last_ran_at = Time.now
16
- never_ran_at = Time.at(0)
28
+ begin
29
+ notify 'Loading configuration...'
30
+ config_file = File.join(Dir.pwd, '.test-loop')
31
+ load config_file if File.exist? config_file
17
32
 
18
- trap :QUIT do
19
- puts 'test-loop: Re-executing loop...'
20
- started_at = never_ran_at
21
- end
33
+ (@overhead_file_globs ||= []).
34
+ push('{test,spec}/*{test,spec}_helper.rb').uniq!
22
35
 
23
- trap :TSTP do
24
- puts 'test-loop: Testing everything...'
25
- last_ran_at = never_ran_at
26
- end
36
+ (@reabsorb_file_globs ||= []).
37
+ concat(@overhead_file_globs).
38
+ push(config_file, 'config/*.{rb,yml}').uniq!
27
39
 
28
- puts 'test-loop: Ready for testing!'
29
- loop do
30
- # figure out what test files need to be run
31
- test_files = {
40
+ (@source_file_to_test_file_mapping ||= {}).merge!(
32
41
  '{test,spec}/**/*_{test,spec}.rb' => '%p',
33
42
  '{lib,app}/**/*.rb' => '{test,spec}/**/%n_{test,spec}%x',
34
- }.
35
- map do |source_file_glob, test_file_pathmap|
36
- Dir[source_file_glob].
37
- select {|file| File.mtime(file) > last_ran_at }.
38
- map {|path| Dir[path.pathmap(test_file_pathmap)] }
39
- end.flatten.uniq
40
-
41
- # fork worker process to run the test files
42
- unless test_files.empty?
43
- last_ran_at = Time.now
44
- fork { test_files.each {|file| load file } }
45
- Process.wait
43
+ )
44
+
45
+ @after_test_execution ||= lambda {|status, ran_at, files|}
46
+
47
+ # absorb test execution overhead into master process
48
+ $LOAD_PATH.unshift 'lib' # for non-Rails applications
49
+
50
+ notify 'Absorbing overhead...'
51
+ Dir[*@overhead_file_globs].each do |file|
52
+ $LOAD_PATH.insert 1, file.pathmap('%d')
53
+ require file.pathmap('%n')
46
54
  end
47
55
 
48
- # reabsorb test execution overhead as necessary
49
- if Dir[overhead_file_glob].any? {|file| File.mtime(file) > started_at }
50
- exec 'ruby', __FILE__, *ARGV
56
+ # continuously watch for and test changed code
57
+ started_at = last_ran_at = Time.now
58
+ never_ran_at = Time.at(0)
59
+
60
+ trap :QUIT do
61
+ notify 'Re-executing loop...'
62
+ started_at = never_ran_at
63
+ end
64
+
65
+ trap :TSTP do
66
+ notify 'Testing everything...'
67
+ last_ran_at = never_ran_at
51
68
  end
52
69
 
53
- sleep 1
70
+ notify 'Ready for testing!'
71
+ loop do
72
+ # figure out what test files need to be run
73
+ test_files = @source_file_to_test_file_mapping.
74
+ map do |source_file_glob, test_file_pathmap|
75
+ Dir[source_file_glob].
76
+ select {|file| File.mtime(file) > last_ran_at }.
77
+ map {|path| Dir[path.pathmap(test_file_pathmap)] }
78
+ end.flatten.uniq
79
+
80
+ # fork worker process to run the test files
81
+ unless test_files.empty?
82
+ last_ran_at = Time.now
83
+ fork { test_files.each {|file| notify file; load file } }
84
+ Process.wait
85
+ @after_test_execution.call($?, last_ran_at, test_files)
86
+ end
87
+
88
+ # reabsorb test execution overhead as necessary
89
+ if Dir[*@reabsorb_file_globs].any? {|file| File.mtime(file) > started_at }
90
+ exec $0, *ARGV
91
+ end
92
+
93
+ sleep 1
94
+ end
95
+ rescue StandardError, LoadError => error
96
+ puts error.inspect, error.backtrace
97
+ sleep 1 and exec $0, *ARGV
54
98
  end
metadata CHANGED
@@ -3,10 +3,10 @@ name: test-loop
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 1
7
6
  - 2
8
7
  - 0
9
- version: 1.2.0
8
+ - 0
9
+ version: 2.0.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Suraj N. Kurapati
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-23 00:00:00 -08:00
17
+ date: 2010-12-31 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -27,7 +27,6 @@ extensions: []
27
27
  extra_rdoc_files: []
28
28
 
29
29
  files:
30
- - LICENSE
31
30
  - README.md
32
31
  - bin/test-loop
33
32
  has_rdoc: true
data/LICENSE DELETED
@@ -1,15 +0,0 @@
1
- (the ISC license)
2
-
3
- Copyright 2010 Suraj N. Kurapati <sunaku@gmail.com>
4
-
5
- Permission to use, copy, modify, and/or distribute this software for any
6
- purpose with or without fee is hereby granted, provided that the above
7
- copyright notice and this permission notice appear in all copies.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.