turbo_tests2 3.1.0 → 3.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d311bffe032ad5025cceb6e487460d7e1c0d1e87cc07134eafb4f41bdc63d515
4
- data.tar.gz: 0a07a421cad5fadb52d3c417fd0626f80159e4757d8a393fe3ac4912c343dba5
3
+ metadata.gz: 60ede4cd429a0a25151b01cd9f0bcddbafb8002e048e55b4aef4dbb47d5fa5d8
4
+ data.tar.gz: 7b64b241458249d78ff9b632ecc7679fc5e27620f8f36aea0d1f4170236c9cd9
5
5
  SHA512:
6
- metadata.gz: f9745db1b03fd8ef015807cab9518079449ffa6d033d898141eec7f815edbd1dcb1a95f9bf7fd361d6e429d8573fa0668ef7b4ca295c2ad116d72bbb63d35c53
7
- data.tar.gz: fe28b347bae32babcdfc80fcf1523b43f54c17dd3726eaeae5e6c4101127685a967e80ef4789c13b47bb16e682282ab5318f9a89b6cce0a16984235128143450
6
+ metadata.gz: a24112e4b8d4280f937aa5b9617cfa6367c4aef082750e819ac76a12681ab596ad8bf2f72c5701833f4efe29e33de89a4eed316422e4b341fb781f2addba3ef5
7
+ data.tar.gz: 34da19c8fbeee18e9541c488c34c8045f8a9ea5f2628b679339c6cbb0160e492fa7b9b21231ca6ecb30685826c27206788d58c6512a4ffc18e7f34728ca625df
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -28,8 +28,30 @@ Please file a bug if you notice a violation of semantic versioning.
28
28
 
29
29
  ### Fixed
30
30
 
31
+ - Worker PID cleanup now uses the `parallel_tests` pid file path captured when the subprocess starts, avoiding JRuby failures after the pid-file environment is restored.
32
+
31
33
  ### Security
32
34
 
35
+ ## [3.1.1] - 2026-06-02
36
+
37
+ - TAG: [v3.1.1][3.1.1t]
38
+ - COVERAGE: 94.63% -- 634/670 lines in 16 files
39
+ - BRANCH COVERAGE: 78.17% -- 111/142 branches in 16 files
40
+ - 36.78% documented
41
+
42
+ ### Fixed
43
+
44
+ - The CLI now honors documented `turbo_tests2:setup` and `turbo_tests2:cleanup`
45
+ Rake hooks, while still falling back to legacy `turbo_tests:*` hooks.
46
+ - Worker processes now receive the full `parallel_tests` environment metadata, so SimpleCov
47
+ defers minimum coverage enforcement to the combined final result instead of checking each
48
+ shard independently.
49
+
50
+ - Restored Ruby 2.4 compatibility for worker wait-thread cleanup.
51
+ - The coverage workflow now runs `kettle-test` through direct RSpec execution,
52
+ so hard coverage thresholds are checked against the complete suite result
53
+ while other gems can still use `turbo_tests2` under `kettle-test`.
54
+
33
55
  ## [3.1.0] - 2026-05-28
34
56
 
35
57
  - TAG: [v3.1.0][3.1.0t]
@@ -92,7 +114,9 @@ Please file a bug if you notice a violation of semantic versioning.
92
114
 
93
115
  - Initial release
94
116
 
95
- [Unreleased]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.0...HEAD
117
+ [Unreleased]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.1...HEAD
118
+ [3.1.1]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.1.0...v3.1.1
119
+ [3.1.1t]: https://github.com/galtzo-floss/turbo_tests2/releases/tag/v3.1.1
96
120
  [3.1.0]: https://github.com/galtzo-floss/turbo_tests2/compare/v3.0.0...v3.1.0
97
121
  [3.1.0t]: https://github.com/galtzo-floss/turbo_tests2/releases/tag/v3.1.0
98
122
  [3.0.0]: https://github.com/galtzo-floss/turbo_tests2/compare/7d4064e5b8acc2f53929fccf7be3eb63f8a9f140...v3.0.0
data/CONTRIBUTING.md CHANGED
@@ -102,13 +102,29 @@ Git hooks and commit message helpers (exe/kettle-commit-msg)
102
102
  - GIT_HOOK_FOOTER_SENTINEL: Required when footer append is enabled — a unique first-line sentinel to prevent duplicates
103
103
  - GIT_HOOK_FOOTER_APPEND_DEBUG: Extra debug output in the footer template (true/false)
104
104
 
