test-loop 12.3.1 → 13.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -0
- data/README.md +43 -34
- data/lib/test/loop.rb +14 -10
- data/lib/test/loop/notify.rb +2 -1
- data/lib/test/loop/parallel_tests.rb +9 -0
- data/lib/test/loop/rails.rb +19 -8
- metadata +7 -5
data/LICENSE
CHANGED
@@ -4,6 +4,7 @@ Copyright 2010 Suraj N. Kurapati <sunaku@gmail.com>
|
|
4
4
|
Copyright 2011 Brian D. Burns <burns180@gmail.com>
|
5
5
|
Copyright 2011 Daniel Pittman <daniel@rimspace.net>
|
6
6
|
Copyright 2011 Jacob Helwig <jacob@technosorcery.net>
|
7
|
+
Copyright 2011 Corné Verbruggen <corne@g-majeur.nl>
|
7
8
|
|
8
9
|
Permission to use, copy, modify, and/or distribute this software for any
|
9
10
|
purpose with or without fee is hereby granted, provided that the above
|
data/README.md
CHANGED
@@ -100,7 +100,34 @@ Configuration
|
|
100
100
|
|
101
101
|
test-loop looks for a configuration file named `.test-loop` in the current
|
102
102
|
working directory. This configuration file is a normal Ruby script in which
|
103
|
-
you can query and modify the `Test::Loop` OpenStruct configuration
|
103
|
+
you can query and modify the `Test::Loop` OpenStruct configuration object
|
104
|
+
according to the configuration options listed below.
|
105
|
+
|
106
|
+
------------------------------------------------------------------------------
|
107
|
+
Configuration presets
|
108
|
+
------------------------------------------------------------------------------
|
109
|
+
|
110
|
+
The following sub-libraries provide "preset" configurations. To use them,
|
111
|
+
simply add the require() lines shown below to your `.test-loop` file or to
|
112
|
+
your application's `test/test_helper.rb` or `spec/spec_helper.rb` file.
|
113
|
+
|
114
|
+
### require 'test/loop/notify'
|
115
|
+
|
116
|
+
Shows on-screen-display notifications for test failures.
|
117
|
+
|
118
|
+
### require 'test/loop/rails'
|
119
|
+
|
120
|
+
Provides support for the Ruby on Rails web framework.
|
121
|
+
|
122
|
+
### require 'test-loop/coco'
|
123
|
+
|
124
|
+
Integrates the [coco](https://github.com/lkdjiin/coco) code coverage library.
|
125
|
+
|
126
|
+
------------------------------------------------------------------------------
|
127
|
+
Configuration options
|
128
|
+
------------------------------------------------------------------------------
|
129
|
+
|
130
|
+
The `Test::Loop` OpenStruct configuration object holds the following options:
|
104
131
|
|
105
132
|
### Test::Loop.delay_per_iteration
|
106
133
|
|
@@ -133,9 +160,8 @@ by an underscore and the file name in reverse like this:
|
|
133
160
|
Then you would add the following to your configuration file:
|
134
161
|
|
135
162
|
Test::Loop.test_file_matchers['{lib,app}/**/*.rb'] = lambda do |path|
|
136
|
-
|
137
|
-
name
|
138
|
-
"{test,spec}/**/#{name}_#{name.reverse}#{extn}"
|
163
|
+
name = File.basename(path, '.rb')
|
164
|
+
"{test,spec}/**/#{name}_#{name.reverse}.rb"
|
139
165
|
end
|
140
166
|
|
141
167
|
In addition, these lambda functions can return `nil` if they do not wish for a
|
@@ -162,18 +188,20 @@ name of the test being defined.
|
|
162
188
|
Array of lambda functions that are executed inside the worker process before
|
163
189
|
loading the test file.
|
164
190
|
|
165
|
-
These functions are passed (1) the path to the test file, (2) the path to
|
166
|
-
|
167
|
-
|
191
|
+
These functions are passed (1) the path to the test file, (2) the path to the
|
192
|
+
log file containing the live output of running the test file, (3) an array
|
193
|
+
containing the names of tests (which were identified by
|
168
194
|
`Test::Loop.test_name_parser`) inside the test file that have changed since
|
169
|
-
the last run of the test file
|
195
|
+
the last run of the test file, and (4) a rotating sequence number of the
|
196
|
+
worker process that will run the test file.
|
170
197
|
|
171
198
|
For example, to print a worker process' ID and what work it will perform:
|
172
199
|
|
173
200
|
Test::Loop.before_each_test.push lambda {
|
174
|
-
|
201
|
+
|test_file, log_file, test_names, worker_id|
|
175
202
|
|
176
203
|
p :worker_pid => $$,
|
204
|
+
:worker_id => worker_id,
|
177
205
|
:test_file => test_file,
|
178
206
|
:log_file => log_file,
|
179
207
|
:test_names => test_names
|
@@ -191,14 +219,15 @@ test has finished running.
|
|
191
219
|
These functions are passed (1) the path to the test file, (2) the path to the
|
192
220
|
log file containing the output of running the test file, (3) a
|
193
221
|
`Process::Status` object describing the exit status of the worker process that
|
194
|
-
ran the test file, (4) the time when test execution began,
|
195
|
-
seconds it took for the overall test execution to complete
|
222
|
+
ran the test file, (4) the time when test execution began, (5) how many
|
223
|
+
seconds it took for the overall test execution to complete, and (6) a rotating
|
224
|
+
sequence number of the worker process that ran the test file.
|
196
225
|
|
197
226
|
For example, to delete log files for successful tests, add the following to
|
198
227
|
your configuration file:
|
199
228
|
|
200
229
|
Test::Loop.after_each_test.push lambda {
|
201
|
-
|test_file, log_file, run_status, started_at, elapsed_time|
|
230
|
+
|test_file, log_file, run_status, started_at, elapsed_time, worker_id|
|
202
231
|
|
203
232
|
File.delete(log_file) if run_status.success?
|
204
233
|
}
|
@@ -208,7 +237,7 @@ add the following to your configuration file (**NOTE:** the `test/loop/notify`
|
|
208
237
|
preset does this for you):
|
209
238
|
|
210
239
|
Test::Loop.after_each_test.push lambda {
|
211
|
-
|test_file, log_file, run_status, started_at, elapsed_time|
|
240
|
+
|test_file, log_file, run_status, started_at, elapsed_time, worker_id|
|
212
241
|
|
213
242
|
unless run_status.success? or run_status.signaled?
|
214
243
|
title = 'FAIL at %s in %0.1fs' % [started_at.strftime('%r'), elapsed_time]
|
@@ -229,7 +258,7 @@ regardless of whether they passed or failed, add the following to your
|
|
229
258
|
configuration file:
|
230
259
|
|
231
260
|
Test::Loop.after_each_test.push lambda {
|
232
|
-
|test_file, log_file, run_status, started_at, elapsed_time|
|
261
|
+
|test_file, log_file, run_status, started_at, elapsed_time, worker_id|
|
233
262
|
|
234
263
|
success = run_status.success?
|
235
264
|
|
@@ -250,26 +279,6 @@ configuration file:
|
|
250
279
|
|
251
280
|
Maximum number of test files to run concurrently. The default value is 4.
|
252
281
|
|
253
|
-
------------------------------------------------------------------------------
|
254
|
-
Configuration presets
|
255
|
-
------------------------------------------------------------------------------
|
256
|
-
|
257
|
-
The following sub-libraries provide "preset" configurations. To use them,
|
258
|
-
simply add the require() lines shown below to your `.test-loop` file or to
|
259
|
-
your application's `test/test_helper.rb` or `spec/spec_helper.rb` file.
|
260
|
-
|
261
|
-
### require 'test/loop/notify'
|
262
|
-
|
263
|
-
Shows on-screen-display notifications for test failures.
|
264
|
-
|
265
|
-
### require 'test/loop/rails'
|
266
|
-
|
267
|
-
Provides support for the Ruby on Rails web framework.
|
268
|
-
|
269
|
-
### require 'test-loop/coco'
|
270
|
-
|
271
|
-
Integrates the [coco](https://github.com/lkdjiin/coco) code coverage library.
|
272
|
-
|
273
282
|
------------------------------------------------------------------------------
|
274
283
|
Known issues
|
275
284
|
------------------------------------------------------------------------------
|
data/lib/test/loop.rb
CHANGED
@@ -17,9 +17,8 @@ module Test
|
|
17
17
|
Loop.test_file_matchers = {
|
18
18
|
# source files that correspond to test files
|
19
19
|
'lib/**/*.rb' => lambda do |path|
|
20
|
-
|
21
|
-
base
|
22
|
-
"{test,spec}/**/#{base}_{test,spec}#{extn}"
|
20
|
+
base = File.basename(path, '.rb')
|
21
|
+
"{test,spec}/**/#{base}_{test,spec}.rb"
|
23
22
|
end,
|
24
23
|
|
25
24
|
# the actual test files themselves
|
@@ -34,7 +33,7 @@ module Test
|
|
34
33
|
end
|
35
34
|
|
36
35
|
Loop.before_each_test = [
|
37
|
-
lambda {|test_file, log_file, test_names|
|
36
|
+
lambda {|test_file, log_file, test_names, worker_id|
|
38
37
|
unless test_names.empty?
|
39
38
|
test_name_pattern = test_names.map do |name|
|
40
39
|
# sanitize string interpolations and invalid method name characters
|
@@ -86,7 +85,7 @@ module Test
|
|
86
85
|
ANSI_RED = "\e[31m%s\e[0m".freeze
|
87
86
|
|
88
87
|
Worker = Struct.new(:test_file, :log_file, :started_at, :finished_at,
|
89
|
-
:exit_status)
|
88
|
+
:exit_status, :id)
|
90
89
|
|
91
90
|
def notify message
|
92
91
|
# using print() because puts() is not an atomic operation.
|
@@ -122,9 +121,8 @@ module Test
|
|
122
121
|
def reload_master_process test_files = Set.new
|
123
122
|
test_files.merge currently_running_test_files
|
124
123
|
stop_worker_queue
|
125
|
-
|
126
|
-
|
127
|
-
exec(*MASTER_EXECV)
|
124
|
+
resume_env = Base64.encode64(Marshal.dump(test_files))
|
125
|
+
exec MASTER_ENV.merge(RESUME_ENV_KEY => resume_env), *MASTER_EXECV
|
128
126
|
end
|
129
127
|
|
130
128
|
def load_user_config
|
@@ -195,6 +193,8 @@ module Test
|
|
195
193
|
end
|
196
194
|
|
197
195
|
def init_worker_queue
|
196
|
+
@worker_id_pool = (0 ... max_concurrent_tests).to_a
|
197
|
+
|
198
198
|
# collect children (of which some may be workers) for reaping below
|
199
199
|
@exited_child_infos = []
|
200
200
|
trap :CHLD do
|
@@ -237,6 +237,7 @@ module Test
|
|
237
237
|
def fork_worker worker
|
238
238
|
notify "TEST #{worker.test_file}"
|
239
239
|
|
240
|
+
worker.id = @worker_id_pool.shift
|
240
241
|
worker.log_file = worker.test_file + '.log'
|
241
242
|
|
242
243
|
# cache the contents of the test file for diffing below
|
@@ -275,7 +276,7 @@ module Test
|
|
275
276
|
|
276
277
|
# tell the testing framework to run only the changed test blocks
|
277
278
|
before_each_test.each do |hook|
|
278
|
-
hook.call worker.test_file, worker.log_file, test_names
|
279
|
+
hook.call worker.test_file, worker.log_file, test_names, worker.id
|
279
280
|
end
|
280
281
|
|
281
282
|
# make the process title Test::Unit friendly and ps(1) searchable
|
@@ -301,8 +302,11 @@ module Test
|
|
301
302
|
|
302
303
|
after_each_test.each do |hook|
|
303
304
|
hook.call worker.test_file, worker.log_file, worker.exit_status,
|
304
|
-
worker.started_at, worker.finished_at - worker.started_at
|
305
|
+
worker.started_at, worker.finished_at - worker.started_at,
|
306
|
+
worker.id
|
305
307
|
end
|
308
|
+
|
309
|
+
@worker_id_pool.push worker.id
|
306
310
|
end
|
307
311
|
end
|
308
312
|
end
|
data/lib/test/loop/notify.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'test/loop'
|
2
2
|
|
3
3
|
Test::Loop.after_each_test.push lambda {
|
4
|
-
|test_file, log_file, run_status, started_at, elapsed_time|
|
4
|
+
|test_file, log_file, run_status, started_at, elapsed_time, worker_id|
|
5
|
+
|
5
6
|
unless run_status.success? or run_status.signaled?
|
6
7
|
title = 'FAIL at %s in %0.1fs' % [started_at.strftime('%r'), elapsed_time]
|
7
8
|
statistics = File.readlines(log_file).grep(/^\d+ \w+,/)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'test/loop'
|
2
|
+
|
3
|
+
Test::Loop.before_each_test.push lambda {
|
4
|
+
|test_file, log_file, test_names, worker_id|
|
5
|
+
|
6
|
+
# for compatitibilty with parallel_tests gem,
|
7
|
+
# use numbers as strings: "", "2", "3", "4"
|
8
|
+
ENV['TEST_ENV_NUMBER'] = worker_id.next.to_s if worker_id > 0
|
9
|
+
}
|
data/lib/test/loop/rails.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'test/loop'
|
2
|
+
require 'active_support/inflector'
|
2
3
|
|
3
4
|
Test::Loop.reabsorb_file_globs.push(
|
4
5
|
'config/**/*.{rb,yml}',
|
@@ -7,20 +8,30 @@ Test::Loop.reabsorb_file_globs.push(
|
|
7
8
|
)
|
8
9
|
|
9
10
|
Test::Loop.test_file_matchers['{app,lib,test,spec}/**/*.rb'] =
|
10
|
-
|
11
|
+
lambda do |path|
|
12
|
+
base = File.basename(path, '.rb')
|
13
|
+
poly = ActiveSupport::Inflector.pluralize(base)
|
14
|
+
"{test,spec}/**/{#{base},#{poly}_*}_{test,spec}.rb"
|
15
|
+
end
|
11
16
|
|
12
17
|
Test::Loop.test_file_matchers['{test,spec}/factories/**/*_factory.rb'] =
|
13
18
|
lambda do |path|
|
14
19
|
base = File.basename(path, '_factory.rb')
|
15
|
-
|
20
|
+
poly = ActiveSupport::Inflector.pluralize(base)
|
21
|
+
"{test,spec}/**/{#{base},#{poly}_*}_{test,spec}.rb"
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
begin
|
25
|
+
require 'rails/railtie'
|
26
|
+
Class.new Rails::Railtie do
|
27
|
+
config.before_initialize do |app|
|
28
|
+
if app.config.cache_classes
|
29
|
+
warn "test-loop: Setting #{app.class}.config.cache_classes = false"
|
30
|
+
app.config.cache_classes = false
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
34
|
+
rescue LoadError
|
35
|
+
warn "test-loop: Railtie not available; please manually set:\n\t"\
|
36
|
+
"config.cache_classes = false"
|
26
37
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test-loop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 13.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,15 @@ authors:
|
|
9
9
|
- Brian D. Burns
|
10
10
|
- Daniel Pittman
|
11
11
|
- Jacob Helwig
|
12
|
+
- Corné Verbruggen
|
12
13
|
autorequire:
|
13
14
|
bindir: bin
|
14
15
|
cert_chain: []
|
15
|
-
date: 2011-
|
16
|
+
date: 2011-08-24 00:00:00.000000000 Z
|
16
17
|
dependencies:
|
17
18
|
- !ruby/object:Gem::Dependency
|
18
19
|
name: diff-lcs
|
19
|
-
requirement: &
|
20
|
+
requirement: &19985940 !ruby/object:Gem::Requirement
|
20
21
|
none: false
|
21
22
|
requirements:
|
22
23
|
- - ! '>='
|
@@ -24,7 +25,7 @@ dependencies:
|
|
24
25
|
version: 1.1.2
|
25
26
|
type: :runtime
|
26
27
|
prerelease: false
|
27
|
-
version_requirements: *
|
28
|
+
version_requirements: *19985940
|
28
29
|
description:
|
29
30
|
email:
|
30
31
|
executables:
|
@@ -38,6 +39,7 @@ files:
|
|
38
39
|
- lib/test/loop.rb
|
39
40
|
- lib/test/loop/notify.rb
|
40
41
|
- lib/test/loop/rails.rb
|
42
|
+
- lib/test/loop/parallel_tests.rb
|
41
43
|
homepage: http://github.com/sunaku/test-loop
|
42
44
|
licenses: []
|
43
45
|
post_install_message:
|
@@ -58,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
60
|
version: '0'
|
59
61
|
requirements: []
|
60
62
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.8.
|
63
|
+
rubygems_version: 1.8.9
|
62
64
|
signing_key:
|
63
65
|
specification_version: 3
|
64
66
|
summary: Continuous testing for Ruby with fork/eval
|