test-loop 12.0.0 → 12.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.md +34 -24
  2. data/lib/test/loop.rb +23 -25
  3. metadata +2 -2
data/README.md CHANGED
@@ -4,39 +4,49 @@ test-loop - Continuous testing for Ruby with fork/eval
4
4
  test-loop is a fast continuous testing tool for Ruby that automatically
5
5
  detects and tests changes in your application in an efficient manner:
6
6
 
7
- 1. Absorbs the test execution overhead into the main Ruby process.
8
- 2. Forks to run your test files without overhead and in parallel.
9
- 3. Avoids running unchanged test blocks inside changed test files.
7
+ 1. Absorbs the test execution overhead into the main Ruby process.
8
+
9
+ 2. Forks to run your test files without overhead and in parallel.
10
+
11
+ 3. Avoids running unchanged test blocks inside changed test files.
10
12
 
11
13
  ------------------------------------------------------------------------------
12
14
  Features
13
15
  ------------------------------------------------------------------------------
14
16
 
15
- * Tests *changes* in your Ruby application: avoids running (1) unchanged
16
- test files and (2) unchanged test blocks inside changed test files.
17
+ * Tests *changes* in your Ruby application: avoids running (1) unchanged
18
+ test files and (2) unchanged test blocks inside changed test files.
17
19
 
18
- * Supports Test::Unit, RSpec, and any other testing framework that (1)
19
- reflects failures in the process' exit status and (2) is loaded by your
20
- application's `test/test_helper.rb` or `spec/spec_helper.rb` file.
20
+ * Supports Test::Unit, RSpec, and any other testing framework that (1)
21
+ reflects failures in the process' exit status and (2) is loaded by your
22
+ application's `test/test_helper.rb` or `spec/spec_helper.rb` file.
21
23
 
22
- * Reabsorbs test execution overhead if the test or spec helper file changes.
24
+ * Reabsorbs test execution overhead if the test or spec helper file changes.
23
25
 
24
- * Executes test files in parallel, making full use of multiple processors.
26
+ * Executes test files in parallel, making full use of multiple processors.
25
27
 
26
- * Logs the output from your tests into separate files: one log per test file.
27
- The path to a log file is simply the path of its test file plus ".log".
28
+ * Logs the output from your tests into separate files: one log per test.
29
+ The path to a log file is simply the path of its test file plus ".log".
28
30
 
29
- * Generally I/O bound, so you can have it always running without CPU slowdown.
31
+ * Generally I/O bound, so you can keep it running without CPU slowdown.
30
32
 
31
- * Configurable through a `.test-loop` file in your current working directory.
33
+ * Configurable through a `.test-loop` file in your working directory.
32
34
 
33
- * Implemented in less than 250 lines (SLOC) of pure Ruby code! :-)
35
+ * Implemented in less than 220 lines (SLOC) of pure Ruby code! :-)
34
36
 
35
37
  ------------------------------------------------------------------------------
36
38
  Prerequisites
37
39
  ------------------------------------------------------------------------------
38
40
 
39
- * Operating system that supports POSIX signals and the `fork()` system call.
41
+ * Ruby 1.8.7 or 1.9.2 or newer.
42
+
43
+ * Operating system that supports POSIX signals and the `fork()` system call.
44
+
45
+ To check if your system qualifies, launch `irb` and enter the following:
46
+
47
+ Process.respond_to? :fork # must be true
48
+
49
+ Signal.list.keys & %w[INT TSTP QUIT TERM CHLD] # must not be empty
40
50
 
41
51
  ------------------------------------------------------------------------------
42
52
  Installation
@@ -65,7 +75,7 @@ If installed as a Git clone:
65
75
 
66
76
  You can monitor your test processes in another terminal:
67
77
 
68
- watch 'ps xf | grep test-loop | sed 1,3d'
78
+ watch 'ps xf | fgrep test-loop | fgrep -v fgrep'
69
79
 
70
80
  If it stops responding, you can annihilate test-loop from another terminal:
71
81
 
@@ -75,13 +85,13 @@ If it stops responding, you can annihilate test-loop from another terminal:
75
85
  Operation
76
86
  ------------------------------------------------------------------------------
77
87
 
78
- * Press Control-Z or send the SIGTSTP signal to forcibly run all
79
- tests, even if there are no changes in your Ruby application.
88
+ * Press Control-Z or send the SIGTSTP signal to forcibly run all
89
+ tests, even if there are no changes in your Ruby application.
80
90
 
81
- * Press Control-\ or send the SIGQUIT signal to forcibly reabsorb
82
- the test execution overhead, even if its sources have not changed.
91
+ * Press Control-\ or send the SIGQUIT signal to forcibly reabsorb
92
+ the test execution overhead, even if its sources have not changed.
83
93
 
84
- * Press Control-C or send the SIGINT signal to quit the test loop.
94
+ * Press Control-C or send the SIGINT signal to quit the test loop.
85
95
 
86
96
  ------------------------------------------------------------------------------
87
97
  Configuration
@@ -112,8 +122,8 @@ hash key; left-hand side of the mapping) change, their associated test files
112
122
  For example, if test files had the same names as their source files followed