105
+ Git diff driver setup
106
+ - Local setup writes repository `.gitattributes` entries and local Git `diff.smorg-*` command config so this checkout uses StructuredMerge semantic diffs.
107
+ - Global setup registers `diff.smorg-*` commands once in the user Git config; use it when you work across several StructuredMerge-enabled repositories.
108
+ - Include-file setup writes `.git/smorg/config` and includes it from local Git config, keeping command registrations out of the repository files.
109
+ - Git hosting forges generally ignore external diff drivers, so pull request views may still show raw textual diffs even when local `git diff` uses semantic drivers.
110
+
111
+ ```console
112
+ K_JEM_TEMPLATING=true bundle exec kettle-jem install
113
+ ```
114
+
115
+ Troubleshooting Git diffs
116
+ - Use `git diff --no-ext-diff` to compare against Git's built-in diff output.
117
+ - Use `git diff --no-textconv` when a textconv projection obscures the raw file bytes you need to inspect.
118
+ - If Git reports a missing `smorg-*` executable, rerun `bundle install` and the setup command above, then check `git config --local --get-regexp '^diff\.smorg-'`.
119
+ - To remove managed local entries, run `K_JEM_TEMPLATING=true bundle exec kettle-jem install --undo`; remove global command registrations with `git config --global --unset-all diff.smorg-ruby.command`.
120
+
105
121
  For a quick starting point, this repository’s `mise.toml` defines the shared defaults, and `.env.local` can override them locally. Copy `.env.local.example` to `.env.local`, use `KEY=value` lines, and either activate `mise` in your shell or run commands through `mise exec -C /path/to/project -- ...`.
106
122
 
107
123
  ## Appraisals
108
124
 
109
125
  From time to time the [appraisal2][🚎appraisal2] gemfiles in `gemfiles/` will need to be updated.
110
126
  Generated appraisal and CI workflow floors are controlled by `ruby.test_minimum`
111
- in `.kettle-jem.yml`; this project was templated with `ruby.test_minimum: 2.4`.
127
+ in `.structuredmerge/kettle-jem.yml`; this project was templated with `ruby.test_minimum: 2.4`.
112
128
  That value describes the lowest Ruby version expected to run the test/development
113
129
  toolchain, and it may be higher than the gemspec runtime floor.
114
130
 
data/LICENSE.md CHANGED
@@ -18,5 +18,5 @@ Copyright (c) 2023 mrudzki
18
18
  Copyright (c) 2023-2024 Sebastien Savater
19
19
  Copyright (c) 2024 David Rodriguez
20
20
  Copyright (c) 2024 Hiroshi SHIBATA
21
- Copyright (c) 2025 Gareth Jones
21
+ Copyright (c) 2025-2026 Gareth Jones
22
22
  Copyright (c) 2025-2026 Peter H. Boling
