forking_test_runner 0.8.0 → 0.9.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.
- 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
|