113
123
  by an underscore and the file name in reverse like this:
114
124
 
115
- * `lib/hello.rb` => `test/hello_olleh.rb`
116
- * `app/world.rb` => `spec/world_ldrow.rb`
125
+ * `lib/hello.rb` => `test/hello_olleh.rb`
126
+ * `app/world.rb` => `spec/world_ldrow.rb`
117
127
 
118
128
  Then you would add the following to your configuration file:
119
129
 
data/lib/test/loop.rb CHANGED
@@ -70,9 +70,9 @@ module Test
70
70
 
71
71
  private
72
72
 
73
- MASTER_ARGV = [$0, *ARGV].map {|s| s.dup.freeze }.freeze
73
+ MASTER_EXECV = [$0, *ARGV].map {|s| s.dup.freeze }.freeze
74
+ MASTER_ENV = Hash[ENV.map {|k,v| [k.freeze, v.freeze] }].freeze
74
75
  RESUME_ENV_KEY = 'TEST_LOOP_RESUME_FILES'.freeze
75
- MASTER_ENV = ENV.to_hash.delete_if {|k,v| k == RESUME_ENV_KEY }.freeze
76
76
 
77
77
  ANSI_CLEAR_LINE = "\e[2K\e[0G".freeze
78
78
  ANSI_GREEN = "\e[32m%s\e[0m".freeze
@@ -97,7 +97,7 @@ module Test
97
97
  def register_signals
98
98
  # this signal is ignored in master and honored in workers, so all
99
99
  # workers can be killed by sending it to the entire process group
100
- trap :TERM, :IGNORE
100
+ trap :TERM, 'IGNORE'
101
101
 
102
102
  trap :CHLD do
103
103
  finished_at = Time.now
@@ -106,24 +106,22 @@ module Test
106
106
  worker_pid = Process.wait
107
107
  run_status = $?
108
108
 
109
- worker = @worker_by_pid.delete(worker_pid)
110
- elapsed_time = finished_at - worker.started_at
111
-
112
- # report test results along with any failure logs
113
- if run_status.success?
114
- notify ANSI_GREEN % "PASS #{worker.test_file}"
115
- elsif run_status.exited?
116
- notify ANSI_RED % "FAIL #{worker.test_file}"
117
- STDERR.print File.read(worker.log_file)
118
- end
119
-
120
- after_each_test.each do |hook|
121
- hook.call worker.test_file, worker.log_file, run_status,
122
- worker.started_at, elapsed_time
109
+ if worker = @worker_by_pid.delete(worker_pid)
110
+ @running_files.delete worker.test_file
111
+
112
+ # report test results along with any failure logs
113
+ if run_status.success?
114
+ notify ANSI_GREEN % "PASS #{worker.test_file}"
115
+ elsif run_status.exited?
116
+ notify ANSI_RED % "FAIL #{worker.test_file}"
117
+ STDERR.print File.read(worker.log_file)
118
+ end
119
+
120
+ after_each_test.each do |hook|
121
+ hook.call worker.test_file, worker.log_file, run_status,
122
+ worker.started_at, finished_at - worker.started_at
123
+ end
123
124
  end
124
-
125
- @running_files.delete worker.test_file
126
-
127
125
  rescue Errno::ECHILD
128
126
  # could not get the terminated child's PID.
129
127
  # Ruby's backtick operator can cause this:
@@ -132,8 +130,8 @@ module Test
132
130
  end
133
131
 
134
132
  trap(:INT) { raise Interrupt }
135
- trap(:QUIT) { reload_master_process }
136
133
  trap(:TSTP) { forcibly_run_all_tests }
134
+ trap(:QUIT) { reload_master_process }
137
135
  end
138
136
 
139
137
  def kill_workers
@@ -147,8 +145,8 @@ module Test
147
145
  def reload_master_process test_files = []
148
146
  test_files.concat @running_files
149
147
  kill_workers
150
- exec MASTER_ENV.merge(RESUME_ENV_KEY => test_files.inspect),
151
- *MASTER_ARGV, {:unsetenv_others => true}
148
+ ENV.replace MASTER_ENV.merge(RESUME_ENV_KEY => test_files.inspect)
149
+ exec(*MASTER_EXECV)
152
150
  end
153
151
 
154
152
  def load_user_config
@@ -226,10 +224,10 @@ module Test
226
224
  started_at = Time.now
227
225
  worker_pid = fork do
228
226
  # handle signals meant for worker process
229
- [:TERM, :CHLD].each {|sig| trap sig, :DEFAULT }
227
+ [:TERM, :CHLD].each {|sig| trap sig, 'DEFAULT' }
230
228
 
231
229
  # ignore signals meant for master process
232
- [:INT, :QUIT, :TSTP].each {|sig| trap sig, :IGNORE }
230
+ [:INT, :TSTP, :QUIT].each {|sig| trap sig, 'IGNORE' }
233
231
 
234
232
  # detach worker from master's terminal device so that
235
233
  # it does not receieve the user's control-key presses
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: test-loop
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 12.0.0
5
+ version: 12.0.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Suraj N. Kurapati
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-04-19 00:00:00 -07:00
14
+ date: 2011-04-20 00:00:00 -07:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency