parallel_tests 4.3.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 598069c4031e361060ee4c4beaf7becc3454365b7825b7e9cb8d7909d2f0bb00
4
- data.tar.gz: 3b0684f907eb1de6b9bb0556289ff3556052fc1fb75c138608801dbb91891b63
3
+ metadata.gz: 9b46d1404706ddf69fdaae9b58cb24f86f894a87dcc629865ae18b664c8a1835
4
+ data.tar.gz: 00f2931c2ba28191e7ff3256edea0e43c516212b035fca3ae8a57ba154cf1014
5
5
  SHA512:
6
- metadata.gz: 5056b01a89580b61ce8b49f034959fe7f5b08f7dee2bd83cd44c115016483ff1be41f1ca34b3cc8471ef9e4ce898b9d3cb3b5123cf88905a9d9c21e6a08439b5
7
- data.tar.gz: 91a0afb5012fc117de3f602b769d590be185e322dab9555c1f9eae220d90db7131d7516e8fd338ec25cbd8c70428209e5b85b644380f00722eaafd5d41ac9f36
6
+ metadata.gz: 74c9ffe885e299f8f2a603b07a0a9e6597eb4ec52529acac790e3b36e4ce8ee9c73c537fdff67131fce664819e1adefc7c376474ff139140f62393e0d32f6aa4
7
+ data.tar.gz: 72120ba7eb205d54c484a71fd58a86bfd95787e4967bf754c19857d5cf2970803a963a70f2e60dc448e61b61eea13c32b8ad7b16762106da9efc743a891d4da8
data/Readme.md CHANGED
@@ -33,18 +33,28 @@ test:
33
33
  ### Create additional database(s)
34
34
  rake parallel:create
35
35
 
36
+ ### (Multi-DB) Create individual database
37
+ rake parallel:create:<database>
38
+ rake parallel:create:secondary
39
+
36
40
  ### Copy development schema (repeat after migrations)
37
41
  rake parallel:prepare
38
42
 
39
43
  ### Run migrations in additional database(s) (repeat after migrations)
40
44
  rake parallel:migrate
41
45
 
46
+ ### (Multi-DB) Run migrations in individual database
47
+ rake parallel:migrate:<database>
48
+
42
49
  ### Setup environment from scratch (create db and loads schema, useful for CI)
43
50
  rake parallel:setup
44
51
 
45
52
  ### Drop all test databases
46
53
  rake parallel:drop
47
54
 
55
+ ### (Multi-DB) Drop individual test database
56
+ rake parallel:drop:<database>
57
+
48
58
  ### Run!
49
59
  rake parallel:test # Minitest
50
60
  rake parallel:spec # RSpec
@@ -106,11 +116,13 @@ at_exit do
106
116
  end
107
117
  ```
108
118
 
109
- Even test group run-times
110
- =========================
119
+ Even test group runtimes
120
+ ========================
121
+
122
+ Test groups will often run for different times, making the full test run as slow as the slowest group.
111
123
 
112
- Test groups are often not balanced and will run for different times, making everything wait for the slowest group.
113
- Use these loggers to record test runtime and then use the recorded runtime to balance test groups more evenly.
124
+ Step 1: Use these loggers (see below) to record test runtime
125
+ Step 2: Your next run will use the recorded test runtimes (use `--runtime-log <file>` if you picked a location different from below)
114
126
 
115
127
  ### RSpec
116
128
 
@@ -128,9 +140,11 @@ Add to your `test_helper.rb`:
128
140
  require 'parallel_tests/test/runtime_logger' if ENV['RECORD_RUNTIME']
129
141
  ```
130
142
 
131
- results will be logged to tmp/parallel_runtime_test.log when `RECORD_RUNTIME` is set,
143
+ results will be logged to `tmp/parallel_runtime_test.log` when `RECORD_RUNTIME` is set,
132
144
  so it is not always required or overwritten.
133
145
 
146
+ ### TODO: add instructions for other frameworks
147
+
134
148
  Loggers
135
149
  =======
136
150
 
@@ -147,7 +161,7 @@ Add the following to your `.rspec_parallel` (or `.rspec`) :
147
161
  RSpec: FailuresLogger
148
162
  -----------------------
149
163
 
150
- Produce pastable command-line snippets for each failed example. For example:
164
+ Produce pasteable command-line snippets for each failed example. For example:
151
165
 
