turbo_tests 1.3.0 → 2.2.4
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/.github/workflows/tag_and_release.yml +82 -0
- data/.github/workflows/tests.yml +12 -7
- data/Gemfile.lock +19 -20
- data/README.md +22 -6
- data/fixtures/rspec/failing_spec.rb +13 -0
- data/fixtures/rspec/no_method_error_spec.rb +3 -0
- data/lib/turbo_tests/cli.rb +12 -7
- data/lib/turbo_tests/json_rows_formatter.rb +4 -3
- data/lib/turbo_tests/reporter.rb +51 -10
- data/lib/turbo_tests/runner.rb +71 -56
- data/lib/turbo_tests/version.rb +1 -1
- data/lib/turbo_tests.rb +2 -0
- data/lib/utils/hash_extension.rb +1 -3
- data/turbo_tests.gemspec +9 -8
- metadata +24 -30
- data/.github/workflows/snyk_ruby-analysis.yml +0 -33
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ce3db5b3cf918f8152cd3986f44505ab55127fcdba96194cfb5479416182b20
|
4
|
+
data.tar.gz: ae140be91a1b0db66f272fc7cc16bcc0d74d8ddc5d769ead501d8e3c5aa41aea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e80161b5d0ed9b656a59efc2c341a71e3bbc299bcedcfcf284f695aee5c34ba275c2c4b75cea33255db7f5c9c98a242048a72cd1d07534329bf3160f3766a04
|
7
|
+
data.tar.gz: 261e0183d586a59076db43f1b378ca6425b6bb79cadfca050b705c2fcde4cd847f26201d57716305d42add671c94421ab5e7b671f0324c0c3dacd2921b0114a9
|
@@ -0,0 +1,82 @@
|
|
1
|
+
name: Tag and Release
|
2
|
+
|
3
|
+
on:
|
4
|
+
workflow_dispatch:
|
5
|
+
push:
|
6
|
+
branches:
|
7
|
+
- master
|
8
|
+
paths:
|
9
|
+
- "lib/turbo_tests/version.rb"
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
release:
|
13
|
+
env:
|
14
|
+
GEM_NAME: turbo_tests
|
15
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
16
|
+
name: Tag and Release
|
17
|
+
runs-on: ubuntu-latest
|
18
|
+
permissions:
|
19
|
+
contents: write
|
20
|
+
packages: write
|
21
|
+
|
22
|
+
steps:
|
23
|
+
- uses: actions/checkout@v3
|
24
|
+
- name: Set up Ruby 2.7
|
25
|
+
uses: ruby/setup-ruby@v1
|
26
|
+
with:
|
27
|
+
ruby-version: 2.7
|
28
|
+
bundler-cache: true
|
29
|
+
|
30
|
+
- name: Run tests
|
31
|
+
run: |
|
32
|
+
bundle exec rake install:local
|
33
|
+
bundle install
|
34
|
+
bundle exec turbo_tests
|
35
|
+
|
36
|
+
- uses: actions/upload-artifact@v3
|
37
|
+
with:
|
38
|
+
name: "ruby-gem"
|
39
|
+
path: "pkg/*.gem"
|
40
|
+
|
41
|
+
- name: Configure Git
|
42
|
+
run: |
|
43
|
+
git config --local user.email "actions@github.com"
|
44
|
+
git config --local user.name "Actions Auto Build"
|
45
|
+
|
46
|
+
- name: Get current version
|
47
|
+
id: version-label
|
48
|
+
run: |
|
49
|
+
VERSION=$(grep VERSION lib/turbo_tests/version.rb | head -n 1 | cut -d'"' -f2)
|
50
|
+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
51
|
+
|
52
|
+
- name: Create tag
|
53
|
+
run: |
|
54
|
+
git tag -a v${{ steps.version-label.outputs.version }} -m "Release v${{ steps.version-label.outputs.version }}"
|
55
|
+
git push origin --tags
|
56
|
+
|
57
|
+
- name: Publish release
|
58
|
+
env:
|
59
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
60
|
+
run: |
|
61
|
+
gh release create v${{ steps.version-label.outputs.version }} --generate-notes
|
62
|
+
|
63
|
+
- name: Publish to GPR
|
64
|
+
run: |
|
65
|
+
mkdir -p $HOME/.gem
|
66
|
+
touch $HOME/.gem/credentials
|
67
|
+
chmod 0600 $HOME/.gem/credentials
|
68
|
+
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
69
|
+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} pkg/*.gem
|
70
|
+
env:
|
71
|
+
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
72
|
+
OWNER: ${{ github.repository_owner }}
|
73
|
+
|
74
|
+
- name: Publish to RubyGems
|
75
|
+
run: |
|
76
|
+
mkdir -p $HOME/.gem
|
77
|
+
touch $HOME/.gem/credentials
|
78
|
+
chmod 0600 $HOME/.gem/credentials
|
79
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
80
|
+
gem push pkg/*.gem
|
81
|
+
env:
|
82
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
|
data/.github/workflows/tests.yml
CHANGED
@@ -1,25 +1,30 @@
|
|
1
1
|
name: Tests
|
2
2
|
|
3
|
-
on:
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
|
6
|
+
permissions:
|
7
|
+
contents: read
|
4
8
|
|
5
9
|
jobs:
|
6
10
|
test:
|
7
11
|
runs-on: ubuntu-latest
|
8
12
|
|
9
13
|
strategy:
|
14
|
+
fail-fast: true
|
10
15
|
matrix:
|
11
|
-
ruby:
|
12
|
-
|
13
|
-
- 2.7
|
16
|
+
ruby: [ 2.7, "3.0", 3.1, 3.2, 3.3 ]
|
17
|
+
os: [ ubuntu-latest, windows-latest ]
|
14
18
|
|
15
19
|
steps:
|
16
|
-
- uses: actions/checkout@
|
17
|
-
- uses: ruby/setup-ruby@
|
20
|
+
- uses: actions/checkout@v3
|
21
|
+
- uses: ruby/setup-ruby@v1
|
18
22
|
with:
|
19
23
|
ruby-version: ${{matrix.ruby}}
|
24
|
+
rubygems: latest
|
20
25
|
bundler-cache: true
|
21
26
|
|
22
27
|
- name: Run tests
|
23
28
|
timeout-minutes: 5
|
24
29
|
run: |
|
25
|
-
|
30
|
+
bundle exec turbo_tests -n4
|
data/Gemfile.lock
CHANGED
@@ -1,37 +1,36 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
turbo_tests (
|
5
|
-
|
6
|
-
|
7
|
-
rspec (~> 3.10)
|
4
|
+
turbo_tests (2.2.4)
|
5
|
+
parallel_tests (>= 3.3.0, < 5)
|
6
|
+
rspec (>= 3.10)
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: https://rubygems.org/
|
11
10
|
specs:
|
12
11
|
coderay (1.1.3)
|
13
|
-
diff-lcs (1.
|
12
|
+
diff-lcs (1.5.0)
|
14
13
|
method_source (1.0.0)
|
15
|
-
parallel (1.
|
16
|
-
parallel_tests (
|
14
|
+
parallel (1.22.1)
|
15
|
+
parallel_tests (4.2.0)
|
17
16
|
parallel
|
18
|
-
pry (0.14.
|
17
|
+
pry (0.14.2)
|
19
18
|
coderay (~> 1.1)
|
20
19
|
method_source (~> 1.0)
|
21
20
|
rake (13.0.6)
|
22
|
-
rspec (3.
|
23
|
-
rspec-core (~> 3.
|
24
|
-
rspec-expectations (~> 3.
|
25
|
-
rspec-mocks (~> 3.
|
26
|
-
rspec-core (3.
|
27
|
-
rspec-support (~> 3.
|
28
|
-
rspec-expectations (3.
|
21
|
+
rspec (3.12.0)
|
22
|
+
rspec-core (~> 3.12.0)
|
23
|
+
rspec-expectations (~> 3.12.0)
|
24
|
+
rspec-mocks (~> 3.12.0)
|
25
|
+
rspec-core (3.12.1)
|
26
|
+
rspec-support (~> 3.12.0)
|
27
|
+
rspec-expectations (3.12.2)
|
29
28
|
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
-
rspec-support (~> 3.
|
31
|
-
rspec-mocks (3.
|
29
|
+
rspec-support (~> 3.12.0)
|
30
|
+
rspec-mocks (3.12.4)
|
32
31
|
diff-lcs (>= 1.2.0, < 2.0)
|
33
|
-
rspec-support (~> 3.
|
34
|
-
rspec-support (3.
|
32
|
+
rspec-support (~> 3.12.0)
|
33
|
+
rspec-support (3.12.0)
|
35
34
|
|
36
35
|
PLATFORMS
|
37
36
|
ruby
|
@@ -42,4 +41,4 @@ DEPENDENCIES
|
|
42
41
|
turbo_tests!
|
43
42
|
|
44
43
|
BUNDLED WITH
|
45
|
-
2.
|
44
|
+
2.4.19
|
data/README.md
CHANGED
@@ -1,10 +1,21 @@
|
|
1
|
-
|
1
|
+
<h1 align="center">
|
2
|
+
TurboTests
|
3
|
+
</h1>
|
2
4
|
|
3
|
-
|
5
|
+
<div align="center">
|
6
|
+
<img src="https://user-images.githubusercontent.com/78694043/233910064-87a6d557-1120-42d2-b965-2a9403c6f2f4.svg" width="500" alt="Turbo-Tests">
|
4
7
|
|
5
|
-
|
8
|
+
</div>
|
6
9
|
|
7
|
-
|
10
|
+
<div align="center">
|
11
|
+
|
12
|
+

|
13
|
+
|
14
|
+
</div>
|
15
|
+
|
16
|
+
`turbo_tests` is a drop-in replacement for [`grosser/parallel_tests`](https://github.com/grosser/parallel_tests) with incremental summarized output. Source code of this gem is based on [Discourse](https://github.com/discourse/discourse/blob/6b9784cf8a18636bce281a7e4d18e65a0cbc6290/lib/turbo_tests.rb) and [RubyGems](https://github.com/rubygems/rubygems/tree/390335ceb351668cd433bd5bb9823dd021f82533/bundler/tool) work in this area.
|
17
|
+
|
18
|
+
Incremental summarized output [doesn't fit vision of `parallel_tests` author](https://github.com/grosser/parallel_tests/issues/708) and [RSpec doesn't support built-in parallel testing yet](https://github.com/rspec/rspec-rails/issues/2104#issuecomment-658474900). This gem will not be useful once one of the issues above will be implemented.
|
8
19
|
|
9
20
|
## Why incremental output?
|
10
21
|
|
@@ -49,11 +60,15 @@ gem 'turbo_tests'
|
|
49
60
|
|
50
61
|
And then execute:
|
51
62
|
|
52
|
-
|
63
|
+
```bash
|
64
|
+
$ bundle install
|
65
|
+
```
|
53
66
|
|
54
67
|
Or install it yourself as:
|
55
68
|
|
56
|
-
|
69
|
+
```bash
|
70
|
+
$ gem install turbo_tests
|
71
|
+
```
|
57
72
|
|
58
73
|
## Usage
|
59
74
|
|
@@ -81,6 +96,7 @@ Options:
|
|
81
96
|
--runtime-log FILE Location of previously recorded test runtimes
|
82
97
|
-v, --verbose More output
|
83
98
|
--fail-fast=[N]
|
99
|
+
--seed SEED Seed for rspec
|
84
100
|
```
|
85
101
|
|
86
102
|
## Development
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec.describe "Failing example group" do
|
2
|
+
after(:each) do |example|
|
3
|
+
example.metadata[:extra_failure_lines] ||= []
|
4
|
+
|
5
|
+
lines = example.metadata[:extra_failure_lines]
|
6
|
+
|
7
|
+
lines << "Test info in extra_failure_lines"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "fails" do
|
11
|
+
expect(2).to eq(3)
|
12
|
+
end
|
13
|
+
end
|
data/lib/turbo_tests/cli.rb
CHANGED
@@ -16,12 +16,15 @@ module TurboTests
|
|
16
16
|
runtime_log = nil
|
17
17
|
verbose = false
|
18
18
|
fail_fast = nil
|
19
|
+
seed = nil
|
19
20
|
|
20
21
|
OptionParser.new { |opts|
|
21
22
|
opts.banner = <<~BANNER
|
22
23
|
Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('1', '2', '3', ...).
|
23
24
|
|
24
|
-
|
25
|
+
Reports test results incrementally. Uses methods from `parallel_tests` gem to split files to groups.
|
26
|
+
|
27
|
+
Source code of `turbo_tests` gem is based on Discourse and RubyGems work in this area (see README file of the source repository).
|
25
28
|
|
26
29
|
Usage: turbo_tests [options]
|
27
30
|
|
@@ -74,6 +77,10 @@ module TurboTests
|
|
74
77
|
end
|
75
78
|
fail_fast = n.nil? || n < 1 ? 1 : n
|
76
79
|
end
|
80
|
+
|
81
|
+
opts.on("--seed SEED", "Seed for rspec") do |s|
|
82
|
+
seed = s
|
83
|
+
end
|
77
84
|
}.parse!(@argv)
|
78
85
|
|
79
86
|
requires.each { |f| require(f) }
|
@@ -91,7 +98,7 @@ module TurboTests
|
|
91
98
|
end
|
92
99
|
end
|
93
100
|
|
94
|
-
|
101
|
+
exitstatus = TurboTests::Runner.run(
|
95
102
|
formatters: formatters,
|
96
103
|
tags: tags,
|
97
104
|
files: @argv.empty? ? ["spec"] : @argv,
|
@@ -99,13 +106,11 @@ module TurboTests
|
|
99
106
|
verbose: verbose,
|
100
107
|
fail_fast: fail_fast,
|
101
108
|
count: count,
|
109
|
+
seed: seed
|
102
110
|
)
|
103
111
|
|
104
|
-
|
105
|
-
|
106
|
-
else
|
107
|
-
exit 1
|
108
|
-
end
|
112
|
+
# From https://github.com/serpapi/turbo_tests/pull/20/
|
113
|
+
exit exitstatus
|
109
114
|
end
|
110
115
|
end
|
111
116
|
end
|
@@ -141,9 +141,10 @@ module TurboTests
|
|
141
141
|
shared_group_inclusion_backtrace:
|
142
142
|
example
|
143
143
|
.metadata[:shared_group_inclusion_backtrace]
|
144
|
-
.map { |frame| stack_frame_to_json(frame) }
|
144
|
+
.map { |frame| stack_frame_to_json(frame) },
|
145
|
+
extra_failure_lines: example.metadata[:extra_failure_lines],
|
145
146
|
},
|
146
|
-
location_rerun_argument: example.location_rerun_argument
|
147
|
+
location_rerun_argument: example.location_rerun_argument,
|
147
148
|
}
|
148
149
|
end
|
149
150
|
|
@@ -163,7 +164,7 @@ module TurboTests
|
|
163
164
|
end
|
164
165
|
|
165
166
|
def output_row(obj)
|
166
|
-
output.puts
|
167
|
+
output.puts ENV["RSPEC_FORMATTER_OUTPUT_ID"] + obj.to_json
|
167
168
|
output.flush
|
168
169
|
end
|
169
170
|
end
|
data/lib/turbo_tests/reporter.rb
CHANGED
@@ -4,8 +4,8 @@ module TurboTests
|
|
4
4
|
class Reporter
|
5
5
|
attr_writer :load_time
|
6
6
|
|
7
|
-
def self.from_config(formatter_config, start_time)
|
8
|
-
reporter = new(start_time)
|
7
|
+
def self.from_config(formatter_config, start_time, seed, seed_used)
|
8
|
+
reporter = new(start_time, seed, seed_used)
|
9
9
|
|
10
10
|
formatter_config.each do |config|
|
11
11
|
name, outputs = config.values_at(:name, :outputs)
|
@@ -23,13 +23,15 @@ module TurboTests
|
|
23
23
|
attr_reader :pending_examples
|
24
24
|
attr_reader :failed_examples
|
25
25
|
|
26
|
-
def initialize(start_time)
|
26
|
+
def initialize(start_time, seed, seed_used)
|
27
27
|
@formatters = []
|
28
28
|
@pending_examples = []
|
29
29
|
@failed_examples = []
|
30
30
|
@all_examples = []
|
31
31
|
@messages = []
|
32
32
|
@start_time = start_time
|
33
|
+
@seed = seed
|
34
|
+
@seed_used = seed_used
|
33
35
|
@load_time = 0
|
34
36
|
@errors_outside_of_examples_count = 0
|
35
37
|
end
|
@@ -50,6 +52,38 @@ module TurboTests
|
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
55
|
+
# Borrowed from RSpec::Core::Reporter
|
56
|
+
# https://github.com/rspec/rspec-core/blob/5699fcdc4723087ff6139af55bd155ad9ad61a7b/lib/rspec/core/reporter.rb#L71
|
57
|
+
def report(example_groups)
|
58
|
+
start(example_groups)
|
59
|
+
begin
|
60
|
+
yield self
|
61
|
+
ensure
|
62
|
+
finish
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def start(example_groups, time=RSpec::Core::Time.now)
|
67
|
+
@start = time
|
68
|
+
@load_time = (@start - @start_time).to_f
|
69
|
+
|
70
|
+
report_number_of_tests(example_groups)
|
71
|
+
expected_example_count = example_groups.flatten(1).count
|
72
|
+
|
73
|
+
delegate_to_formatters(:seed, RSpec::Core::Notifications::SeedNotification.new(@seed, @seed_used))
|
74
|
+
delegate_to_formatters(:start, RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time))
|
75
|
+
end
|
76
|
+
|
77
|
+
def report_number_of_tests(groups)
|
78
|
+
name = ParallelTests::RSpec::Runner.test_file_name
|
79
|
+
|
80
|
+
num_processes = groups.size
|
81
|
+
num_tests = groups.map(&:size).sum
|
82
|
+
tests_per_process = (num_processes == 0 ? 0 : num_tests.to_f / num_processes).round
|
83
|
+
|
84
|
+
puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{tests_per_process} #{name}s per process"
|
85
|
+
end
|
86
|
+
|
53
87
|
def group_started(notification)
|
54
88
|
delegate_to_formatters(:example_group_started, notification)
|
55
89
|
end
|
@@ -83,16 +117,18 @@ module TurboTests
|
|
83
117
|
@messages << message
|
84
118
|
end
|
85
119
|
|
86
|
-
def error_outside_of_examples
|
120
|
+
def error_outside_of_examples(error_message)
|
87
121
|
@errors_outside_of_examples_count += 1
|
122
|
+
message error_message
|
88
123
|
end
|
89
124
|
|
90
125
|
def finish
|
91
|
-
|
92
|
-
|
126
|
+
end_time = RSpec::Core::Time.now
|
127
|
+
|
128
|
+
@duration = end_time - @start_time
|
129
|
+
delegate_to_formatters :stop, RSpec::Core::Notifications::ExamplesNotification.new(self)
|
93
130
|
|
94
|
-
delegate_to_formatters
|
95
|
-
RSpec::Core::Notifications::NullNotification)
|
131
|
+
delegate_to_formatters :start_dump, RSpec::Core::Notifications::NullNotification
|
96
132
|
delegate_to_formatters(:dump_pending,
|
97
133
|
RSpec::Core::Notifications::ExamplesNotification.new(
|
98
134
|
self
|
@@ -110,8 +146,13 @@ module TurboTests
|
|
110
146
|
@load_time,
|
111
147
|
@errors_outside_of_examples_count
|
112
148
|
))
|
113
|
-
delegate_to_formatters(:
|
114
|
-
RSpec::Core::Notifications::
|
149
|
+
delegate_to_formatters(:seed,
|
150
|
+
RSpec::Core::Notifications::SeedNotification.new(
|
151
|
+
@seed,
|
152
|
+
@seed_used,
|
153
|
+
))
|
154
|
+
ensure
|
155
|
+
delegate_to_formatters :close, RSpec::Core::Notifications::NullNotification
|
115
156
|
end
|
116
157
|
|
117
158
|
protected
|
data/lib/turbo_tests/runner.rb
CHANGED
@@ -14,18 +14,19 @@ module TurboTests
|
|
14
14
|
formatters = opts[:formatters]
|
15
15
|
tags = opts[:tags]
|
16
16
|
|
17
|
-
|
18
|
-
start_time = opts.fetch(:start_time) { Process.clock_gettime(Process::CLOCK_MONOTONIC) }
|
17
|
+
start_time = opts.fetch(:start_time) { RSpec::Core::Time.now }
|
19
18
|
runtime_log = opts.fetch(:runtime_log, nil)
|
20
19
|
verbose = opts.fetch(:verbose, false)
|
21
20
|
fail_fast = opts.fetch(:fail_fast, nil)
|
22
21
|
count = opts.fetch(:count, nil)
|
22
|
+
seed = opts.fetch(:seed)
|
23
|
+
seed_used = !seed.nil?
|
23
24
|
|
24
25
|
if verbose
|
25
|
-
|
26
|
+
warn "VERBOSE"
|
26
27
|
end
|
27
28
|
|
28
|
-
reporter = Reporter.from_config(formatters, start_time)
|
29
|
+
reporter = Reporter.from_config(formatters, start_time, seed, seed_used)
|
29
30
|
|
30
31
|
new(
|
31
32
|
reporter: reporter,
|
@@ -34,7 +35,9 @@ module TurboTests
|
|
34
35
|
runtime_log: runtime_log,
|
35
36
|
verbose: verbose,
|
36
37
|
fail_fast: fail_fast,
|
37
|
-
count: count
|
38
|
+
count: count,
|
39
|
+
seed: seed,
|
40
|
+
seed_used: seed_used,
|
38
41
|
).run
|
39
42
|
end
|
40
43
|
|
@@ -46,11 +49,14 @@ module TurboTests
|
|
46
49
|
@verbose = opts[:verbose]
|
47
50
|
@fail_fast = opts[:fail_fast]
|
48
51
|
@count = opts[:count]
|
52
|
+
@seed = opts[:seed]
|
53
|
+
@seed_used = opts[:seed_used]
|
54
|
+
|
49
55
|
@load_time = 0
|
50
56
|
@load_count = 0
|
51
57
|
@failure_count = 0
|
52
58
|
|
53
|
-
@messages = Queue.new
|
59
|
+
@messages = Thread::Queue.new
|
54
60
|
@threads = []
|
55
61
|
@error = false
|
56
62
|
end
|
@@ -81,22 +87,25 @@ module TurboTests
|
|
81
87
|
setup_tmp_dir
|
82
88
|
|
83
89
|
subprocess_opts = {
|
84
|
-
record_runtime: use_runtime_info
|
90
|
+
record_runtime: use_runtime_info,
|
85
91
|
}
|
86
92
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
handle_messages
|
93
|
+
@reporter.report(tests_in_groups) do |reporter|
|
94
|
+
wait_threads = tests_in_groups.map.with_index do |tests, process_id|
|
95
|
+
start_regular_subprocess(tests, process_id + 1, **subprocess_opts)
|
96
|
+
end
|
94
97
|
|
95
|
-
|
98
|
+
handle_messages
|
96
99
|
|
97
|
-
|
100
|
+
@threads.each(&:join)
|
98
101
|
|
99
|
-
|
102
|
+
if @reporter.failed_examples.empty? && wait_threads.map(&:value).all?(&:success?)
|
103
|
+
0
|
104
|
+
else
|
105
|
+
# From https://github.com/serpapi/turbo_tests/pull/20/
|
106
|
+
wait_threads.map { |thread| thread.value.exitstatus }.max
|
107
|
+
end
|
108
|
+
end
|
100
109
|
end
|
101
110
|
|
102
111
|
private
|
@@ -124,19 +133,19 @@ module TurboTests
|
|
124
133
|
if tests.empty?
|
125
134
|
@messages << {
|
126
135
|
type: "exit",
|
127
|
-
process_id: process_id
|
136
|
+
process_id: process_id,
|
128
137
|
}
|
129
138
|
else
|
130
|
-
|
131
|
-
|
132
|
-
begin
|
133
|
-
File.mkfifo(tmp_filename)
|
134
|
-
rescue Errno::EEXIST
|
135
|
-
end
|
136
|
-
|
139
|
+
env["RSPEC_FORMATTER_OUTPUT_ID"] = SecureRandom.uuid
|
137
140
|
env["RUBYOPT"] = ["-I#{File.expand_path("..", __dir__)}", ENV["RUBYOPT"]].compact.join(" ")
|
138
141
|
env["RSPEC_SILENCE_FILTER_ANNOUNCEMENTS"] = "1"
|
139
142
|
|
143
|
+
if ENV["BUNDLE_BIN_PATH"]
|
144
|
+
command_name = [ENV["BUNDLE_BIN_PATH"], "exec", "rspec"]
|
145
|
+
else
|
146
|
+
command_name = "rspec"
|
147
|
+
end
|
148
|
+
|
140
149
|
record_runtime_options =
|
141
150
|
if record_runtime
|
142
151
|
[
|
@@ -147,23 +156,30 @@ module TurboTests
|
|
147
156
|
[]
|
148
157
|
end
|
149
158
|
|
159
|
+
seed_option = if @seed_used
|
160
|
+
[
|
161
|
+
"--seed", @seed,
|
162
|
+
]
|
163
|
+
else
|
164
|
+
[]
|
165
|
+
end
|
166
|
+
|
150
167
|
command = [
|
151
|
-
|
168
|
+
*command_name,
|
152
169
|
*extra_args,
|
153
|
-
|
170
|
+
*seed_option,
|
154
171
|
"--format", "TurboTests::JsonRowsFormatter",
|
155
|
-
"--out", tmp_filename,
|
156
172
|
*record_runtime_options,
|
157
|
-
*tests
|
173
|
+
*tests,
|
158
174
|
]
|
159
175
|
|
160
176
|
if @verbose
|
161
177
|
command_str = [
|
162
178
|
env.map { |k, v| "#{k}=#{v}" }.join(" "),
|
163
|
-
command.join(" ")
|
179
|
+
command.join(" "),
|
164
180
|
].select { |x| x.size > 0 }.join(" ")
|
165
181
|
|
166
|
-
|
182
|
+
warn "Process #{process_id}: #{command_str}"
|
167
183
|
end
|
168
184
|
|
169
185
|
stdin, stdout, stderr, wait_thr = Open3.popen3(env, *command)
|
@@ -171,26 +187,30 @@ module TurboTests
|
|
171
187
|
|
172
188
|
@threads <<
|
173
189
|
Thread.new do
|
174
|
-
|
175
|
-
|
176
|
-
|
190
|
+
stdout.each_line do |line|
|
191
|
+
result = line.split(env["RSPEC_FORMATTER_OUTPUT_ID"])
|
192
|
+
|
193
|
+
output = result.shift
|
194
|
+
print(output) unless output.empty?
|
177
195
|
|
178
|
-
|
179
|
-
|
180
|
-
|
196
|
+
message = result.shift
|
197
|
+
next unless message
|
198
|
+
|
199
|
+
message = JSON.parse(message, symbolize_names: true)
|
200
|
+
message[:process_id] = process_id
|
201
|
+
@messages << message
|
181
202
|
end
|
182
203
|
|
183
|
-
@messages << {type: "exit", process_id: process_id}
|
204
|
+
@messages << { type: "exit", process_id: process_id }
|
184
205
|
end
|
185
206
|
|
186
|
-
@threads << start_copy_thread(stdout, STDOUT)
|
187
207
|
@threads << start_copy_thread(stderr, STDERR)
|
188
208
|
|
189
|
-
@threads << Thread.new
|
209
|
+
@threads << Thread.new do
|
190
210
|
unless wait_thr.value.success?
|
191
|
-
@messages << {type: "error"}
|
211
|
+
@messages << { type: "error" }
|
192
212
|
end
|
193
|
-
|
213
|
+
end
|
194
214
|
|
195
215
|
wait_thr
|
196
216
|
end
|
@@ -239,12 +259,17 @@ module TurboTests
|
|
239
259
|
break
|
240
260
|
end
|
241
261
|
when "message"
|
242
|
-
|
262
|
+
if message[:message].include?("An error occurred") || message[:message].include?("occurred outside of examples")
|
263
|
+
@reporter.error_outside_of_examples(message[:message])
|
264
|
+
@error = true
|
265
|
+
else
|
266
|
+
@reporter.message(message[:message])
|
267
|
+
end
|
243
268
|
when "seed"
|
244
269
|
when "close"
|
245
270
|
when "error"
|
246
|
-
|
247
|
-
|
271
|
+
# Do nothing
|
272
|
+
nil
|
248
273
|
when "exit"
|
249
274
|
exited += 1
|
250
275
|
if exited == @num_processes
|
@@ -260,17 +285,7 @@ module TurboTests
|
|
260
285
|
end
|
261
286
|
|
262
287
|
def fail_fast_met
|
263
|
-
!@fail_fast.nil? && @
|
264
|
-
end
|
265
|
-
|
266
|
-
def report_number_of_tests(groups)
|
267
|
-
name = ParallelTests::RSpec::Runner.test_file_name
|
268
|
-
|
269
|
-
num_processes = groups.size
|
270
|
-
num_tests = groups.map(&:size).sum
|
271
|
-
tests_per_process = (num_processes == 0 ? 0 : num_tests.to_f / num_processes).round
|
272
|
-
|
273
|
-
puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{tests_per_process} #{name}s per process"
|
288
|
+
!@fail_fast.nil? && @failure_count >= @fail_fast
|
274
289
|
end
|
275
290
|
end
|
276
291
|
end
|
data/lib/turbo_tests/version.rb
CHANGED
data/lib/turbo_tests.rb
CHANGED
data/lib/utils/hash_extension.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module CoreExtensions
|
2
2
|
refine Hash do
|
3
3
|
def to_struct
|
4
|
-
|
5
|
-
acc[key] = val.is_a?(Hash) ? val.to_struct : val
|
6
|
-
end)
|
4
|
+
Struct.new(*self.keys).new(*self.values.map { |value| value.is_a?(Hash) ? value.to_struct : value })
|
7
5
|
end
|
8
6
|
end
|
9
7
|
end
|
data/turbo_tests.gemspec
CHANGED
@@ -3,26 +3,27 @@ require_relative "lib/turbo_tests/version"
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = "turbo_tests"
|
5
5
|
spec.version = TurboTests::VERSION
|
6
|
-
spec.
|
7
|
-
spec.
|
6
|
+
spec.platform = Gem::Platform::RUBY
|
7
|
+
spec.date = Time.now.strftime('%Y-%m-%d')
|
8
8
|
|
9
|
-
spec.summary = "
|
9
|
+
spec.summary = "`turbo_tests` is a drop-in replacement for `grosser/parallel_tests` with incremental summarized output. Source code of `turbo_test` gem is based on Discourse and Rubygems work in this area (see README file of the source repository)."
|
10
10
|
spec.homepage = "https://github.com/serpapi/turbo_tests"
|
11
11
|
spec.license = "MIT"
|
12
12
|
|
13
|
+
spec.authors = ["Illia Zub"]
|
14
|
+
spec.email = ["ilya@serpapi.com"]
|
15
|
+
|
13
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
14
17
|
spec.metadata["source_code_uri"] = "https://github.com/serpapi/turbo_tests"
|
15
18
|
spec.metadata["changelog_uri"] = "https://github.com/serpapi/turbo_tests/releases"
|
16
19
|
|
17
|
-
spec.required_ruby_version = ">= 2.
|
20
|
+
spec.required_ruby_version = ">= 2.7"
|
18
21
|
|
19
|
-
spec.add_dependency "rspec", "
|
20
|
-
spec.add_dependency "parallel_tests", "
|
22
|
+
spec.add_dependency "rspec", ">= 3.10"
|
23
|
+
spec.add_dependency "parallel_tests", ">= 3.3.0", "< 5"
|
21
24
|
|
22
25
|
spec.add_development_dependency "pry", "~> 0.14"
|
23
26
|
|
24
|
-
spec.add_runtime_dependency "bundler"
|
25
|
-
|
26
27
|
# Specify which files should be added to the gem when it is released.
|
27
28
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
28
29
|
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
metadata
CHANGED
@@ -1,43 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbo_tests
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Illia Zub
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3.10'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.10'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: parallel_tests
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 3.3.0
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '5'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
43
|
+
version: 3.3.0
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '5'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: pry
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,33 +58,18 @@ dependencies:
|
|
52
58
|
- - "~>"
|
53
59
|
- !ruby/object:Gem::Version
|
54
60
|
version: '0.14'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: bundler
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
61
|
description:
|
70
62
|
email:
|
71
|
-
-
|
63
|
+
- ilya@serpapi.com
|
72
64
|
executables:
|
73
65
|
- turbo_tests
|
74
66
|
extensions: []
|
75
67
|
extra_rdoc_files: []
|
76
68
|
files:
|
77
|
-
- ".github/workflows/
|
69
|
+
- ".github/workflows/tag_and_release.yml"
|
78
70
|
- ".github/workflows/tests.yml"
|
79
71
|
- ".gitignore"
|
80
72
|
- ".rspec"
|
81
|
-
- ".travis.yml"
|
82
73
|
- CODE_OF_CONDUCT.md
|
83
74
|
- Gemfile
|
84
75
|
- Gemfile.lock
|
@@ -87,6 +78,8 @@ files:
|
|
87
78
|
- Rakefile
|
88
79
|
- bin/turbo_tests
|
89
80
|
- fixtures/rspec/errors_outside_of_examples_spec.rb
|
81
|
+
- fixtures/rspec/failing_spec.rb
|
82
|
+
- fixtures/rspec/no_method_error_spec.rb
|
90
83
|
- fixtures/rspec/pending_exceptions_spec.rb
|
91
84
|
- lib/turbo_tests.rb
|
92
85
|
- lib/turbo_tests/cli.rb
|
@@ -111,16 +104,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
104
|
requirements:
|
112
105
|
- - ">="
|
113
106
|
- !ruby/object:Gem::Version
|
114
|
-
version: '2.
|
107
|
+
version: '2.7'
|
115
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
109
|
requirements:
|
117
110
|
- - ">="
|
118
111
|
- !ruby/object:Gem::Version
|
119
112
|
version: '0'
|
120
113
|
requirements: []
|
121
|
-
rubygems_version: 3.
|
114
|
+
rubygems_version: 3.1.6
|
122
115
|
signing_key:
|
123
116
|
specification_version: 4
|
124
|
-
summary:
|
125
|
-
|
117
|
+
summary: "`turbo_tests` is a drop-in replacement for `grosser/parallel_tests` with
|
118
|
+
incremental summarized output. Source code of `turbo_test` gem is based on Discourse
|
119
|
+
and Rubygems work in this area (see README file of the source repository)."
|
126
120
|
test_files: []
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# A sample workflow which checks out your Infrastructure as Code Configuration files,
|
2
|
-
# such as Kubernetes, Helm & Terraform and scans them for any security issues.
|
3
|
-
# The results are then uploaded to GitHub Security Code Scanning
|
4
|
-
#
|
5
|
-
# For more examples, including how to limit scans to only high-severity issues
|
6
|
-
# and fail PR checks, see https://github.com/snyk/actions/
|
7
|
-
|
8
|
-
name: Snyk Ruby
|
9
|
-
|
10
|
-
on:
|
11
|
-
push:
|
12
|
-
branches: [ master ]
|
13
|
-
pull_request:
|
14
|
-
# The branches below must be a subset of the branches above
|
15
|
-
branches: [ master ]
|
16
|
-
schedule:
|
17
|
-
- cron: '0 0 * * 0'
|
18
|
-
|
19
|
-
jobs:
|
20
|
-
snyk:
|
21
|
-
runs-on: ubuntu-latest
|
22
|
-
steps:
|
23
|
-
- uses: actions/checkout@v2
|
24
|
-
- name: Run Snyk to check configuration files for security issues
|
25
|
-
# Snyk can be used to break the build when it detects security issues.
|
26
|
-
# In this case we want to upload the issues to GitHub Code Scanning
|
27
|
-
continue-on-error: true
|
28
|
-
uses: snyk/actions/ruby@master
|
29
|
-
env:
|
30
|
-
# In order to use the Snyk Action you will need to have a Snyk API token.
|
31
|
-
# More details in https://github.com/snyk/actions#getting-your-snyk-token
|
32
|
-
# or you can signup for free at https://snyk.io/login
|
33
|
-
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|