Skip to content

Commit

Permalink
Chore: Run tests in parallel on CI (#4759)
Browse files Browse the repository at this point in the history
Because:
- It shaves a minute off our CI completion time 🚤 

This commit:
- Adds parallel tests gem
- Split tests in groups on Github actions using their matrix feature
- Change test setup to allow for dynamic ports based on the parallel
test number thats is being used
  • Loading branch information
KevinMulhern authored Aug 15, 2024
1 parent 70a58c4 commit b2299b4
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 21 deletions.
37 changes: 23 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,35 @@ jobs:
tests:
name: Tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Set N number of parallel jobs you want to run tests on.
# Use higher number if you have slow tests to split them on more parallel jobs.
# Remember to update ci_node_index below to 0..N-1
ci_node_total: [4]
# set N-1 indexes for parallel jobs
# When you run 2 parallel jobs then first job will have index 0, the second job will have index 1 etc
ci_node_index: [0, 1, 2, 3]
services:
postgres:
image: postgres:15.7
ports:
- 5432:5432
env:
POSTGRES_USER: postgres
POSTGRES_DB: theodinproject_test
POSTGRES_PASSWORD: "password"
ports: ["5432:5432"]
POSTGRES_PASSWORD: postgres

redis:
image: redis
ports: ["6379:6379"]

env:
RAILS_ENV: test
POSTGRES_USERNAME: postgres
POSTGRES_PASSWORD: postgres
SKIP_YARN_INSTALL: true

steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -74,22 +90,15 @@ jobs:
yarn install
- name: Build assets
env:
RAILS_ENV: test
SKIP_YARN_INSTALL: true
run: |
bin/rails javascript:build
bin/rails css:build
- name: Setup test database
env:
RAILS_ENV: test
DATABASE_URL: postgres://postgres:password@localhost:5432/theodinproject_test
run: |
bin/rails db:schema:load
bundle exec rake parallel:create
bundle exec rake parallel:load_schema
bundle exec rake parallel:migrate
- name: Run tests
env:
RAILS_ENV: test
DATABASE_URL: postgres://postgres:password@localhost:5432/theodinproject_test
run: bin/rspec
run: ./bin/ci_spec
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ end

group :development, :test do
gem 'dotenv-rails', '~> 3.1'
gem 'parallel_tests', '~> 4.7'
gem 'rspec-rails', '~> 6.1'
end

Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ GEM
orm_adapter (0.5.0)
pagy (6.5.0)
parallel (1.26.1)
parallel_tests (4.7.1)
parallel
parser (3.3.4.2)
ast (~> 2.4.1)
racc
Expand Down Expand Up @@ -630,6 +632,7 @@ DEPENDENCIES
omniauth-google-oauth2 (~> 1.1.1)
omniauth-rails_csrf_protection (~> 1.0)
pagy (~> 6.2)
parallel_tests (~> 4.7)
pg (~> 1.5)
propshaft (~> 0.9)
public_activity (~> 3.0)
Expand Down
15 changes: 15 additions & 0 deletions bin/ci_spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env ruby

# This script is used to run tests in parallel in Github Actions.
# parallel_test test -n 8 --only-group 1,2

CI_RUNNER_PROCESS_COUNT = 2

parallel_tests_is_one_indexed = 1
node_index = ENV['CI_NODE_INDEX'].to_i

groups = "#{node_index * CI_RUNNER_PROCESS_COUNT + parallel_tests_is_one_indexed },#{node_index * CI_RUNNER_PROCESS_COUNT + parallel_tests_is_one_indexed + 1}"

total_parallelism = CI_RUNNER_PROCESS_COUNT * ENV['CI_NODE_TOTAL'].to_i

exec "bundle exec parallel_test ./spec -t rspec -n #{total_parallelism} --only-group #{groups}"
2 changes: 1 addition & 1 deletion config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ development: &development
# DO NOT PUT A REAL USERNAME AND PASSWORD IN THIS FILE
test: &test
<<: *default
database: <%= ENV['POSTGRES_TEST_DB'] || 'theodinproject_test' %>
database: theodinproject_test<%= ENV['TEST_ENV_NUMBER'] %>

production:
adapter: postgresql
Expand Down
5 changes: 3 additions & 2 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@

config.action_mailer.perform_caching = false

test_port = 3001 + ENV['TEST_ENV_NUMBER'].to_i
config.action_mailer.default_url_options = {
host: ENV.fetch('HOST', 'localhost'),
port: ENV.fetch('HOST_PORT', 3001)
port: ENV.fetch('HOST_PORT', test_port)
}
routes.default_url_options = {
host: ENV.fetch('HOST', 'localhost'),
port: ENV.fetch('HOST_PORT', 3001)
port: ENV.fetch('HOST_PORT', test_port)
}

# Tell Action Mailer not to deliver emails to the real world.
Expand Down
2 changes: 1 addition & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion spec/services/notifications/flag_submission_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
notification_message = "OdinUser has flagged a submission on #{flagged_submission.lesson.title}\n" \
"Reason: inappropriate\n" \
"Extra: I find it offensive\n" \
'Resolve the flag here: http://localhost:3001/admin/flags/120'
"Resolve the flag here: http://localhost:#{Rails.application.routes.default_url_options[:port]}/admin/flags/120"

expect(notification.message).to eq notification_message
end
Expand Down
4 changes: 2 additions & 2 deletions spec/support/capybara.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
Capybara.configure do |config|
config.test_id = 'data-test'
config.automatic_label_click = true
config.server_port = 3001
config.app_host = 'http://localhost:3001'
config.server_port = 3001 + ENV['TEST_ENV_NUMBER'].to_i
config.app_host = "http://localhost:#{config.server_port}"
end

Capybara.singleton_class.prepend(Module.new do
Expand Down

0 comments on commit b2299b4

Please sign in to comment.