turbo_tests2 3.1.8 → 3.1.10
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +32 -3
- data/README.md +1 -1
- data/lib/turbo_tests/cli.rb +1 -1
- data/lib/turbo_tests/runner.rb +105 -11
- data/lib/turbo_tests/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1897469552c29056b84010fd5991b4465c76c41e1a66c6c1381dcf3ac88af695
|
|
4
|
+
data.tar.gz: cdbeee85dd4055a61a4202f721b0f394395bd91db75e5994d4e80590f37ddbe7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef33ca0fe4ebcc40e26195844a5d2a2cefa62c677f38e129b2b2fa407c6a8ecb904837ee4d2f3960e1edea7b03d289e4c12b6b619eb76970ea39fb992c920e8e
|
|
7
|
+
data.tar.gz: 83893ce9174430d692795cc45213c85bfcb159d35401279df0692b4072af6a54339ed9a79c533b191be6c2171cce51b0b8f5522cdaa85ce0e530a3d2545b32a8
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -28,11 +28,36 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
28
28
|
|
|
29
29
|
### Fixed
|
|
30
30
|
|
|
31
|
+
### Security
|
|
32
|
+
|
|
33
|
+
## [3.1.10] - 2026-07-15
|
|
34
|
+
|
|
35
|
+
- TAG: [v3.1.10][3.1.10t]
|
|
36
|
+
- COVERAGE: 97.65% -- 706/723 lines in 10 files
|
|
37
|
+
- BRANCH COVERAGE: 88.95% -- 169/190 branches in 10 files
|
|
38
|
+
- 36.67% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- No-argument runs now use RSpec configuration for file discovery, including
|
|
43
|
+
`.rspec` `--pattern` settings, instead of assuming a top-level `spec/`
|
|
44
|
+
directory.
|
|
45
|
+
|
|
46
|
+
## [3.1.9] - 2026-07-14
|
|
47
|
+
|
|
48
|
+
- TAG: [v3.1.9][3.1.9t]
|
|
49
|
+
- COVERAGE: 97.60% -- 692/709 lines in 10 files
|
|
50
|
+
- BRANCH COVERAGE: 89.13% -- 164/184 branches in 10 files
|
|
51
|
+
- 37.08% documented
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- Buffered non-RSpec worker stdout/stderr so successful parallel runs no longer
|
|
56
|
+
leak interleaved coverage formatter output, while still reporting a single
|
|
57
|
+
concise coverage summary.
|
|
31
58
|
- Prevented invalid UTF-8 bytes in worker output from crashing the parent
|
|
32
59
|
runner on JRuby after the underlying RSpec examples pass.
|
|
33
60
|
|
|
34
|
-
### Security
|
|
35
|
-
|
|
36
61
|
## [3.1.8] - 2026-07-14
|
|
37
62
|
|
|
38
63
|
- TAG: [v3.1.8][3.1.8t]
|
|
@@ -223,7 +248,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
223
248
|
|
|
224
249
|
- Initial release
|
|
225
250
|
|
|
226
|
-
[Unreleased]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.
|
|
251
|
+
[Unreleased]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.10...HEAD
|
|
252
|
+
[3.1.10]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.9...v3.1.10
|
|
253
|
+
[3.1.10t]: https://github.com/galtzo-floss/turbo_tests2/releases/tag/v3.1.10
|
|
254
|
+
[3.1.9]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.8...v3.1.9
|
|
255
|
+
[3.1.9t]: https://github.com/galtzo-floss/turbo_tests2/releases/tag/v3.1.9
|
|
227
256
|
[3.1.8]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.7...v3.1.8
|
|
228
257
|
[3.1.8t]: https://github.com/galtzo-floss/turbo_tests2/releases/tag/v3.1.8
|
|
229
258
|
[3.1.7]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.6...v3.1.7
|
data/README.md
CHANGED
|
@@ -666,7 +666,7 @@ Thanks for RTFM. ☺️
|
|
|
666
666
|
[📌gitmoji]: https://gitmoji.dev
|
|
667
667
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
668
668
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
669
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.
|
|
669
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.723-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
670
670
|
[🔐security]: https://github.com/galtzo-floss/turbo_tests2/blob/main/SECURITY.md
|
|
671
671
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
672
672
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/lib/turbo_tests/cli.rb
CHANGED
data/lib/turbo_tests/runner.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
4
|
require "parallel_tests/rspec/runner"
|
|
5
|
+
require "rspec/core"
|
|
5
6
|
require "tempfile"
|
|
6
7
|
|
|
7
8
|
require_relative "../utils/hash_extension"
|
|
@@ -23,7 +24,8 @@ module TurboTests
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def run(opts = {})
|
|
26
|
-
|
|
27
|
+
default_file_discovery = !opts.key?(:files) || opts[:files].nil?
|
|
28
|
+
files = default_file_discovery ? rspec_configured_files_to_run : opts[:files]
|
|
27
29
|
formatters = opts[:formatters]
|
|
28
30
|
tags = opts[:tags]
|
|
29
31
|
parallel_options = opts[:parallel_options] || {}
|
|
@@ -41,7 +43,7 @@ module TurboTests
|
|
|
41
43
|
print_failed_group = opts.fetch(:print_failed_group, false)
|
|
42
44
|
nice = opts.fetch(:nice, false)
|
|
43
45
|
|
|
44
|
-
use_runtime_info =
|
|
46
|
+
use_runtime_info = default_file_discovery
|
|
45
47
|
|
|
46
48
|
if example_status_log
|
|
47
49
|
runtime_log = runtime_log_from_example_status(example_status_log)
|
|
@@ -103,6 +105,16 @@ module TurboTests
|
|
|
103
105
|
def generate_seed
|
|
104
106
|
(Random.new_seed % 65_535).to_s
|
|
105
107
|
end
|
|
108
|
+
|
|
109
|
+
def rspec_configured_files_to_run
|
|
110
|
+
configuration = RSpec::Core::Configuration.new
|
|
111
|
+
RSpec::Core::ConfigurationOptions.new([]).configure(configuration)
|
|
112
|
+
root = "#{Dir.pwd}/"
|
|
113
|
+
configuration.files_to_run.map do |path|
|
|
114
|
+
path = path.to_s
|
|
115
|
+
path.start_with?(root) ? path.delete_prefix(root) : path
|
|
116
|
+
end
|
|
117
|
+
end
|
|
106
118
|
end
|
|
107
119
|
|
|
108
120
|
def initialize(**opts)
|
|
@@ -135,16 +147,25 @@ module TurboTests
|
|
|
135
147
|
@threads = []
|
|
136
148
|
@wait_threads = []
|
|
137
149
|
@exited_process_ids = []
|
|
150
|
+
@worker_output = Hash.new { |hash, process_id| hash[process_id] = {stdout: +"", stderr: +""} }
|
|
151
|
+
@worker_output_mutex = Mutex.new
|
|
138
152
|
@error = false
|
|
139
153
|
@print_failed_group = opts[:print_failed_group]
|
|
140
154
|
end
|
|
141
155
|
|
|
142
156
|
def run
|
|
157
|
+
tests_with_size = ParallelTests::RSpec::Runner.tests_with_size(@files, {})
|
|
143
158
|
@num_processes = [
|
|
144
159
|
ParallelTests.determine_number_of_processes(@count),
|
|
145
|
-
|
|
160
|
+
tests_with_size.size
|
|
146
161
|
].min
|
|
147
162
|
|
|
163
|
+
if @num_processes.zero?
|
|
164
|
+
@tests_in_groups = []
|
|
165
|
+
@reporter.report([]) { |_reporter| }
|
|
166
|
+
return 0
|
|
167
|
+
end
|
|
168
|
+
|
|
148
169
|
tests_in_groups =
|
|
149
170
|
ParallelTests::RSpec::Runner.tests_in_groups(
|
|
150
171
|
@files,
|
|
@@ -158,6 +179,9 @@ module TurboTests
|
|
|
158
179
|
}
|
|
159
180
|
|
|
160
181
|
ParallelTests.with_pid_file do
|
|
182
|
+
exit_status = nil
|
|
183
|
+
report_coverage = false
|
|
184
|
+
|
|
161
185
|
@reporter.report(tests_in_groups) do |_reporter|
|
|
162
186
|
old_signal = Signal.trap(:INT) { handle_interrupt }
|
|
163
187
|
|
|
@@ -174,13 +198,20 @@ module TurboTests
|
|
|
174
198
|
|
|
175
199
|
Signal.trap(:INT, old_signal)
|
|
176
200
|
|
|
177
|
-
|
|
178
|
-
|
|
201
|
+
statuses = @wait_threads.map(&:value)
|
|
202
|
+
|
|
203
|
+
if @reporter.failed_examples.empty? && statuses.all?(&:success?)
|
|
204
|
+
report_coverage = true
|
|
205
|
+
exit_status = 0
|
|
179
206
|
else
|
|
207
|
+
flush_worker_output
|
|
180
208
|
# From https://github.com/galtzo-floss/turbo_tests2/pull/20/
|
|
181
|
-
|
|
209
|
+
exit_status = statuses.map(&:exitstatus).max
|
|
182
210
|
end
|
|
183
211
|
end
|
|
212
|
+
|
|
213
|
+
flush_coverage_summary if report_coverage
|
|
214
|
+
exit_status
|
|
184
215
|
end
|
|
185
216
|
end
|
|
186
217
|
|
|
@@ -302,7 +333,7 @@ module TurboTests
|
|
|
302
333
|
result = line.b.split(output_id)
|
|
303
334
|
|
|
304
335
|
initial = result.shift
|
|
305
|
-
|
|
336
|
+
append_worker_output(process_id, :stdout, initial) unless initial.empty?
|
|
306
337
|
|
|
307
338
|
message = result.shift
|
|
308
339
|
next unless message
|
|
@@ -322,14 +353,14 @@ module TurboTests
|
|
|
322
353
|
# rubocop:enable ThreadSafety/NewThread
|
|
323
354
|
@threads << stdout_thread
|
|
324
355
|
|
|
325
|
-
stderr_thread = start_copy_thread(stderr,
|
|
356
|
+
stderr_thread = start_copy_thread(stderr, process_id, :stderr)
|
|
326
357
|
@threads << stderr_thread
|
|
327
358
|
|
|
328
359
|
# rubocop:disable ThreadSafety/NewThread
|
|
329
360
|
@threads << Thread.new do
|
|
330
361
|
begin
|
|
331
362
|
status = wait_thr.value
|
|
332
|
-
@messages << {type: "error"} unless status.success?
|
|
363
|
+
@messages << {type: "error", process_id: process_id} unless status.success?
|
|
333
364
|
@messages << {type: "exit", process_id: process_id}
|
|
334
365
|
ensure
|
|
335
366
|
stop_reader_thread(stdout_thread, stdout)
|
|
@@ -355,7 +386,7 @@ module TurboTests
|
|
|
355
386
|
ParallelTests::Pids.new(pid_file_path).delete(pid) if pid && pid_file_path
|
|
356
387
|
end
|
|
357
388
|
|
|
358
|
-
def start_copy_thread(src,
|
|
389
|
+
def start_copy_thread(src, process_id, stream)
|
|
359
390
|
# rubocop:disable ThreadSafety/NewThread
|
|
360
391
|
Thread.new do
|
|
361
392
|
# rubocop:enable ThreadSafety/NewThread
|
|
@@ -368,10 +399,73 @@ module TurboTests
|
|
|
368
399
|
rescue IOError
|
|
369
400
|
break
|
|
370
401
|
else
|
|
371
|
-
|
|
402
|
+
append_worker_output(process_id, stream, msg)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def append_worker_output(process_id, stream, msg)
|
|
409
|
+
return if msg.empty?
|
|
410
|
+
|
|
411
|
+
msg = msg.dup.force_encoding(Encoding::UTF_8).scrub
|
|
412
|
+
@worker_output_mutex.synchronize do
|
|
413
|
+
@worker_output[process_id][stream] << msg
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
io = (stream == :stderr) ? $stderr : $stdout
|
|
417
|
+
io.write(msg) if @verbose
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def flush_worker_output
|
|
421
|
+
output_by_process = @worker_output_mutex.synchronize do
|
|
422
|
+
@worker_output.transform_values(&:dup)
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
output_by_process.each do |process_id, streams|
|
|
426
|
+
streams.each do |stream, output|
|
|
427
|
+
next if output.empty?
|
|
428
|
+
|
|
429
|
+
io = (stream == :stderr) ? $stderr : $stdout
|
|
430
|
+
io.puts
|
|
431
|
+
io.puts("TurboTests worker #{process_id} #{stream}:")
|
|
432
|
+
io.write(output)
|
|
433
|
+
io.puts unless output.end_with?("\n")
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def flush_coverage_summary
|
|
439
|
+
line_coverage = nil
|
|
440
|
+
branch_coverage = nil
|
|
441
|
+
@worker_output_mutex.synchronize do
|
|
442
|
+
@worker_output.each_value do |streams|
|
|
443
|
+
streams.each_value do |output|
|
|
444
|
+
output.each_line do |line|
|
|
445
|
+
stripped = line.strip
|
|
446
|
+
line_coverage = coverage_line("Line", stripped, line_coverage)
|
|
447
|
+
branch_coverage = coverage_line("Branch", stripped, branch_coverage)
|
|
448
|
+
end
|
|
372
449
|
end
|
|
373
450
|
end
|
|
374
451
|
end
|
|
452
|
+
|
|
453
|
+
return unless line_coverage || branch_coverage
|
|
454
|
+
|
|
455
|
+
puts
|
|
456
|
+
puts("Coverage:")
|
|
457
|
+
puts(line_coverage) if line_coverage
|
|
458
|
+
puts(branch_coverage) if branch_coverage
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def coverage_line(kind, line, current)
|
|
462
|
+
return line if line.start_with?("#{kind} Coverage:")
|
|
463
|
+
return current if current&.start_with?("#{kind} Coverage:")
|
|
464
|
+
|
|
465
|
+
match = line.match(/\A#{kind} coverage:\s*(\d+)\s*\/\s*(\d+)\s*\(([^)]+)\)\z/i)
|
|
466
|
+
return current unless match
|
|
467
|
+
|
|
468
|
+
"#{kind} Coverage: #{match[3]} (#{match[1]} / #{match[2]})"
|
|
375
469
|
end
|
|
376
470
|
|
|
377
471
|
def stop_reader_thread(thread, io)
|
data/lib/turbo_tests/version.rb
CHANGED
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: turbo_tests2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.1.
|
|
4
|
+
version: 3.1.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Illia
|
|
@@ -312,10 +312,10 @@ licenses:
|
|
|
312
312
|
- MIT
|
|
313
313
|
metadata:
|
|
314
314
|
homepage_uri: https://turbo-tests2.galtzo.com
|
|
315
|
-
source_code_uri: https://github.com/galtzo-floss/turbo_tests2/tree/v3.1.
|
|
316
|
-
changelog_uri: https://github.com/galtzo-floss/turbo_tests2/blob/v3.1.
|
|
315
|
+
source_code_uri: https://github.com/galtzo-floss/turbo_tests2/tree/v3.1.10
|
|
316
|
+
changelog_uri: https://github.com/galtzo-floss/turbo_tests2/blob/v3.1.10/CHANGELOG.md
|
|
317
317
|
bug_tracker_uri: https://github.com/galtzo-floss/turbo_tests2/issues
|
|
318
|
-
documentation_uri: https://www.rubydoc.info/gems/turbo_tests2/3.1.
|
|
318
|
+
documentation_uri: https://www.rubydoc.info/gems/turbo_tests2/3.1.10
|
|
319
319
|
funding_uri: https://github.com/sponsors/pboling
|
|
320
320
|
wiki_uri: https://github.com/galtzo-floss/turbo_tests2/wiki
|
|
321
321
|
news_uri: https://www.railsbling.com/tags/turbo_tests2
|
metadata.gz.sig
CHANGED
|
Binary file
|