Skip to content

Commit 5c88388

Browse files
authored
Merge pull request #2598 from mroderick/parallel-test-execution
Add parallel test execution for local development
2 parents fd1a03b + 6209806 commit 5c88388

4 files changed

Lines changed: 47 additions & 39 deletions

File tree

.github/workflows/ruby.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
BUNDLE_IGNORE_FUNDING_REQUESTS: true
1818
BUNDLE_IGNORE_MESSAGES: true
1919
RAILS_ENV: test
20+
COVERAGE: true
2021
PARALLEL_TEST_PROCESSORS: ${{ matrix.ci_node_total }}
2122
services:
2223
postgres:

AGENTS.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ codebar planner is a Rails 8.1 application for managing [codebar.io](https://cod
3131

3232
- **Setup**: `bundle && rake db:create db:migrate db:seed`
3333
- **Server**: `bundle exec rails server`
34-
- **Tests**: `bundle exec rspec [path]` - runs RSpec tests, optionally for specific file/line
34+
- **Tests**: `make test` or `bundle exec parallel_rspec spec/ -n 3` - runs RSpec tests in parallel (3 processes is optimal)
35+
- **Single test**: `bundle exec rspec spec/path/to/file_spec.rb:42`
3536
- **Rails console**: `bundle exec rails console`
3637
- **Run rake tasks**: `bundle exec rake [task]`
3738
- **Linting**: `bundle exec rubocop`
@@ -129,14 +130,15 @@ See `app/models/README.md` for detailed data model documentation.
129130
- **JavaScript Driver**: Playwright (Chromium by default)
130131
- **Factories**: Fabrication (not FactoryBot)
131132
- **Test data**: Faker for generated data
132-
- **Coverage**: SimpleCov
133+
- **Coverage**: SimpleCov (runs in CI when COVERAGE=true)
134+
- **Parallel testing**: Use `make test` or `bundle exec parallel_rspec spec/ -n 3` for ~45% faster test runs
133135
- **JavaScript tests**: Capybara with Playwright driver
134136
- Use `PLAYWRIGHT_HEADLESS=false` to debug with visible browser
135137
- Use `PWDEBUG=1` for Playwright Inspector (step-through debugging)
136138
- Use `PLAYWRIGHT_BROWSER=firefox` or `webkit` for cross-browser testing
137139
- **Matchers**: Shoulda Matchers, RSpec Collection Matchers
138140

139-
Run single test: `bin/drspec spec/path/to/file_spec.rb:42`
141+
Run single test: `bundle exec rspec spec/path/to/file_spec.rb:42`
140142

141143
## Code Style
142144

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ deploy_staging:
2222
heroku maintenance:off --app=codebar-staging
2323
serve:
2424
rm -f ./tmp/pids/server.pid && bundle exec rails server --binding=0.0.0.0 --port=3000
25+
26+
test:
27+
bundle exec parallel_rspec spec/ -n 3

spec/spec_helper.rb

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,49 @@
1-
require 'simplecov'
2-
require 'simplecov-lcov'
1+
require 'simplecov' if ENV['COVERAGE'] == 'true'
2+
require 'simplecov-lcov' if ENV['COVERAGE'] == 'true'
33
require 'shoulda/matchers'
44
require 'webmock/rspec'
55

6-
# Fix incompatibility of simplecov-lcov with older versions of simplecov that are not expresses in its gemspec.
7-
# https://github.com/fortissimo1997/simplecov-lcov/pull/25
6+
if ENV['COVERAGE'] == 'true'
7+
# Fix incompatibility of simplecov-lcov with older versions of simplecov that are not expresses in its gemspec.
8+
# https://github.com/fortissimo1997/simplecov-lcov/pull/25
89

9-
if !SimpleCov.respond_to?(:branch_coverage)
10-
module SimpleCov
11-
def self.branch_coverage?
12-
false
10+
if !SimpleCov.respond_to?(:branch_coverage)
11+
module SimpleCov
12+
def self.branch_coverage?
13+
false
14+
end
1315
end
1416
end
15-
end
1617

17-
SimpleCov::Formatter::LcovFormatter.config do |c|
18-
c.report_with_single_file = true
19-
c.single_report_path = 'coverage/lcov.info'
20-
end
18+
SimpleCov::Formatter::LcovFormatter.config do |c|
19+
c.report_with_single_file = true
20+
c.single_report_path = 'coverage/lcov.info'
21+
end
2122

22-
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
23-
[
24-
SimpleCov::Formatter::HTMLFormatter,
25-
SimpleCov::Formatter::LcovFormatter,
26-
]
27-
)
28-
29-
SimpleCov.start do
30-
add_filter 'spec/'
31-
32-
# Support parallel test execution
33-
# In CI: Use CI_NODE_INDEX (0, 1, 2, 3) set by GitHub Actions matrix
34-
# Locally: Use TEST_ENV_NUMBER ('', '2', '3', '4') set by parallel_tests
35-
if ENV['CI_NODE_INDEX']
36-
command_name "RSpec-#{ENV['CI_NODE_INDEX']}"
37-
use_merging true
38-
merge_timeout 3600
39-
elsif ENV.key?('TEST_ENV_NUMBER')
40-
# TEST_ENV_NUMBER is '' for first process, '2', '3', etc. for others
41-
suffix = ENV['TEST_ENV_NUMBER'].empty? ? '1' : ENV['TEST_ENV_NUMBER']
42-
command_name "RSpec-#{suffix}"
43-
use_merging true
44-
merge_timeout 3600
23+
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
24+
[
25+
SimpleCov::Formatter::HTMLFormatter,
26+
SimpleCov::Formatter::LcovFormatter,
27+
]
28+
)
29+
30+
SimpleCov.start do
31+
add_filter 'spec/'
32+
33+
# Support parallel test execution
34+
# In CI: Use CI_NODE_INDEX (0, 1, 2, 3) set by GitHub Actions matrix
35+
# Locally: Use TEST_ENV_NUMBER ('', '2', '3', '4') set by parallel_tests
36+
if ENV['CI_NODE_INDEX']
37+
command_name "RSpec-#{ENV['CI_NODE_INDEX']}"
38+
use_merging true
39+
merge_timeout 3600
40+
elsif ENV.key?('TEST_ENV_NUMBER')
41+
# TEST_ENV_NUMBER is '' for first process, '2', '3', etc. for others
42+
suffix = ENV['TEST_ENV_NUMBER'].empty? ? '1' : ENV['TEST_ENV_NUMBER']
43+
command_name "RSpec-#{suffix}"
44+
use_merging true
45+
merge_timeout 3600
46+
end
4547
end
4648
end
4749

0 commit comments

Comments
 (0)