Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallel test databases are truncated before each run, but non-parallel test databases are not #46820

Closed
ghiculescu opened this issue Dec 24, 2022 · 4 comments

Comments

@ghiculescu
Copy link
Member

Steps to reproduce

Repro here: https://github.com/ghiculescu/parallel-tests-repro. The key bits are as follows.

In the test helper:

parallelize(workers: :number_of_processors, threshold: 2)

# Load some data in the test database before tests run.
# We don't use fixtures for this because it's a huge static dataset.
# A good example might be loading data from the countries gem or something like that.
# We don't do this in `setup` because it is slow. We want to just do it once (per database), before all tests.
10.times {|n| User.create!(name: "User #{n}") }

The test:

test "static data is created in test_helper.rb" do
  assert_equal 10, User.count
end

This just confirms that the static data was successfully loaded and is available to the test.

Expected behavior

I expect the test to pass if you run in singular or in parallel.

rails db:reset test # run tests in singular, should pass
PARALLEL_WORKERS=2 rails db:reset test # run tests in parallel, should pass

Actual behavior

Running not in parallel passes.

Running in parallel fails.

PARALLEL_WORKERS=2 rails db:reset test
Dropped database 'db/development.sqlite3'
Dropped database 'db/test.sqlite3'
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
Running 1 tests in parallel using 2 processes
Run options: --seed 10094

# Running:

F

Failure:
UserTest#test_static_data_is_created_in_test_helper.rb_-_0
Expected: 10
  Actual: 0

It is failing because

create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)

calls

which truncates all tables. The equivalent does not happen if you aren't running in parallel.

I tried commenting out that line, and all tests still passed, but I assumed there's a reason for it (though I can't think of one...) so wanted to make an issue for discussion first.

System configuration

Rails version: main

Ruby version: 3.2

seanpdoyle added a commit to seanpdoyle/turbo-rails that referenced this issue Dec 24, 2022
In the past, the test suite has been flaky, and didn't seem to truncate
tables from previous runs.

The root cause of that might be related to [rails/rails#46820][]. In the
meantime, while that is resolved, this commit adds a line to
[parallelize][] to the test suite, and some corresponding `.sqlite3`
ignore values to the `.gitignore`.

[rails/rails#46820]: rails/rails#46820
[parallelize]: https://edgeapi.rubyonrails.org/classes/ActiveSupport/TestCase.html#method-c-parallelize
seanpdoyle added a commit to seanpdoyle/turbo-rails that referenced this issue Dec 24, 2022
In the past, the test suite has been flaky, and didn't seem to truncate
tables from previous runs.

The root cause of that might be related to [rails/rails#46820][]. In the
meantime, while that is resolved, this commit adds a line to
[parallelize][] to the test suite, and some corresponding `.sqlite3`
ignore values to the `.gitignore`.

[rails/rails#46820]: rails/rails#46820
[parallelize]: https://edgeapi.rubyonrails.org/classes/ActiveSupport/TestCase.html#method-c-parallelize
@eileencodes
Copy link
Member

The data being inserted into the database is happening before the test databases are created. If you want to insert data into the parallel databases you need to hook into the same callback that parallel testing uses. This is documented here https://guides.rubyonrails.org/testing.html#parallel-testing-with-processes.

I think the docs could be improved, but calling a manual insert before the test databases are established will always cause the tests to fail in parallel.

@ghiculescu
Copy link
Member Author

ghiculescu commented Jan 5, 2023

Geez, how did I miss that. This works as expected: https://github.com/ghiculescu/parallel-tests-repro/compare/use-parallel-setup

Thanks for the help @eileencodes

@seanabrahams
Copy link
Contributor

I ran into a discrepancy with parallelization when it comes to when fixture data is available to the forked processes vs non-parallelized runs. Everything works fine without parallelization but failed with parallelization due to fixture data not yet being available in the database. I worked around the issue by manually loading the fixtures I needed in parallelize_setup:

parallelize_setup do |i|
  ActiveRecord::FixtureSet.create_fixtures(Rails.root.join("test/fixtures"), "accounts")
end

@ghiculescu
Copy link
Member Author

That seems like a bug, fixtures should get loaded automatically in either setup. Could you create an issue with more derail?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants