Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Switching from :transaction to :truncation for some tests doesn't work

オープン
#652 コメント 5 件 リアクション 2 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
postgresql, ruby
領域
databases, testing

調査の方向性

spec/rails_helper.rb から始め、Sidekiq が別プロセスとして実行されている状態で、truncate: true とマークされた RSpec の example を再現します。hook の後の DatabaseCleaner の strategy を調べ、PostgreSQL からの row visibility を確認します。完了条件は、マークされた example が truncation を使用して外部からレコードを参照でき、残りの suite はトランザクションのままであることです。

索引モデルが issue の本文から書いたものです。

説明

So, I have some tests that need truncation because I am testing the whole Sidekiq stack and as a separate process Sidekiq needs to be able to see the records created in the original process. I want to keep the suite in general as :transaction though as the rest of the tests are fine with that strategy.

To do this I add come config to the rspec config:

config.before(:each) do |example|
  DatabaseCleaner.start

  if example.metadata[:truncate]
    DatabaseCleaner.strategy = :truncation
  else
    DatabaseCleaner.strategy = :transaction
  end
end

Then add metadata to the test:

it 'should doit', truncate: true do
  # create records then run the background worker
  # wait for the background worker to finish
end

The problem is that Sidekiq gets ActiveRecord not found errors, and sure enough, there are no rows available to on a separate database (postgres) connection:

connector_test=# select count(*) from contacts;
 count 
-------
     0
(1 row)

If I stick byebug in the test I can confirm that there are in fact records:

(byebug) Contact.count
3

but the strategey does seem to be truncation:

(byebug) DatabaseCleaner[:active_record].strategy.class
DatabaseCleaner::ActiveRecord::Truncation

(byebug) DatabaseCleaner[:active_record].strategy
#<DatabaseCleaner::ActiveRecord::Truncation:0x00007f95e600ff68 @only=nil, @tables_to_exclude=["schema_migrations"], @pre_count=nil, @reset_ids=nil, @cache_tables=true, @db=:default>

If I re-run the test after configuring truncation for all of the tests:

config.before(:suite) do
   DatabaseCleaner.strategy = :truncation
   …
end

I can see that the strategy in the test is the same:

(byebug) DatabaseCleaner[:active_record].strategy
#<DatabaseCleaner::ActiveRecord::Truncation:0x00007f8faf0ccec0 @only=nil, @tables_to_exclude=["schema_migrations"], @pre_count=nil, @reset_ids=nil, @cache_tables=true, @db=:default>

and the records are available in the test:

(byebug) Contact.count
3

but this time the records are also available in the database:

connector_test=# select count(*) from contacts;
 count 
-------
     3
(1 row)

and my test passes. These are the versions of relevant gems I am using

$ bundle info database_cleaner
  * database_cleaner (1.7.0)
	Summary: Strategies for cleaning databases.  Can be used to ensure a clean state for testing.
	Homepage: http://github.com/DatabaseCleaner/database_cleaner
	Path: /Users/will/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/database_cleaner-1.7.0

$ bundle info rspec-rails
  * rspec-rails (3.8.3)
	Summary: RSpec for Rails
	Homepage: https://github.com/rspec/rspec-rails
	Path: /Users/will/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/rspec-rails-3.8.3

Upgrading database cleaner

So I noticed as I was gathering the version data that database_cleaner was out of date (I could have sworn that I updated it already!). Anyway, after upgrading database_cleaner it now looks like inside the test the reported strategy matches the observed behaviour:

(byebug) DatabaseCleaner[:active_record].strategy
#<DatabaseCleaner::ActiveRecord::Transaction:0x00007ff8ba938928 @db=:default>

This is despite my strategy switch seeming to work OK in the rspec config:

[57, 66] in /Users/will/clients/foo/repos/web-app/spec/rails_helper.rb
   57:   config.before(:each) do |example|
   58:     $redis.flushall
   59:     DatabaseCleaner.start
   60: 
   61:     byebug
=> 62:     if example.metadata[:truncate]
   63:       DatabaseCleaner.strategy = :truncation
   64:     else
   65:       DatabaseCleaner.strategy = :transaction
   66:     end
(byebug) example.metadata[:truncate]
true

and as the test is using transactions not truncation the external process can't see the records and the test fails. Any ideas what's going on here?

主要言語
Ruby
スター
3k
フォーク
485
PR マージ指標
30日以内にマージされた PR はありません

環境構築

  • Dockerfile または Docker Compose ファイルあり
  • プルリクエストのテンプレートなし
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

DatabaseCleaner/database_cleaner のほかの issue

DatabaseCleaner/database_cleaner の issue をすべて見る

似ている issue

Ruby の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。