rails: [Parallel Testing] byebug crashing on new Rails project

Steps to reproduce

  1. Create a new Rails project: rails new project-foobar --database=mysql --api
  2. Create database: rake db:create
  3. Generate a new model: rails g model FruitFarm apple:string orange:string
  4. Migrate database: rake db:migrate
  5. Uncomment out sample test in /test/models/fruit_farm_test.rb, add a byebug statement before assert true
require 'test_helper'

class FruitFarmTest < ActiveSupport::TestCase
  test "the truth" do
    byebug
    assert true
  end
end
  1. Test application: rails test
  2. When in the byebug shell, press c to continue with the program.

Do steps 6 & 7 (i.e. keep re-testing), ~5-10 times, the error shows up inconsistently.

Expected behavior

The test suite should continue to completion without an issue!

Actual behavior

Getting the following error:

Traceback (most recent call last):
	19: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0/gems/minitest-5.11.3/lib/minitest.rb:63:in `block in autorun'
	18: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0/gems/minitest-5.11.3/lib/minitest.rb:133:in `run'
	17: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:74:in `start'
	16: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:74:in `map'
	15: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:74:in `each'
	14: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:74:in `times'
	13: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:75:in `block in start'
	12: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:75:in `fork'
	11: from /Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:95:in `block (2 levels) in start'
	10: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1138:in `method_missing'
	 9: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1158:in `with_friend'
	 8: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1139:in `block in method_missing'
	 7: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1213:in `open'
	 6: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1213:in `synchronize'
	 5: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1216:in `block in open'
	 4: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1216:in `each'
	 3: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1218:in `block (2 levels) in open'
	 2: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1262:in `alive?'
	 1: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1005:in `alive?'
/Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/drb/drb.rb:1005:in `wait_readable': Bad file descriptor (Errno::EBADF)
Traceback (most recent call last):
	2: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0/gems/minitest-5.11.3/lib/minitest.rb:63:in `block in autorun'
	1: from /Users/chrismaltais/.rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0/gems/minitest-5.11.3/lib/minitest.rb:140:in `run'
/Users/chrismaltais/.rvm/gems/ruby-2.6.0/gems/activesupport-6.0.0/lib/active_support/testing/parallelization.rb:118:in `shutdown': Queue not empty, but all workers have finished. This probably means that a worker crashed and 1 tests were missed. (RuntimeError)

System configuration

Rails version: 6.0.0

Ruby version: 2.6.0p0

Note

Related issues found online and pretty recent:

  1. StackOverflow
  2. Qiita
  3. Qiita 2

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 17 (5 by maintainers)

Most upvoted comments

I do not recommend using spring with parallel tests.

Ah ok. What is the recommended way to run parallel tests? bin/rake test, bin/rails test and bundle exec [rails|rake] test will use spring by default.

Check your fixtures. If it’s a new app, your fixtures probably look like this

one: {}
two: {}

Commenting one of them out should fix the issue with Parallel testing.

I don’t think there’s a solution for this. Rails / parallel tests can’t know that you set a byebug breakpoint before we hit it. We wouldn’t be able to ignore a byebug/pry breakpoint without doing an ugly hack to override methods in those gems. If you need byebug / pry running with an entire suite or test file it may break before you need it anyway so I don’t think it makes sense for us to pursue a fix.

Would you like to open a PR documenting that byebug/pry are unsupported? I think that’s the best we can do other than turn off parallelization for local tests.

After some digging, it seems like the issue here is with parallelized testing. It works if we edit /test/test_helper.rb:

ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'

class ActiveSupport::TestCase
  # Run tests in parallel with specified workers
  # OLD: parallelize(workers: :number_of_processors)  <--
  parallelize(workers: 1) # i.e don't run tests in parallel via forked processes
  # OR just comment the line above out completely <--

  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
end

When looking for answers I found this question asking about breakpoint functionality with byebug and multiple processes. It was answered here with regards to threads… but not forked processes

Follow-up

It seems there is an intuitive hurdle in the ability to run tests in parallel and setting breakpoints with byebug. Are there any docs available for this? If you set parallelize(workers: 2) it will continue to crash occasionally.