test-loop 12.3.1 → 13.0.0
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.
- 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
|