diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 6f3e4c127..953d99c6d 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -17,6 +17,7 @@ jobs: BUNDLE_IGNORE_FUNDING_REQUESTS: true BUNDLE_IGNORE_MESSAGES: true RAILS_ENV: test + COVERAGE: true PARALLEL_TEST_PROCESSORS: ${{ matrix.ci_node_total }} services: postgres: diff --git a/AGENTS.md b/AGENTS.md index c2687774c..1fedbd75f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,7 +31,8 @@ codebar planner is a Rails 8.1 application for managing [codebar.io](https://cod - **Setup**: `bundle && rake db:create db:migrate db:seed` - **Server**: `bundle exec rails server` -- **Tests**: `bundle exec rspec [path]` - runs RSpec tests, optionally for specific file/line +- **Tests**: `make test` or `bundle exec parallel_rspec spec/ -n 3` - runs RSpec tests in parallel (3 processes is optimal) +- **Single test**: `bundle exec rspec spec/path/to/file_spec.rb:42` - **Rails console**: `bundle exec rails console` - **Run rake tasks**: `bundle exec rake [task]` - **Linting**: `bundle exec rubocop` @@ -129,14 +130,15 @@ See `app/models/README.md` for detailed data model documentation. - **JavaScript Driver**: Playwright (Chromium by default) - **Factories**: Fabrication (not FactoryBot) - **Test data**: Faker for generated data -- **Coverage**: SimpleCov +- **Coverage**: SimpleCov (runs in CI when COVERAGE=true) +- **Parallel testing**: Use `make test` or `bundle exec parallel_rspec spec/ -n 3` for ~45% faster test runs - **JavaScript tests**: Capybara with Playwright driver - Use `PLAYWRIGHT_HEADLESS=false` to debug with visible browser - Use `PWDEBUG=1` for Playwright Inspector (step-through debugging) - Use `PLAYWRIGHT_BROWSER=firefox` or `webkit` for cross-browser testing - **Matchers**: Shoulda Matchers, RSpec Collection Matchers -Run single test: `bin/drspec spec/path/to/file_spec.rb:42` +Run single test: `bundle exec rspec spec/path/to/file_spec.rb:42` ## Code Style diff --git a/Makefile b/Makefile index 650ee21a8..1107a5681 100644 --- a/Makefile +++ b/Makefile @@ -22,3 +22,6 @@ deploy_staging: heroku maintenance:off --app=codebar-staging serve: rm -f ./tmp/pids/server.pid && bundle exec rails server --binding=0.0.0.0 --port=3000 + +test: + bundle exec parallel_rspec spec/ -n 3 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3ca44fcb8..ca4b95fab 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,47 +1,49 @@ -require 'simplecov' -require 'simplecov-lcov' +require 'simplecov' if ENV['COVERAGE'] == 'true' +require 'simplecov-lcov' if ENV['COVERAGE'] == 'true' require 'shoulda/matchers' require 'webmock/rspec' -# Fix incompatibility of simplecov-lcov with older versions of simplecov that are not expresses in its gemspec. -# https://github.com/fortissimo1997/simplecov-lcov/pull/25 +if ENV['COVERAGE'] == 'true' + # Fix incompatibility of simplecov-lcov with older versions of simplecov that are not expresses in its gemspec. + # https://github.com/fortissimo1997/simplecov-lcov/pull/25 -if !SimpleCov.respond_to?(:branch_coverage) - module SimpleCov - def self.branch_coverage? - false + if !SimpleCov.respond_to?(:branch_coverage) + module SimpleCov + def self.branch_coverage? + false + end end end -end -SimpleCov::Formatter::LcovFormatter.config do |c| - c.report_with_single_file = true - c.single_report_path = 'coverage/lcov.info' -end + SimpleCov::Formatter::LcovFormatter.config do |c| + c.report_with_single_file = true + c.single_report_path = 'coverage/lcov.info' + end -SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new( - [ - SimpleCov::Formatter::HTMLFormatter, - SimpleCov::Formatter::LcovFormatter, - ] -) - -SimpleCov.start do - add_filter 'spec/' - - # Support parallel test execution - # In CI: Use CI_NODE_INDEX (0, 1, 2, 3) set by GitHub Actions matrix - # Locally: Use TEST_ENV_NUMBER ('', '2', '3', '4') set by parallel_tests - if ENV['CI_NODE_INDEX'] - command_name "RSpec-#{ENV['CI_NODE_INDEX']}" - use_merging true - merge_timeout 3600 - elsif ENV.key?('TEST_ENV_NUMBER') - # TEST_ENV_NUMBER is '' for first process, '2', '3', etc. for others - suffix = ENV['TEST_ENV_NUMBER'].empty? ? '1' : ENV['TEST_ENV_NUMBER'] - command_name "RSpec-#{suffix}" - use_merging true - merge_timeout 3600 + SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new( + [ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::LcovFormatter, + ] + ) + + SimpleCov.start do + add_filter 'spec/' + + # Support parallel test execution + # In CI: Use CI_NODE_INDEX (0, 1, 2, 3) set by GitHub Actions matrix + # Locally: Use TEST_ENV_NUMBER ('', '2', '3', '4') set by parallel_tests + if ENV['CI_NODE_INDEX'] + command_name "RSpec-#{ENV['CI_NODE_INDEX']}" + use_merging true + merge_timeout 3600 + elsif ENV.key?('TEST_ENV_NUMBER') + # TEST_ENV_NUMBER is '' for first process, '2', '3', etc. for others + suffix = ENV['TEST_ENV_NUMBER'].empty? ? '1' : ENV['TEST_ENV_NUMBER'] + command_name "RSpec-#{suffix}" + use_merging true + merge_timeout 3600 + end end end