JavaScript를 실행하는 기능 사양에서 ActiveRecord에 원숭이 패치를 제거하는 방법
Rails의 기능 사양에서 자주 발생하는 문제
Rails의 피쳐 스펙으로
js: true
로 한다(테스트 실행시에 JavaScript도 움직이는) 경우, 피쳐 스펙내에서 작성한 테스트 데이터가 브라우저(Poltergeist나 Selenium webdriver로 기동하는 Firefox)내에서 참조할 수 없다고 하는 문제가 자주 발생 한다.다음은 문제가 발생하는 기능 사양의 예입니다.
require 'rails_helper'
feature 'User management' do
scenario "adds a new user", js: true do
admin = create(:admin)
visit root_path
click_link 'Log In'
fill_in 'Email', with: admin.email
fill_in 'Password', with: admin.password
# 上で作成したadminのデータがブラウザ側で参照できないのでログインに失敗する
click_button 'Log In'
# ...
end
end
이 문제는 테스트를 실행하는 코드의 DB 연결과 기능 사양 용 웹 서버가 사용하는 DB 연결이 별도이기 때문에 한 DB 트랜잭션 내에서 생성 된 데이터는 다른 DB 연결에서 볼 수 없습니다. 에 기인한다.
기존의 기존 솔루션(원숭이 패치 포함)
이 문제를 해결하기 위해 특수 원숭이 패치와 DatabaseCleaner를 사용하여 다음과 같은 해결책이 잘 취해졌습니다.
spec/support/shared_db_connection.rb
class ActiveRecord::Base
mattr_accessor :shared_connection
@@shared_connection = nil
def self.connection
@@shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
spec/rails_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
# ...
config.use_transactional_fixtures = true
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with :truncation
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
config.after(:each) do
DatabaseCleaner.clean
end
end
이것은 무엇을 하고 있는가 하면, 테스트 실행 코드와 피쳐 스펙용의 Web 서버로 DB 커넥션을 공유해, 어느 쪽에서라도 같은 데이터의 읽고 쓰기를 할 수 있도록 하고 있다.
최근 솔루션(원숭이 패치 없음)
그러나 ActiveRecord에 원숭이 패치를 맞춘다는 것은 검은 마술적이며 그다지 기분이 좋은 것은 아니다.
그래서 최신 DatabaseCleaner의 README에서는 위의 원숭이 패치를 사용하지 않고이 문제를 해결하는 방법이 실려있다.
spec/support/shared_db_connection.rb
# 不要になるのでファイルごと削除
spec/rails_helper.rb
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
if config.use_transactional_fixtures?
raise(<<-MSG)
設定がおかしいので警告メッセージを表示 (省略)
MSG
end
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, type: :feature) do
driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test
if !driver_shares_db_connection_with_specs
DatabaseCleaner.strategy = :truncation
end
end
config.before(:each) do
DatabaseCleaner.start
end
config.append_after(:each) do
DatabaseCleaner.clean
end
end
위의 설정은 간단히 말하면 다음과 같습니다.
js: true
의 경우 ( driver_shares_db_connection_with_specs
가 false
의 경우)는 트랜잭션을 사용하지 않고 데이터를 읽고 씁니다. 트랜잭션을 사용하지 않으므로 어느 DB 연결에서도 같은 데이터를 참조할 수 있다. 테스트가 끝나면 모든 데이터를 truncate합니다. 동작 확인한 실행 환경
필자는 이하의 환경에서 「원숭이 패치를 사용하지 않는 해결책」이 유효하게 기능하는 것을 확인했다.
이전 버전의 gem에서는 확인하지 않았기 때문에, 이 해결책을 적용하는 경우는 테스트 관련의 gem은 가능한 한 최신으로 하는 것이 바람직하다.
샘플 코드
Everyday Rails - RSpec에 의한 Rails 테스트 입문 샘플 응용 프로그램을 기반으로 위의 솔루션을 적용했습니다.
테스트 코드의 내용은 아래의 GitHub 리포지토리에서 확인할 수 있다.
이 설정이 해결될 수 있는 문제
Rails 5로 업데이트하면 요청 사양에서 다음과 같은 오류가 발생하여 테스트가 떨어질 수 있습니다.
PG::ConnectionBad: PQsocket() can't get socket descriptor: ROLLBACK TO SAVEPOINT active_record_1
테스트 관련 gem을 최신으로 하고 원숭이 패치를 사용하지 않는 해결책을 적용한 결과 이 문제가 해결되었다.
기타 : Everyday Rails의 독자 여러분에게
Everyday Rails - RSpec에 의한 Rails 테스트 입문 에서는 「종래의 낡은 해결책」이 실려 있으므로, 적절히 「원숭이 패치를 사용하지 않는 해결책」을 사용해 주세요.
구체적인 일정은 미정이지만 Everyday Rails도 Rails 5에 대응할 예정이므로, 그 때에는 최신의 해결책이 실려 있을 것입니다. .
함께 읽고 싶다.
Everyday Rails 샘플 애플리케이션을 Rails 5.0으로 업그레이드하는 방법을 설명하는 기사입니다.
이쪽도 함께 부디.
이것으로 더 이상 무섭지 않아! ? Rails 4.1에서 Rails 5.0으로 업그레이드하는 단계를 동영상으로 설명합니다.
Reference
이 문제에 관하여(JavaScript를 실행하는 기능 사양에서 ActiveRecord에 원숭이 패치를 제거하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/jnchito/items/ec04537b352123cab288텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)