Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ jobs:
env:
TEST_DATABASE_URL: postgres://postgres:postgres@localhost/intercode_test
RAILS_ENV: test
# the runner has 4 cores; each worker gets its own copy of the test database
PARALLEL_WORKERS: 4
services:
postgres:
image: postgres:18
Expand Down Expand Up @@ -352,7 +354,7 @@ jobs:
name: vitest-coverage
path: vitest-coverage
- name: Merge coverage reports
run: ruby scripts/merge_coverage.rb merged-coverage.xml minitest-coverage/coverage.xml vitest-coverage/cobertura-coverage.xml minitest-system-coverage/coverage.xml
run: ruby scripts/merge_coverage.rb merged-coverage.xml minitest-coverage/coverage.xml minitest-coverage/worker-*/coverage.xml vitest-coverage/cobertura-coverage.xml minitest-system-coverage/coverage.xml
- name: Generate Coverage Report
uses: clearlyip/code-coverage-report-action@v7
id: code_coverage_report_action
Expand Down
16 changes: 16 additions & 0 deletions agent-docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ When modifying loader/action patterns:
4. Run `yarn run tsc --noEmit` to check for TypeScript errors
5. Test actual navigation flows to ensure data loading works

### Running Minitest in parallel

Set `PARALLEL_WORKERS` to run the suite in that many processes, each with its own copy of the test database
(`intercode_test-0`, `-1`, ...). CI uses 4, which cuts the Minitest run from about 4陆 minutes to about 1陆.

```sh
PARALLEL_WORKERS=4 bin/rails test
```

- On macOS the `pg` gem can crash (a segfault in `connect_start`) when the workers fork. Set
`PGGSSENCMODE=disable OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES` as well.
- Each worker writes its own coverage report to `coverage/worker-N/coverage.xml`, and the main process's
`coverage/coverage.xml` has what loading the app covered. Merge them with
`ruby scripts/merge_coverage.rb merged.xml coverage/coverage.xml coverage/worker-*/coverage.xml` (CI's coverage report
job does). The merged result is line-for-line identical to a single-process run's.

## End-to-End Testing with Playwright

Use Playwright (and Rails system tests) sparingly: browser-driven tests have been flaky in this project, so prefer a component test (see [Frontend Testing](frontend-testing.md)) wherever it gets close enough. Reserve end-to-end tests for the few flows that really need a real browser.
Expand Down
18 changes: 15 additions & 3 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,21 @@ class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
include ActionMailer::TestCase::ClearTestDeliveries

# Minitest is broken with parallelization on Ruby 3.1 - it's expecting methods to be methods but Rails is
# deserializing them as strings, so you can't actually see the unexpected error output
# parallelize(workers: :number_of_processors)
# Set PARALLEL_WORKERS to run tests in that many processes (each with its own copy of the test database). CI does,
# to use all of the cores on its runners; it's left off by default so that a plain `rails test` stays simple.
if ENV["PARALLEL_WORKERS"].to_i > 1
parallelize(workers: ENV["PARALLEL_WORKERS"].to_i)

# Each worker writes its own coverage report (coverage/worker-N/coverage.xml) instead of merging with the others as
# the run exits, which races the workers finishing. The main process's coverage.xml has what loading the app
# covered (class bodies and so on), so CI merges all of them with scripts/merge_coverage.rb.
parallelize_setup do |worker|
SimpleCov.command_name "#{SimpleCov.command_name}-#{worker}"
SimpleCov.use_merging false
SimpleCov.coverage_dir "coverage/worker-#{worker}"
end
parallelize_teardown { |_worker| SimpleCov.result.format! }
end

class TestGraphqlContext
def self.with_user_con_profile(user_con_profile, **attrs)
Expand Down
Loading