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.
- data/README.md +41 -2
- data/bin/test-loop +83 -39
- metadata +3 -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
|
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
|
108
|
+
See the `bin/test-loop` file.
|
data/bin/test-loop
CHANGED
@@ -1,54 +1,98 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
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
|
-
|
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
|
-
|
9
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
20
|
-
started_at = never_ran_at
|
21
|
-
end
|
33
|
+
(@overhead_file_globs ||= []).
|
34
|
+
push('{test,spec}/*{test,spec}_helper.rb').uniq!
|
22
35
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
36
|
+
(@reabsorb_file_globs ||= []).
|
37
|
+
concat(@overhead_file_globs).
|
38
|
+
push(config_file, 'config/*.{rb,yml}').uniq!
|
27
39
|
|
28
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
#
|
49
|
-
|
50
|
-
|
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
|
-
|
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
|
-
|
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-
|
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.
|