forking_test_runner 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/forking_test_runner/version.rb +1 -1
- data/lib/forking_test_runner.rb +103 -51
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 989a8330a49520c4aaa7d1a073f5a9ab216793cf
|
4
|
+
data.tar.gz: 983e7875d09eb54246efd8f8859d0f1c3a81387c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e691f90b08041be6598d725959951bb7cc475e9cc98563cc32e9fb4f59d452d874c61bd60387b63effd1b4ce35b038dcf5b301282eca69569476755a49aa0ac0
|
7
|
+
data.tar.gz: 3e7633c9cbc4f11b946e7f9b6526f8a112faa3811cde9e49135de322fba9e56ad3ca1b4d86ed2b8e97866097a3ae53e073210a5f8a24dd12e51b1b59d9dd4596
|
data/lib/forking_test_runner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'benchmark'
|
2
|
+
require 'optparse'
|
2
3
|
|
3
4
|
module ForkingTestRunner
|
4
5
|
CLEAR = "------"
|
@@ -38,29 +39,18 @@ module ForkingTestRunner
|
|
38
39
|
|
39
40
|
class << self
|
40
41
|
def cli(argv)
|
41
|
-
@
|
42
|
-
@no_fixtures = delete_argv("--no-fixtures", argv, arg: false)
|
43
|
-
@quiet = delete_argv("--quiet", argv, arg: false)
|
44
|
-
@merge_coverage = delete_argv("--merge-coverage", argv, arg: false)
|
45
|
-
|
46
|
-
if @merge_coverage
|
47
|
-
raise "merge_coverage does not work on ruby prior to 2.3" if RUBY_VERSION < "2.3.0"
|
48
|
-
require 'coverage'
|
49
|
-
klass = (class << Coverage; self; end)
|
50
|
-
klass.prepend CoverageCapture
|
51
|
-
end
|
42
|
+
@options, tests = parse_options(argv)
|
52
43
|
|
53
44
|
disable_test_autorun
|
54
45
|
|
55
|
-
load_test_env(
|
46
|
+
load_test_env(@options.fetch(:helper))
|
56
47
|
|
57
48
|
# figure out what we need to run
|
58
|
-
|
59
|
-
|
60
|
-
group, group_count, tests = extract_group_args(argv)
|
49
|
+
runtime_log = @options.fetch(:runtime_log)
|
50
|
+
group, group_count = find_group_args
|
61
51
|
tests = find_tests_for_group(group, group_count, tests, runtime_log)
|
62
52
|
|
63
|
-
if @quiet
|
53
|
+
if @options.fetch(:quiet)
|
64
54
|
puts "Running #{tests.size} test files"
|
65
55
|
else
|
66
56
|
puts "Running tests #{tests.map(&:first).join(" ")}"
|
@@ -71,27 +61,27 @@ module ForkingTestRunner
|
|
71
61
|
ActiveRecord::Base.connection.disconnect!
|
72
62
|
end
|
73
63
|
|
74
|
-
Coverage.capture_coverage! if @merge_coverage
|
64
|
+
Coverage.capture_coverage! if @options.fetch(:merge_coverage)
|
75
65
|
|
76
66
|
# run all the tests
|
77
67
|
results = tests.map do |file, expected|
|
78
68
|
puts "#{CLEAR} >>> #{file} "
|
79
69
|
time, success, output = benchmark { run_test(file) }
|
80
70
|
|
81
|
-
puts output if !success && @quiet
|
71
|
+
puts output if !success && @options.fetch(:quiet)
|
82
72
|
|
83
|
-
if runtime_log && !@quiet
|
73
|
+
if runtime_log && !@options.fetch(:quiet)
|
84
74
|
puts "Time: expected #{expected.round(2)}, actual #{time.round(2)}"
|
85
75
|
end
|
86
76
|
|
87
|
-
if !success || !@quiet
|
77
|
+
if !success || !@options.fetch(:quiet)
|
88
78
|
puts "#{CLEAR} <<< #{file} ---- #{success ? "OK" : "Failed"}"
|
89
79
|
end
|
90
80
|
|
91
81
|
[file, time, expected, output, success]
|
92
82
|
end
|
93
83
|
|
94
|
-
unless @quiet
|
84
|
+
unless @options.fetch(:quiet)
|
95
85
|
# pretty print the results
|
96
86
|
puts "\nResults:"
|
97
87
|
puts results.
|
@@ -110,10 +100,10 @@ module ForkingTestRunner
|
|
110
100
|
puts "Time: #{diff.round(2)} diff to expected"
|
111
101
|
end
|
112
102
|
|
113
|
-
if record_runtime
|
103
|
+
if mode = @options.fetch(:record_runtime)
|
114
104
|
# store runtime log
|
115
105
|
log = runtime_log || 'runtime.log'
|
116
|
-
record_test_runtime(
|
106
|
+
record_test_runtime(mode, results, log)
|
117
107
|
end
|
118
108
|
|
119
109
|
# exit with success or failure
|
@@ -131,7 +121,7 @@ module ForkingTestRunner
|
|
131
121
|
end
|
132
122
|
|
133
123
|
def summarize_results(results)
|
134
|
-
runner = if @rspec
|
124
|
+
runner = if @options.fetch(:rspec)
|
135
125
|
require 'parallel_tests/rspec/runner'
|
136
126
|
ParallelTests::RSpec::Runner
|
137
127
|
else
|
@@ -174,36 +164,29 @@ module ForkingTestRunner
|
|
174
164
|
end
|
175
165
|
end
|
176
166
|
|
177
|
-
def
|
178
|
-
if
|
167
|
+
def find_group_args
|
168
|
+
if @options.fetch(:group) && @options.fetch(:groups)
|
179
169
|
# delete options we want while leaving others as they are (-v / --seed etc)
|
180
|
-
group
|
181
|
-
|
182
|
-
value.to_i
|
183
|
-
end
|
184
|
-
dir = argv.shift
|
185
|
-
raise "Unable to find directory #{dir.inspect}" unless File.exist?(dir.to_s)
|
186
|
-
tests = [dir]
|
170
|
+
group = @options.fetch(:group)
|
171
|
+
group_count = @options.fetch(:groups)
|
187
172
|
else
|
188
173
|
group = 1
|
189
174
|
group_count = 1
|
190
|
-
size = argv.index { |arg| arg.start_with? "-" } || argv.size
|
191
|
-
tests = argv.slice!(0, size)
|
192
175
|
end
|
193
176
|
|
194
|
-
[group, group_count
|
177
|
+
[group, group_count]
|
195
178
|
end
|
196
179
|
|
197
180
|
def load_test_env(helper=nil)
|
198
|
-
require 'rspec' if @rspec
|
199
|
-
helper = helper || (@rspec ? "spec/spec_helper" : "test/test_helper")
|
181
|
+
require 'rspec' if @options.fetch(:rspec)
|
182
|
+
helper = helper || (@options.fetch(:rspec) ? "spec/spec_helper" : "test/test_helper")
|
200
183
|
require "./#{helper}"
|
201
184
|
end
|
202
185
|
|
203
186
|
# This forces Rails to load all fixtures, then prevents it from
|
204
187
|
# "deleting and re-inserting all fixtures" when a new connection is used (forked).
|
205
188
|
def preload_fixtures
|
206
|
-
return if @no_fixtures
|
189
|
+
return if @options.fetch(:no_fixtures)
|
207
190
|
|
208
191
|
fixtures = (ActiveSupport::VERSION::MAJOR == 3 ? ActiveRecord::Fixtures : ActiveRecord::FixtureSet)
|
209
192
|
|
@@ -256,7 +239,7 @@ module ForkingTestRunner
|
|
256
239
|
|
257
240
|
def run_test(file)
|
258
241
|
output = change_program_name_to file do
|
259
|
-
fork_with_captured_output(!@quiet) do
|
242
|
+
fork_with_captured_output(!@options.fetch(:quiet)) do
|
260
243
|
SimpleCov.pid = Process.pid if defined?(SimpleCov) && SimpleCov.respond_to?(:pid=) # trick simplecov into reporting in this fork
|
261
244
|
if ar?
|
262
245
|
key = (ActiveRecord::VERSION::STRING >= "4.1.0" ? :test : "test")
|
@@ -294,16 +277,6 @@ module ForkingTestRunner
|
|
294
277
|
group.map { |test| [test, (tests[test] if group_by == :runtime)] }
|
295
278
|
end
|
296
279
|
|
297
|
-
def delete_argv(name, argv, arg: true)
|
298
|
-
return unless index = argv.index(name)
|
299
|
-
argv.delete_at(index)
|
300
|
-
if arg
|
301
|
-
argv.delete_at(index) || raise("Missing argument for #{name}")
|
302
|
-
else
|
303
|
-
true
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
280
|
def ar?
|
308
281
|
defined?(ActiveRecord::Base)
|
309
282
|
end
|
@@ -323,7 +296,7 @@ module ForkingTestRunner
|
|
323
296
|
end
|
324
297
|
|
325
298
|
def toggle_test_autorun(value, file=nil)
|
326
|
-
if @rspec
|
299
|
+
if @options.fetch(:rspec)
|
327
300
|
if value
|
328
301
|
exit(RSpec::Core::Runner.run([file] + ARGV))
|
329
302
|
else
|
@@ -342,5 +315,84 @@ module ForkingTestRunner
|
|
342
315
|
end
|
343
316
|
end
|
344
317
|
end
|
318
|
+
|
319
|
+
# we remove the args we understand and leave the rest alone
|
320
|
+
# so minitest / rspec can read their own options (--seed / -v ...)
|
321
|
+
# - keep our options clear / unambiguous to avoid overriding
|
322
|
+
# - read all serial non-flag arguments as tests and leave only unknown options behind
|
323
|
+
# - use .fetch everywhere to make sure nothing is misspelled
|
324
|
+
# GOOD: test --ours --theirs
|
325
|
+
# OK: --ours test --theirs
|
326
|
+
# BAD: --theirs test --ours
|
327
|
+
def parse_options(argv)
|
328
|
+
arguments = [
|
329
|
+
[:rspec, "--rspec", "RSpec mode"],
|
330
|
+
[:helper, "--helper", "Helper file to load before tests start", String],
|
331
|
+
[:quiet, "--quiet", "Quiet"],
|
332
|
+
[:no_fixtures, "--no-fixtures", "Do not load fixtures"],
|
333
|
+
[:merge_coverage, "--merge-coverage", "Merge base code coverage into indvidual files coverage, great for SingleCov"],
|
334
|
+
[
|
335
|
+
:record_runtime,
|
336
|
+
"--record-runtime=MODE",
|
337
|
+
"\n Record test runtime:\n" <<
|
338
|
+
" simple = write to disk at --runtime-log)\n" <<
|
339
|
+
" amend = write from multiple remote workers via http://github.com/grosser/amend, needs TRAVIS_REPO_SLUG & TRAVIS_BUILD_NUMBER",
|
340
|
+
String
|
341
|
+
],
|
342
|
+
[:runtime_log, "--runtime-log=FILE", "File to store runtime log in or runtime.log", String],
|
343
|
+
[:group, "--group=NUM", "What group this is (use with --groups / starts at 1)", Integer],
|
344
|
+
[:groups, "--groups=NUM", "How many groups there are in total (use with --group)", Integer],
|
345
|
+
[:version, "--version", "Show version"],
|
346
|
+
[:help, "--help", "Show help"]
|
347
|
+
]
|
348
|
+
|
349
|
+
options = arguments.each_with_object({}) do |(setting, flag, _, type), all|
|
350
|
+
all[setting] = delete_argv(flag.split('=', 2)[0], argv, type: type)
|
351
|
+
end
|
352
|
+
|
353
|
+
# show version
|
354
|
+
if options.fetch(:version)
|
355
|
+
puts VERSION
|
356
|
+
exit 0
|
357
|
+
end
|
358
|
+
|
359
|
+
# # show help
|
360
|
+
if options[:help]
|
361
|
+
parser = OptionParser.new("forking-test-runner folder [options]", 32, '') do |opts|
|
362
|
+
arguments.each do |_, flag, desc, type|
|
363
|
+
opts.on(flag, desc, type)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
puts parser
|
367
|
+
exit 0
|
368
|
+
end
|
369
|
+
|
370
|
+
# check if we can use merge_coverage
|
371
|
+
if options.fetch(:merge_coverage)
|
372
|
+
abort "merge_coverage does not work on ruby prior to 2.3" if RUBY_VERSION < "2.3.0"
|
373
|
+
require 'coverage'
|
374
|
+
klass = (class << Coverage; self; end)
|
375
|
+
klass.prepend CoverageCapture
|
376
|
+
end
|
377
|
+
|
378
|
+
# all remaining non-flag options until the next flag must be tests
|
379
|
+
next_flag = argv.index { |arg| arg.start_with?("-") } || argv.size
|
380
|
+
tests = argv.slice!(0, next_flag)
|
381
|
+
abort "No tests or folders found in arguments" if tests.empty?
|
382
|
+
tests.each { |t| abort "Unable to find #{t}" unless File.exist?(t) }
|
383
|
+
|
384
|
+
[options, tests]
|
385
|
+
end
|
386
|
+
|
387
|
+
def delete_argv(name, argv, type: nil)
|
388
|
+
return unless index = argv.index(name)
|
389
|
+
argv.delete_at(index)
|
390
|
+
if type
|
391
|
+
found = argv.delete_at(index) || raise("Missing argument for #{name}")
|
392
|
+
send(type.name, found) # case found
|
393
|
+
else
|
394
|
+
true
|
395
|
+
end
|
396
|
+
end
|
345
397
|
end
|
346
398
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forking_test_runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parallel_tests
|