152
166
  ```bash
153
167
  rspec /path/to/my_spec.rb:123 # should do something
@@ -160,6 +174,24 @@ Add to `.rspec_parallel` or use as CLI flag:
160
174
 
161
175
  (Not needed to retry failures, for that pass [--only-failures](https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures) to rspec)
162
176
 
177
+
178
+ RSpec: VerboseLogger
179
+ -----------------------
180
+
181
+ Prints a single line for starting and finishing each example, to see what is currently running in each process.
182
+
183
+ ```
184
+ # PID, parallel process number, spec status, example description
185
+ [14403] [2] [STARTED] Foo foo
186
+ [14402] [1] [STARTED] Bar bar
187
+ [14402] [1] [PASSED] Bar bar
188
+ ```
189
+
190
+ Add to `.rspec_parallel` or use as CLI flag:
191
+
192
+ --format ParallelTests::RSpec::VerboseLogger
193
+
194
+
163
195
  Cucumber: FailuresLogger
164
196
  -----------------------
165
197
 
@@ -36,6 +36,8 @@ class ParallelTests::RSpec::RuntimeLogger < ParallelTests::RSpec::LoggerBase
36
36
  def start_dump(*)
37
37
  return unless ENV['TEST_ENV_NUMBER'] # only record when running in parallel
38
38
  lock_output do
39
+ # Order the output from slowest to fastest
40
+ @example_times = @example_times.sort_by(&:last).reverse
39
41
  @example_times.each do |file, time|
40
42
  relative_path = file.sub(%r{^#{Regexp.escape Dir.pwd}/}, '').sub(%r{^\./}, "")
41
43
  @output.puts "#{relative_path}:#{[time, 0].max}"
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/core/formatters/base_text_formatter'
4
+ require 'parallel_tests/rspec/runner'
5
+
6
+ class ParallelTests::RSpec::VerboseLogger < RSpec::Core::Formatters::BaseTextFormatter
7
+ RSpec::Core::Formatters.register(
8
+ self,
9
+ :example_group_started,
10
+ :example_group_finished,
11
+ :example_started,
12
+ :example_passed,
13
+ :example_pending,
14
+ :example_failed
15
+ )
16
+
17
+ def initialize(output)
18
+ super
19
+ @line = []
20
+ end
21
+
22
+ def example_group_started(notification)
23
+ @line.push(notification.group.description)
24
+ end
25
+
26
+ def example_group_finished(_notification)
27
+ @line.pop
28
+ end
29
+
30
+ def example_started(notification)
31
+ @line.push(notification.example.description)
32
+ output_formatted_line('STARTED', :yellow)
33
+ end
34
+
35
+ def example_passed(_passed)
36
+ output_formatted_line('PASSED', :success)
37
+ @line.pop
38
+ end
39
+
40
+ def example_pending(_pending)
41
+ output_formatted_line('PENDING', :pending)
42
+ @line.pop
43
+ end
44
+
45
+ def example_failed(_failure)
46
+ output_formatted_line('FAILED', :failure)
47
+ @line.pop
48
+ end
49
+
50
+ private
51
+
52
+ def output_formatted_line(status, console_code)
53
+ prefix = ["[#{Process.pid}]"]
54
+ if ENV.include?('TEST_ENV_NUMBER')
55
+ test_env_number = ENV['TEST_ENV_NUMBER'] == '' ? 1 : Integer(ENV['TEST_ENV_NUMBER'])
56
+ prefix << "[#{test_env_number}]"
57
+ end
58
+ prefix << RSpec::Core::Formatters::ConsoleCodes.wrap("[#{status}]", console_code)
59
+
60
+ output.puts [*prefix, *@line].join(' ')
61
+ end
62
+ end
@@ -48,6 +48,9 @@ module ParallelTests
48
48
  activate_pipefail = "set -o pipefail"
49
49
  remove_ignored_lines = %{(grep -v #{Shellwords.escape(ignore_regex)} || true)}
50
50
 
51
+ # remove nil values (ex: #purge_before_load returns nil)
52
+ command.compact!
53
+
51
54
  if system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null")
52
55
  shell_command = "#{activate_pipefail} && (#{Shellwords.shelljoin(command)}) | #{remove_ignored_lines}"
53
56
  ['/bin/bash', '-c', shell_command]
@@ -125,6 +128,23 @@ module ParallelTests
125
128
  command
126
129
  end
127
130
 
131
+ def configured_databases
132
+ return [] unless defined?(ActiveRecord) && rails_61_or_greater?
133
+
134
+ @@configured_databases ||= ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
135
+ end
136
+
137
+ def for_each_database(&block)
138
+ # Use nil to represent all databases
139
+ block&.call(nil)
140
+
141
+ return unless defined?(ActiveRecord)
142
+
143
+ ActiveRecord::Tasks::DatabaseTasks.for_each(configured_databases) do |name|
144
+ block&.call(name)
145
+ end
146
+ end
147
+
128
148
  private
129
149
 
130
150
  def rails_7_or_greater?
@@ -145,25 +165,33 @@ namespace :parallel do
145
165
  ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
146
166
  end
147
167
 
148
- desc "Create test databases via db:create --> parallel:create[num_cpus]"
149
- task :create, :count do |_, args|
150
- ParallelTests::Tasks.run_in_parallel(
151
- [$0, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
152
- args
153
- )
168
+ ParallelTests::Tasks.for_each_database do |name|
169
+ task_name = 'create'
170
+ task_name += ":#{name}" if name
171
+ desc "Create test#{" #{name}" if name} database via db:#{task_name} --> parallel:#{task_name}[num_cpus]"
172
+ task task_name.to_sym, :count do |_, args|
173
+ ParallelTests::Tasks.run_in_parallel(
174
+ [$0, "db:#{task_name}", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
175
+ args
176
+ )
177
+ end
154
178
  end
155
179
 
156
- desc "Drop test databases via db:drop --> parallel:drop[num_cpus]"
157
- task :drop, :count do |_, args|
158
- ParallelTests::Tasks.run_in_parallel(
159
- [
160
- $0,
161
- "db:drop",
162
- "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
163
- "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
164
- ],
165
- args
166
- )
180
+ ParallelTests::Tasks.for_each_database do |name|
181
+ task_name = 'drop'
182
+ task_name += ":#{name}" if name
183
+ desc "Drop test#{" #{name}" if name} database via db:#{task_name} --> parallel:#{task_name}[num_cpus]"
184
+ task task_name.to_sym, :count do |_, args|
185
+ ParallelTests::Tasks.run_in_parallel(
186
+ [
187
+ $0,
188
+ "db:#{task_name}",
189
+ "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
190
+ "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
191
+ ],
192
+ args
193
+ )
194
+ end
167
195
  end
168
196
 
169
197
  desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]"
@@ -190,12 +218,16 @@ namespace :parallel do
190
218
  end
191
219
 
192
220
  # when dumping/resetting takes too long
193
- desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]"
194
- task :migrate, :count do |_, args|
195
- ParallelTests::Tasks.run_in_parallel(
196
- [$0, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
197
- args
198
- )
221
+ ParallelTests::Tasks.for_each_database do |name|
222
+ task_name = 'migrate'
223
+ task_name += ":#{name}" if name
224
+ desc "Update test#{" #{name}" if name} database via db:#{task_name} --> parallel:#{task_name}[num_cpus]"
225
+ task task_name.to_sym, :count do |_, args|
226
+ ParallelTests::Tasks.run_in_parallel(
227
+ [$0, "db:#{task_name}", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
228
+ args
229
+ )
230
+ end
199
231
  end
200
232
 
201
233
  desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]"
@@ -207,16 +239,24 @@ namespace :parallel do
207
239
  end
208
240
 
209
241
  # just load the schema (good for integration server <-> no development db)
210
- desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
211
- task :load_schema, :count do |_, args|
212
- command = [
213
- $0,
214
- ParallelTests::Tasks.purge_before_load,
215
- "db:schema:load",
216
- "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
217
- "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
218
- ]
219
- ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
242
+ ParallelTests::Tasks.for_each_database do |name|
243
+ rails_task = 'db:schema:load'
244
+ rails_task += ":#{name}" if name
245
+
246
+ task_name = 'load_schema'
247
+ task_name += ":#{name}" if name
248
+
249
+ desc "Load dumped schema for test#{" #{name}" if name} database via #{rails_task} --> parallel:#{task_name}[num_cpus]"
250
+ task task_name.to_sym, :count do |_, args|
251
+ command = [
252
+ $0,
253
+ ParallelTests::Tasks.purge_before_load,
254
+ rails_task,
255
+ "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
256
+ "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
257
+ ]
258
+ ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
259
+ end
220
260
  end
221
261
 
222
262
  # load the structure from the structure.sql file
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ParallelTests
3
- VERSION = '4.3.0'
3
+ VERSION = '4.5.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_tests
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 4.5.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: 2023-10-09 00:00:00.000000000 Z
11
+ date: 2024-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -58,6 +58,7 @@ files:
58
58
  - lib/parallel_tests/rspec/runner.rb
59
59
  - lib/parallel_tests/rspec/runtime_logger.rb
60
60
  - lib/parallel_tests/rspec/summary_logger.rb
61
+ - lib/parallel_tests/rspec/verbose_logger.rb
61
62
  - lib/parallel_tests/spinach/runner.rb
62
63
  - lib/parallel_tests/tasks.rb
63
64
  - lib/parallel_tests/test/runner.rb
@@ -68,8 +69,8 @@ licenses:
68
69
  - MIT
69
70
  metadata:
70
71
  bug_tracker_uri: https://github.com/grosser/parallel_tests/issues
71
- documentation_uri: https://github.com/grosser/parallel_tests/blob/v4.3.0/Readme.md
72
- source_code_uri: https://github.com/grosser/parallel_tests/tree/v4.3.0
72
+ documentation_uri: https://github.com/grosser/parallel_tests/blob/v4.5.0/Readme.md
73
+ source_code_uri: https://github.com/grosser/parallel_tests/tree/v4.5.0
73
74
  wiki_uri: https://github.com/grosser/parallel_tests/wiki
74
75
  post_install_message:
75
76
  rdoc_options: []
@@ -86,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
87
  - !ruby/object:Gem::Version
87
88
  version: '0'
88
89
  requirements: []
89
- rubygems_version: 3.3.3
90
+ rubygems_version: 3.4.10
90
91
  signing_key:
91
92
  specification_version: 4
92
93
  summary: Run Test::Unit / RSpec / Cucumber / Spinach in parallel