data/README.md CHANGED
@@ -1,17 +1,10 @@
1
- [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-floss-i]][🖼️galtzo-floss] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![turbo_tests2 Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-floss-turbo_tests2-i]][🖼️galtzo-floss-turbo_tests2]
2
-
3
- [🖼️galtzo-floss-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
4
- [🖼️galtzo-floss]: https://discord.gg/3qme4XHNKN
5
- [🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg
6
- [🖼️ruby-lang]: https://www.ruby-lang.org/
7
- [🖼️galtzo-floss-turbo_tests2-i]: https://logos.galtzo.com/assets/images/galtzo-floss/turbo_tests2/avatar-192px.svg
8
- [🖼️galtzo-floss-turbo_tests2]: https://github.com/galtzo-floss/turbo_tests2
1
+ <a href="https://github.com/galtzo-floss"><img alt="galtzo-floss Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px.svg" width="12%" align="right"/></a> <a href="https://github.com/galtzo-floss/turbo_tests2"><img alt="turbo_tests2 Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/turbo_tests2/avatar-128px.svg" width="12%" align="right"/></a>
9
2
 
10
3
  # 🚀 TurboTests
11
4
 
12
5
  [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
13
6
 
14
- `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-floss], as I may have missed the [discord notification][🖼️galtzo-floss].
7
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][✉️discord-invite], as I may have missed the [discord notification][✉️discord-invite].
15
8
 
16
9
  ---
17
10
 
@@ -26,7 +19,7 @@ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-ta
26
19
 
27
20
  </details>
28
21
 
29
- ## 🌻 Synopsis
22
+ ## 🌻 Synopsis <a href="https://discord.gg/3qme4XHNKN"><img alt="Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px.svg" width="8%" align="right"/></a> <a href="https://ruby-toolbox.com"><img alt="ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5" src="https://logos.galtzo.com/assets/images/ruby-lang/avatar-128px.svg" width="8%" align="right"/></a>
30
23
 
31
24
  | Hard Fork Note |
32
25
  |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -98,8 +91,6 @@ not practical for the current toolchain.
98
91
  |------------------------------------------------|--------------------------------------------------------|
99
92
  | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
100
93
 
101
-
102
-
103
94
  ### Federated DVCS
104
95
 
105
96
  <details markdown="1">
@@ -217,12 +208,12 @@ bundle exec turbo_tests2 -r fuubar -f Fuubar spec/whatever
217
208
 
218
209
  ### Rake Hooks
219
210
 
220
- If Rake is present, the CLI will invoke the tasks `turbo_tests:setup` and `turbo_tests:cleanup` before and after running
211
+ If Rake is present, the CLI will invoke the tasks `turbo_tests2:setup` and `turbo_tests2:cleanup` before and after running
221
212
  the test suite. These can be used to do work that should only happen once, such as removing files or collating coverage:
222
213
 
223
214
  ```ruby
224
215
  # lib/tasks/turbo_tests.rake
225
- namespace :turbo_tests do
216
+ namespace :turbo_tests2 do
226
217
  task setup: :environment do
227
218
  # precompile assets once, to avoid doing it per each process
228
219
  Rake::Tasks["assets:precompile"]
@@ -256,8 +247,8 @@ SimpleCov.start("rails") do
256
247
  formatter SimpleCov::Formatter::SimpleFormatter
257
248
  end
258
249
 
259
- # lib/tasks/turbo_tests.rake
260
- namespace :turbo_tests do
250
+ # lib/tasks/turbo_tests2.rake
251
+ namespace :turbo_tests2 do
261
252
  task setup: :environment do
262
253
  # remove any existing coverage files to avoid false reporting
263
254
  FileUtils.rm_rf("coverage/turbo_tests")
@@ -439,7 +430,7 @@ See [LICENSE.md][📄license] for the official copyright notice.
439
430
  - Copyright (c) 2023-2024 Sebastien Savater
440
431
  - Copyright (c) 2024 David Rodriguez
441
432
  - Copyright (c) 2024 Hiroshi SHIBATA
442
- - Copyright (c) 2025 Gareth Jones
433
+ - Copyright (c) 2025-2026 Gareth Jones
443
434
  - Copyright (c) 2025-2026 Peter H. Boling
444
435
 
445
436
  </details>
@@ -463,6 +454,8 @@ To say "thanks!" ☝️ Join the Discord or 👇️ send money.
463
454
 
464
455
  ### Please give the project a star ⭐ ♥.
465
456
 
457
+ Many parts of this project are actively managed by a [kettle-jem](https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/kettle-jem) smart template utilizing [StructuredMerge.org](https://structuredmerge.org) merge contracts.
458
+
466
459
  Thanks for RTFM. ☺️
467
460
 
468
461
  [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
@@ -651,7 +644,7 @@ Thanks for RTFM. ☺️
651
644
  [📌gitmoji]: https://gitmoji.dev
652
645
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
653
646
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
654
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.641-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
647
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.670-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
655
648
  [🔐security]: https://github.com/galtzo-floss/turbo_tests2/blob/main/SECURITY.md
656
649
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
657
650
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -677,9 +670,9 @@ Thanks for RTFM. ☺️
677
670
  | Field | Value |
678
671
  |---|---|
679
672
  | Package | turbo_tests2 |
680
- | Description | 🚀 `turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests` and `grosser/parallel_tests` with incremental summarized output. Source code of `turbo_test2` gem is based on Discourse and Rubygems work in this area (see README file of the source repository). |
673
+ | Description | 🚀 turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests` and `grosser/parallel_tests` with incremental summarized output. Source code of `turbo_test2` gem is based on Discourse and Rubygems work in this area (see README.md). |
681
674
  | Homepage | https://github.com/galtzo-floss/turbo_tests2 |
682
- | Source | https://github.com/galtzo-floss/turbo_tests2/tree/v3.0.0 |
675
+ | Source | https://github.com/galtzo-floss/turbo_tests2/tree/v3.1.1 |
683
676
  | License | `MIT` |
684
677
  | Funding | https://github.com/sponsors/pboling, https://issuehunt.io/u/pboling, https://ko-fi.com/pboling, https://liberapay.com/pboling/donate, https://opencollective.com/galtzo-floss, https://patreon.com/galtzo, https://polar.sh/pboling, https://thanks.dev/u/gh/pboling, https://tidelift.com/funding/github/rubygems/turbo_tests2, https://www.buymeacoffee.com/pboling |
685
678
  <!-- kettle-jem:metadata:end -->
@@ -52,11 +52,11 @@ module TurboTests
52
52
  opts.on(
53
53
  "-f",
54
54
  "--format FORMATTER",
55
- "Choose a formatter. Available formatters: progress (p), documentation (d). Default: progress",
55
+ "Choose a formatter. Available formatters: progress (p), documentation (d). Default: progress"
56
56
  ) do |name|
57
57
  formatters << {
58
58
  name: name,
59
- outputs: [],
59
+ outputs: []
60
60
  }
61
61
  end
62
62
 
@@ -68,7 +68,7 @@ module TurboTests
68
68
  if formatters.empty?
69
69
  formatters << {
70
70
  name: "progress",
71
- outputs: [],
71
+ outputs: []
72
72
  }
73
73
  end
74
74
  formatters.last[:outputs] << filename
@@ -89,7 +89,7 @@ module TurboTests
89
89
  opts.on("--fail-fast=[N]") do |n|
90
90
  n = begin
91
91
  Integer(n)
92
- rescue StandardError
92
+ rescue
93
93
  nil
94
94
  end
95
95
  fail_fast = (n.nil? || n < 1) ? 1 : n
@@ -121,7 +121,7 @@ module TurboTests
121
121
  if formatters.empty?
122
122
  formatters << {
123
123
  name: "progress",
124
- outputs: [],
124
+ outputs: []
125
125
  }
126
126
  end
127
127
 
@@ -131,7 +131,7 @@ module TurboTests
131
131
 
132
132
  load_rake
133
133
 
134
- invoke_rake_task("turbo_tests:setup")
134
+ invoke_rake_hook("setup")
135
135
 
136
136
  files = @argv.empty? ? ["spec"] : @argv
137
137
  parallel_options = {}
@@ -148,10 +148,10 @@ module TurboTests
148
148
  seed: seed,
149
149
  nice: nice,
150
150
  print_failed_group: print_failed_group,
151
- parallel_options: parallel_options,
151
+ parallel_options: parallel_options
152
152
  )
153
153
 
154
- invoke_rake_task("turbo_tests:cleanup")
154
+ invoke_rake_hook("cleanup")
155
155
 
156
156
  # From https://github.com/galtzo-floss/turbo_tests2/pull/20/
157
157
  exit(exitstatus)
@@ -187,7 +187,7 @@ module TurboTests
187
187
  pids = (1..processes).map do |process_id|
188
188
  env = {
189
189
  "TEST_ENV_NUMBER" => process_id.to_s,
190
- "PARALLEL_TEST_GROUPS" => processes.to_s,
190
+ "PARALLEL_TEST_GROUPS" => processes.to_s
191
191
  }
192
192
  Process.spawn(env, *args)
193
193
  end
@@ -243,7 +243,7 @@ module TurboTests
243
243
  def shim_usage(command = nil)
244
244
  lines = [
245
245
  "Usage: turbo_tests2 shim install [--path PATH]",
246
- " turbo_tests2 shim remove [--path PATH]",
246
+ " turbo_tests2 shim remove [--path PATH]"
247
247
  ]
248
248
  lines << "Unknown shim command: #{command}" if command && !%w[install remove].include?(command)
249
249
  lines.join("\n")
@@ -270,5 +270,14 @@ module TurboTests
270
270
 
271
271
  Rake::Task[name].invoke
272
272
  end
273
+
274
+ def invoke_rake_hook(name)
275
+ current_task = "turbo_tests2:#{name}"
276
+ legacy_task = "turbo_tests:#{name}"
277
+
278
+ return invoke_rake_task(current_task) if defined?(Rake) && Rake::Task.task_defined?(current_task)
279
+
280
+ invoke_rake_task(legacy_task)
281
+ end
273
282
  end
274
283
  end
@@ -23,7 +23,7 @@ module TurboTests
23
23
  INTERNAL_BACKTRACE_PATTERNS = [
24
24
  %r{/bin/turbo_tests2\b},
25
25
  %r{/exe/turbo_tests2\b},
26
- %r{/lib/turbo_tests(?:\.rb|/)},
26
+ %r{/lib/turbo_tests(?:\.rb|/)}
27
27
  ].freeze
28
28
 
29
29
  RSpec::Core::Formatters.register(
@@ -38,7 +38,7 @@ module TurboTests
38
38
  :message,
39
39
  :seed,
40
40
  :deprecation,
41
- :dump_profile,
41
+ :dump_profile
42
42
  )
43
43
 
44
44
  attr_reader :output
@@ -50,76 +50,76 @@ module TurboTests
50
50
  def start(notification)
51
51
  output_row(
52
52
  type: :load_summary,
53
- summary: load_summary_to_json(notification),
53
+ summary: load_summary_to_json(notification)
54
54
  )
55
55
  end
56
56
 
57
57
  def example_group_started(notification)
58
58
  output_row(
59
59
  type: :group_started,
60
- group: group_to_json(notification),
60
+ group: group_to_json(notification)
61
61
  )
62
62
  end
63
63
 
64
64
  def example_group_finished(notification)
65
65
  output_row(
66
66
  type: :group_finished,
67
- group: group_to_json(notification),
67
+ group: group_to_json(notification)
68
68
  )
69
69
  end
70
70
 
71
71
  def example_passed(notification)
72
72
  output_row(
73
73
  type: :example_passed,
74
- example: example_to_json(notification.example),
74
+ example: example_to_json(notification.example)
75
75
  )
76
76
  end
77
77
 
78
78
  def example_pending(notification)
79
79
  output_row(
80
80
  type: :example_pending,
81
- example: example_to_json(notification.example),
81
+ example: example_to_json(notification.example)
82
82
  )
83
83
  end
84
84
 
85
85
  def example_failed(notification)
86
86
  output_row(
87
87
  type: :example_failed,
88
- example: example_to_json(notification.example),
88
+ example: example_to_json(notification.example)
89
89
  )
90
90
  end
91
91
 
92
92
  def seed(notification)
93
93
  output_row(
94
94
  type: :seed,
95
- seed: notification.seed,
95
+ seed: notification.seed
96
96
  )
97
97
  end
98
98
 
99
99
  def close(_notification)
100
100
  output_row(
101
- type: :close,
101
+ type: :close
102
102
  )
103
103
  end
104
104
 
105
105
  def message(notification)
106
106
  output_row(
107
107
  type: :message,
108
- message: notification.message,
108
+ message: notification.message
109
109
  )
110
110
  end
111
111
 
112
112
  def deprecation(notification)
113
113
  output_row(
114
114
  type: :deprecation,
115
- deprecation: deprecation_to_json(notification),
115
+ deprecation: deprecation_to_json(notification)
116
116
  )
117
117
  end
118
118
 
119
119
  def dump_profile(notification)
120
120
  output_row(
121
121
  type: :profile,
122
- profile: profile_to_json(notification),
122
+ profile: profile_to_json(notification)
123
123
  )
124
124
  end
125
125
 
@@ -129,7 +129,7 @@ module TurboTests
129
129
  {
130
130
  duration: notification.duration,
131
131
  number_of_examples: notification.number_of_examples,
132
- examples: notification.examples.map { |example| example_to_json(example) },
132
+ examples: notification.examples.map { |example| example_to_json(example) }
133
133
  }
134
134
  end
135
135
 
@@ -138,7 +138,7 @@ module TurboTests
138
138
  deprecated: notification.deprecated,
139
139
  message: notification.message,
140
140
  replacement: notification.replacement,
141
- call_site: notification.call_site,
141
+ call_site: notification.call_site
142
142
  }
143
143
  end
144
144
 
@@ -149,7 +149,7 @@ module TurboTests
149
149
  class_name: exception.class.name.to_s,
150
150
  backtrace: filtered_backtrace(exception.backtrace),
151
151
  message: exception.message,
152
- cause: exception_to_json(exception.cause),
152
+ cause: exception_to_json(exception.cause)
153
153
  }
154
154
  end
155
155
 
@@ -166,14 +166,14 @@ module TurboTests
166
166
  status: result.status,
167
167
  pending_fixed?: result.pending_fixed?,
168
168
  exception: exception_to_json(result.exception || result.pending_exception),
169
- run_time: result.respond_to?(:run_time) ? result.run_time : nil,
169
+ run_time: result.respond_to?(:run_time) ? result.run_time : nil
170
170
  }
171
171
  end
172
172
 
173
173
  def stack_frame_to_json(frame)
174
174
  {
175
175
  shared_group_name: frame.shared_group_name,
176
- inclusion_location: frame.inclusion_location,
176
+ inclusion_location: frame.inclusion_location
177
177
  }
178
178
  end
179
179
 
@@ -188,24 +188,24 @@ module TurboTests
188
188
  example
189
189
  .metadata[:shared_group_inclusion_backtrace]
190
190
  .map { |frame| stack_frame_to_json(frame) },
191
- extra_failure_lines: example.metadata[:extra_failure_lines],
191
+ extra_failure_lines: example.metadata[:extra_failure_lines]
192
192
  },
193
- location_rerun_argument: example.location_rerun_argument,
193
+ location_rerun_argument: example.location_rerun_argument
194
194
  }
195
195
  end
196
196
 
197
197
  def load_summary_to_json(notification)
198
198
  {
199
199
  count: notification.count,
200
- load_time: notification.load_time,
200
+ load_time: notification.load_time
201
201
  }
202
202
  end
203
203
 
204
204
  def group_to_json(notification)
205
205
  {
206
206
  group: {
207
- description: notification.group.description,
208
- },
207
+ description: notification.group.description
208
+ }
209
209
  }
210
210
  end
211
211
 
@@ -75,7 +75,7 @@ module TurboTests
75
75
  delegate_to_formatters(:seed, RSpec::Core::Notifications::SeedNotification.new(@seed, @seed_used))
76
76
  delegate_to_formatters(
77
77
  :start,
78
- RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time),
78
+ RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time)
79
79
  )
80
80
  end
81
81
 
@@ -132,7 +132,7 @@ module TurboTests
132
132
  deprecated: deprecation[:deprecated],
133
133
  message: deprecation[:message],
134
134
  replacement: deprecation[:replacement],
135
- call_site: deprecation[:call_site],
135
+ call_site: deprecation[:call_site]
136
136
  )
137
137
  delegate_to_formatters(:deprecation, notification)
138
138
  end
@@ -143,7 +143,7 @@ module TurboTests
143
143
  profile[:duration],
144
144
  examples,
145
145
  profile[:number_of_examples],
146
- {},
146
+ {}
147
147
  )
148
148
  delegate_to_formatters(:dump_profile, notification)
149
149
  end
@@ -158,14 +158,14 @@ module TurboTests
158
158
  delegate_to_formatters(
159
159
  :dump_pending,
160
160
  RSpec::Core::Notifications::ExamplesNotification.new(
161
- self,
162
- ),
161
+ self
162
+ )
163
163
  )
164
164
  delegate_to_formatters(
165
165
  :dump_failures,
166
166
  RSpec::Core::Notifications::ExamplesNotification.new(
167
- self,
168
- ),
167
+ self
168
+ )
169
169
  )
170
170
  delegate_to_formatters(
171
171
  :dump_summary,
@@ -175,15 +175,15 @@ module TurboTests
175
175
  @failed_examples,
176
176
  @pending_examples,
177
177
  @load_time,
178
- @errors_outside_of_examples_count,
179
- ),
178
+ @errors_outside_of_examples_count
179
+ )
180
180
  )
181
181
  delegate_to_formatters(
182
182
  :seed,
183
183
  RSpec::Core::Notifications::SeedNotification.new(
184
184
  @seed,
185
- @seed_used,
186
- ),
185
+ @seed_used
186
+ )
187
187
  )
188
188
  ensure
189
189
  delegate_to_formatters(:close, RSpec::Core::Notifications::NullNotification)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "json"
4
4
  require "parallel_tests/rspec/runner"
5
+ require "tempfile"
5
6
 
6
7
  require_relative "../utils/hash_extension"
7
8
 
@@ -69,7 +70,7 @@ module TurboTests
69
70
  print_failed_group: print_failed_group,
70
71
  use_runtime_info: use_runtime_info,
71
72
  parallel_options: parallel_options,
72
- nice: nice,
73
+ nice: nice
73
74
  ).run
74
75
  end
75
76
 
@@ -125,42 +126,44 @@ module TurboTests
125
126
  def run
126
127
  @num_processes = [
127
128
  ParallelTests.determine_number_of_processes(@count),
128
- ParallelTests::RSpec::Runner.tests_with_size(@files, {}).size,
129
+ ParallelTests::RSpec::Runner.tests_with_size(@files, {}).size
129
130
  ].min
130
131
 
131
132
  tests_in_groups =
132
133
  ParallelTests::RSpec::Runner.tests_in_groups(
133
134
  @files,
134
135
  @num_processes,
135
- **@parallel_options,
136
+ **@parallel_options
136
137
  )
137
138
  @tests_in_groups = tests_in_groups
138
139
 
139
140
  subprocess_opts = {
140
- record_runtime: @record_runtime,
141
+ record_runtime: @record_runtime
141
142
  }
142
143
 
143
- @reporter.report(tests_in_groups) do |_reporter|
144
- old_signal = Signal.trap(:INT) { handle_interrupt }
144
+ ParallelTests.with_pid_file do
145
+ @reporter.report(tests_in_groups) do |_reporter|
146
+ old_signal = Signal.trap(:INT) { handle_interrupt }
145
147
 
146
- @wait_threads = tests_in_groups.map.with_index do |tests, process_id|
147
- start_regular_subprocess(tests, process_id + 1, **subprocess_opts)
148
- end.compact
149
- @interrupt_handled = false
148
+ @wait_threads = tests_in_groups.map.with_index do |tests, process_id|
149
+ start_regular_subprocess(tests, process_id + 1, **subprocess_opts)
150
+ end.compact
151
+ @interrupt_handled = false
150
152
 
151
- handle_messages
153
+ handle_messages
152
154
 
153
- @threads.each(&:join)
155
+ @threads.each(&:join)
154
156
 
155
- report_failed_group(tests_in_groups) if @print_failed_group
157
+ report_failed_group(tests_in_groups) if @print_failed_group
156
158
 
157
- Signal.trap(:INT, old_signal)
159
+ Signal.trap(:INT, old_signal)
158
160
 
159
- if @reporter.failed_examples.empty? && @wait_threads.map(&:value).all?(&:success?)
160
- 0
161
- else
162
- # From https://github.com/galtzo-floss/turbo_tests2/pull/20/
163
- @wait_threads.map { |thread| thread.value.exitstatus }.max
161
+ if @reporter.failed_examples.empty? && @wait_threads.map(&:value).all?(&:success?)
162
+ 0
163
+ else
164
+ # From https://github.com/galtzo-floss/turbo_tests2/pull/20/
165
+ @wait_threads.map { |thread| thread.value.exitstatus }.max
166
+ end
164
167
  end
165
168
  end
166
169
  end
@@ -188,11 +191,15 @@ module TurboTests
188
191
 
189
192
  def start_regular_subprocess(tests, process_id, **opts)
190
193
  start_subprocess(
191
- {"TEST_ENV_NUMBER" => process_id.to_s},
194
+ {
195
+ "TEST_ENV_NUMBER" => process_id.to_s,
196
+ "PARALLEL_TEST_GROUPS" => @num_processes.to_s,
197
+ "PARALLEL_PID_FILE" => parallel_pid_file_path
198
+ },
192
199
  @tags.map { |tag| "--tag=#{tag}" },
193
200
  tests,
194
201
  process_id,
195
- **opts,
202
+ **opts
196
203
  )
197
204
  end
198
205
 
@@ -200,7 +207,7 @@ module TurboTests
200
207
  if tests.empty?
201
208
  @messages << {
202
209
  type: "exit",
203
- process_id: process_id,
210
+ process_id: process_id
204
211
  }
205
212
 
206
213
  nil
@@ -224,7 +231,7 @@ module TurboTests
224
231
  "--format",
225
232
  "ParallelTests::RSpec::RuntimeLogger",
226
233
  "--out",
227
- @runtime_log,
234
+ @runtime_log
228
235
  ]
229
236
  else
230
237
  []
@@ -232,7 +239,7 @@ module TurboTests
232
239
 
233
240
  seed_option = if @seed_used
234
241
  [
235
- "--seed", @seed,
242
+ "--seed", @seed
236
243
  ]
237
244
  else
238
245
  []
@@ -248,20 +255,22 @@ module TurboTests
248
255
  "TurboTests::JsonRowsFormatter",
249
256
  *record_runtime_options,
250
257
  *spec_opts,
251
- *tests,
258
+ *tests
252
259
  ]
253
260
  command.unshift("nice") if @nice
254
261
 
255
262
  if @verbose
256
263
  command_str = [
257
264
  env.map { |k, v| "#{k}=#{v}" }.join(" "),
258
- command.join(" "),
265
+ command.join(" ")
259
266
  ].select { |x| x.size > 0 }.join(" ")
260
267
 
261
268
  warn("Process #{process_id}: #{command_str}")
262
269
  end
263
270
 
271
+ pid_file_path = env["PARALLEL_PID_FILE"] || parallel_pid_file_path
264
272
  stdin, stdout, stderr, wait_thr = Open3.popen3(env, *command)
273
+ track_parallel_pid(wait_thr.pid, pid_file_path)
265
274
  stdin.close
266
275
 
267
276
  # rubocop:disable ThreadSafety/NewThread
@@ -290,7 +299,12 @@ module TurboTests
290
299
 
291
300
  # rubocop:disable ThreadSafety/NewThread
292
301
  @threads << Thread.new do
293
- @messages << {type: "error"} unless wait_thr.value.success?
302
+ begin
303
+ status = wait_thr.value
304
+ @messages << {type: "error"} unless status.success?
305
+ ensure
306
+ untrack_parallel_pid(wait_thr.pid, pid_file_path)
307
+ end
294
308
  end
295
309
  # rubocop:enable ThreadSafety/NewThread
296
310
 
@@ -298,6 +312,18 @@ module TurboTests
298
312
  end
299
313
  end
300
314
 
315
+ def parallel_pid_file_path
316
+ ENV["PARALLEL_PID_FILE"]
317
+ end
318
+
319
+ def track_parallel_pid(pid, pid_file_path = parallel_pid_file_path)
320
+ ParallelTests::Pids.new(pid_file_path).add(pid) if pid && pid_file_path
321
+ end
322
+
323
+ def untrack_parallel_pid(pid, pid_file_path = parallel_pid_file_path)
324
+ ParallelTests::Pids.new(pid_file_path).delete(pid) if pid && pid_file_path
325
+ end
326
+
301
327
  def start_copy_thread(src, dst)
302
328
  # rubocop:disable ThreadSafety/NewThread
303
329
  Thread.new do
@@ -356,9 +382,7 @@ module TurboTests
356
382
  @reporter.deprecation(message[:deprecation])
357
383
  when "profile"
358
384
  @reporter.profile(message[:profile])
359
- when "seed"
360
- when "close"
361
- when "error"
385
+ when "seed", "close", "error"
362
386
  # Do nothing
363
387
  nil
364
388
  when "exit"
@@ -2,7 +2,7 @@
2
2
 
3
3
  module TurboTests
4
4
  module Version
5
- VERSION = "3.1.0"
5
+ VERSION = "3.1.1"
6
6
  end
7
7
  VERSION = Version::VERSION # Traditional Constant Location
8
8
  end
data/lib/turbo_tests.rb CHANGED
@@ -39,7 +39,7 @@ module TurboTests
39
39
  klass.new(
40
40
  obj[:backtrace],
41
41
  obj[:message],
42
- FakeException.from_obj(obj[:cause]),
42
+ FakeException.from_obj(obj[:cause])
43
43
  )
44
44
  end
45
45
  end
@@ -52,7 +52,7 @@ module TurboTests
52
52
  :pending_fixed?,
53
53
  :exception,
54
54
  :pending_exception,
55
- :run_time,
55
+ :run_time
56
56
  )
57
57
  class FakeExecutionResult
58
58
  class << self
@@ -64,7 +64,7 @@ module TurboTests
64
64
  obj[:pending_fixed?],
65
65
  FakeException.from_obj(obj[:exception]),
66
66
  FakeException.from_obj(obj[:exception]),
67
- obj[:run_time],
67
+ obj[:run_time]
68
68
  )
69
69
  end
70
70
  end
@@ -76,7 +76,7 @@ module TurboTests
76
76
  :description,
77
77
  :full_description,
78
78
  :metadata,
79
- :location_rerun_argument,
79
+ :location_rerun_argument
80
80
  )
81
81
  class FakeExample
82
82
  class << self
@@ -86,7 +86,7 @@ module TurboTests
86
86
  metadata[:shared_group_inclusion_backtrace].map! do |frame|
87
87
  RSpec::Core::SharedExampleGroupInclusionStackFrame.new(
88
88
  frame[:shared_group_name],
89
- frame[:inclusion_location],
89
+ frame[:inclusion_location]
90
90
  )
91
91
  end
92
92
 
@@ -98,14 +98,14 @@ module TurboTests
98
98
  obj[:description],
99
99
  obj[:full_description],
100
100
  metadata,
101
- obj[:location_rerun_argument],
101
+ obj[:location_rerun_argument]
102
102
  )
103
103
  end
104
104
  end
105
105
 
106
106
  def notification
107
107
  RSpec::Core::Notifications::ExampleNotification.for(
108
- self,
108
+ self
109
109
  )
110
110
  end
111
111
  end
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.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Illia
@@ -112,7 +112,7 @@ dependencies:
112
112
  version: '2.0'
113
113
  - - ">="
114
114
  - !ruby/object:Gem::Version
115
- version: 2.0.5
115
+ version: 2.0.7
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  version: '2.0'
123
123
  - - ">="
124
124
  - !ruby/object:Gem::Version
125
- version: 2.0.5
125
+ version: 2.0.7
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: bundler-audit
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -200,7 +200,7 @@ dependencies:
200
200
  version: '2.0'
201
201
  - - ">="
202
202
  - !ruby/object:Gem::Version
203
- version: 2.0.1
203
+ version: 2.0.2
204
204
  type: :development
205
205
  prerelease: false
206
206
  version_requirements: !ruby/object:Gem::Requirement
@@ -210,7 +210,7 @@ dependencies:
210
210
  version: '2.0'
211
211
  - - ">="
212
212
  - !ruby/object:Gem::Version
213
- version: 2.0.1
213
+ version: 2.0.2
214
214
  - !ruby/object:Gem::Dependency
215
215
  name: ruby-progressbar
216
216
  requirement: !ruby/object:Gem::Requirement
@@ -254,7 +254,7 @@ dependencies:
254
254
  version: '2.0'
255
255
  - - ">="
256
256
  - !ruby/object:Gem::Version
257
- version: 2.0.0
257
+ version: 2.0.1
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
@@ -264,11 +264,10 @@ dependencies:
264
264
  version: '2.0'
265
265
  - - ">="
266
266
  - !ruby/object:Gem::Version
267
- version: 2.0.0
268
- description: "\U0001F680 `turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests`
267
+ version: 2.0.1
268
+ description: "\U0001F680 turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests`
269
269
  and `grosser/parallel_tests` with incremental summarized output. Source code of
270
- `turbo_test2` gem is based on Discourse and Rubygems work in this area (see README
271
- file of the source repository)."
270
+ `turbo_test2` gem is based on Discourse and Rubygems work in this area (see README.md)."
272
271
  email:
273
272
  - floss@galtzo.com
274
273
  executables:
@@ -312,10 +311,10 @@ licenses:
312
311
  - MIT
313
312
  metadata:
314
313
  homepage_uri: https://turbo-tests2.galtzo.com
315
- source_code_uri: https://github.com/galtzo-floss/turbo_tests2/tree/v3.1.0
316
- changelog_uri: https://github.com/galtzo-floss/turbo_tests2/blob/v3.1.0/CHANGELOG.md
314
+ source_code_uri: https://github.com/galtzo-floss/turbo_tests2/tree/v3.1.1
315
+ changelog_uri: https://github.com/galtzo-floss/turbo_tests2/blob/v3.1.1/CHANGELOG.md
317
316
  bug_tracker_uri: https://github.com/galtzo-floss/turbo_tests2/issues
318
- documentation_uri: https://www.rubydoc.info/gems/turbo_tests2/3.1.0
317
+ documentation_uri: https://www.rubydoc.info/gems/turbo_tests2/3.1.1
319
318
  funding_uri: https://github.com/sponsors/pboling
320
319
  wiki_uri: https://github.com/galtzo-floss/turbo_tests2/wiki
321
320
  news_uri: https://www.railsbling.com/tags/turbo_tests2
@@ -323,7 +322,7 @@ metadata:
323
322
  rubygems_mfa_required: 'true'
324
323
  rdoc_options:
325
324
  - "--title"
326
- - "turbo_tests2 - \U0001F680 `turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests`
325
+ - "turbo_tests2 - \U0001F680 turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests`
327
326
  and `grosser/parallel_tests` with incremental summarized output"
328
327
  - "--main"
329
328
  - README.md
@@ -347,6 +346,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
347
346
  requirements: []
348
347
  rubygems_version: 4.0.10
349
348
  specification_version: 4
350
- summary: "\U0001F680 `turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests`
349
+ summary: "\U0001F680 turbo_tests2` is a drop-in replacement for `serpapi/turbo_tests`
351
350
  and `grosser/parallel_tests` with incremental summarized output"
352
351
  test_files: []
metadata.gz.sig CHANGED
Binary file