[ruby-on-rails] 레이크 스펙을 실행하지 않고 Rails rspec 테스트를 위해 테스트 데이터베이스를 준비하려면 어떻게해야합니까?

중요한 문제 해결 후, rake specrspec을 직접 (예 : 사양의 하위 집합에서) 실행하기 전에 한 번 실행해야한다는 것을 알게 되었습니다 (control-c로 중단 할 수 있음). 우리는 Rails 3.0.7과 RSpec 2.5.0을 실행하고 있습니다.

분명히, rake는 몇 가지 중요한 데이터베이스 설정 작업 / 코드를 실행하고 있습니다 (루트 레벨 레일 Rakefile 및 가능하면 다른 위치에 사용자 정의 코드가 있음).

실행하지 않고 레이크 테스트 데이터베이스 설정 작업 / 코드를 rake spec어떻게 실행할 수 있습니까?

파일의 하위 집합에서 rspec을 실행할 수있는 것 외에도 specjour 를 사용하여 사양을 여러 코어에 분산하고 있지만 (아직 LAN을 통해 분산하는 데 성공하지 못함) rspec을 실행할 때와 동일한 동작을 봅니다. 직접 : rake specspecjour가 작동하기 전에 각 테스트 데이터베이스 (2 개의 코어 가정) 에서 실행해야 합니다.

rake spec TEST_ENV_NUMBER=1
control-c (after tests start)
rake spec TEST_ENV_NUMBER=2
control-c (after tests start)
specjour

참고 : 내 config / database.yml에는 다음과 같은 테스트 항목이 있습니다 (병렬 테스트 gem의 경우 일반적 임).

test:
  adapter: postgresql
  encoding: unicode
  database: test<%=ENV['TEST_ENV_NUMBER']%>
  username: user
  password:

parallel_tests 는 데이터베이스를 올바르게 설정 것처럼 보이지만 많은 사양이 실패합니다.

실행 specjour prepare하면 Postgres가 데이터베이스를 찾을 수 없다는 오류를 기록하지만 테이블없이 생성 된다는 점도 언급해야합니다 . 후속 실행에서는 오류가 기록되지 않지만 테이블도 생성되지 않습니다. 내 전체 문제가 단순히에서 버그 prepare일 수 있으므로 github에보고했습니다.

Specjour::Configuration.prepare.specjour / hooks.rb 를 설정하여 각 specjour 테스트 데이터베이스에서 임의의 코드를 실행할 수 있다고 생각하므로 실행 해야하는 레이크 작업이나 다른 코드가 있으면 작동 할 수 있습니다.



답변

직장에서 CI 시스템을 설정하는 데 비슷한 문제가 있었기 때문에 점차적으로이를 처리 할 시스템을 구축했습니다. 최선의 해결책은 아닐지 모르지만 제 상황에서는 저에게 효과적이며 저는 항상 더 나은 방법을 찾고 있습니다.

설정이 필요한 테스트 데이터베이스가 있지만 테스트가 작동하려면로드 된 데이터가 필요했습니다.

레이크 작업 문제 해결의 기본은 –trace 옵션을 사용하여 rake를 실행하여 내부에서 무슨 일이 발생하는지 확인하는 것입니다. 이 작업을 수행했을 때 rake spec을 실행하면 사용자 지정 레이크 작업에서 복제 (또는 적합하다고 생각한대로 수정) 할 수있는 여러 가지 작업이 수행된다는 것을 알았습니다.

다음은 우리가하는 일의 예입니다.

desc "Setup test database - drops, loads schema, migrates and seeds the test db"
task :test_db_setup => [:pre_reqs] do
  Rails.env = ENV['RAILS_ENV'] = 'test'
  Rake::Task['db:drop'].invoke
  Rake::Task['db:create'].invoke
  result = capture_stdout { Rake::Task['db:schema:load'].invoke }
  File.open(File.join(ENV['CC_BUILD_ARTIFACTS'] || 'log', 'schema-load.log'), 'w') { |f| f.write(result) }
  Rake::Task['db:seed:load'].invoke
  ActiveRecord::Base.establish_connection
  Rake::Task['db:migrate'].invoke
end

이것은 예시 일 뿐이며 상황에 따라 다르므로 테스트 DB 설정을 위해 수행해야 할 작업을 파악해야하지만 rake의 –trace 옵션을 사용하여 결정하는 것은 매우 쉽습니다.

또한 테스트 설정이 너무 오래 걸리는 경우 (우리의 경우처럼) 데이터베이스를 .sql 형식으로 덤프하고 테스트 데이터베이스에서 직접 mysql로 ​​파이프하여로드하도록 할 수 있습니다. 그렇게하면 테스트 DB 설정에서 몇 분을 절약 할 수 있습니다. 나는 그것이 상당히 복잡하기 때문에 여기에서 보여주지 않는다. 부실하지 않고 적절하게 생성되어야한다

HTH


답변

테스트 데이터베이스를 삭제 한 다음 다시 만들고 마이그레이션하는 것이 좋습니다.

bundle exec rake db:drop RAILS_ENV=test
bundle exec rake db:create RAILS_ENV=test
bundle exec rake db:schema:load RAILS_ENV=test

이 단계 후에 사양을 실행할 수 있습니다.

bundle exec rspec spec

gerry3 는 다음과 같이 언급했습니다.

더 간단한 해결책은 rake db:test:prepare

그러나 PostgreSQL을 사용하는 경우 Rails 환경이로드되어 데이터베이스 연결이 열리기 때문에 작동하지 않습니다. 이로 인해 prepareDB를 삭제할 수 없기 때문에 호출이 실패합니다. 까다로운 것.


답변

제공된 솔루션은 모두 Rails 환경을로드해야하며, 이는 대부분의 경우 매우 큰 오버 헤드와 매우 낮은 속도로 인해 원하는 동작이 아닙니다. DatabaseCleanergem도 다소 느리고 앱에 또 다른 종속성을 추가합니다.

위에 언급 된 이유들 덕분에 몇 달간 억울함과 짜증을 낸 후 마침내 다음과 같은 해결책이 정확히 필요한 것을 발견했습니다. 멋지고 간단하며 빠릅니다. 에서 spec_helper.rb:

config.after :all do
  ActiveRecord::Base.subclasses.each(&:delete_all)
end

이것에 대한 가장 좋은 부분은 : 그것은 당신이 효과적으로 터치 한 테이블들만 지울 것입니다 (손상되지 않은 모델들은로드되지 않을 것이고 따라서 subclasses이것은 테스트 전에 이것이 작동하지 않는 이유이기도합니다 ). 또한 테스트 후에 실행되므로 녹색 점이 즉시 나타납니다.

유일한 단점은 테스트를 실행하기 전에 더티 데이터베이스가 있으면 정리되지 않는다는 것입니다. 그러나 테스트 데이터베이스는 일반적으로 외부 테스트에서 건드리지 않기 때문에 이것이 중요한 문제라고 의심합니다.

편집하다

이 답변이 인기를 얻었 기 때문에 완전성을 위해 편집하고 싶었습니다. 모든 테이블 을 지우고 싶다면 , 건드리지 않은 테이블이라도 아래의 “핵”과 같은 작업을 할 수 있어야합니다.

해킹 1- subclasses방법에 대한 모든 모델 미리로드

전화하기 전에 이것을 평가하십시오 subclasses:

Dir[Rails.root.join("app", "models", "**", "*.rb")].each(&method(:require))

이 방법은 다소 시간이 걸릴 수 있습니다!

해킹 2-수동으로 테이블 자르기

ActiveRecord::Base.connection.tables.keep_if{ |x| x != 'schema_migrations' }

다음과 같은 작업을 수행 할 수있는 모든 테이블 이름을 얻을 수 있습니다.

case ActiveRecord::Base.configurations[Rails.env]["adapter"]
when /^mysql/, /^postgresql/
  ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")
when /^sqlite/
  ActiveRecord::Base.connection.execute("DELETE FROM #{table_name}")
  ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table_name}'")
end


답변

Rails 4.1+에서 가장 좋은 해결책은 단순히 ActiveRecord::Migration.maintain_test_schema!.NET Core 뒤에 rails_helper 를 추가 하는 것 require 'rspec/rails'입니다.

즉, 더 이상 데이터베이스를 준비해야하는 것에 대해 걱정할 필요가 없습니다.

https://relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks


답변

Spring-ified Rails 4 앱에서는 bin/setup일반적으로 다음을 포함하도록 확장됩니다.

puts "\n== Preparing test database =="
system "RAILS_ENV=test bin/rake db:setup"

이것은 leviathan의 답변 과 매우 유사 하며 테스트 DB를 시드합니다.

rake db:setup # 데이터베이스를 만들고, 스키마를로드하고, 시드 데이터로 초기화합니다
(
데이터베이스를 먼저 삭제하는데도 사용 db:reset ).

코멘트에서 언급했듯이 DB를 먼저 삭제하려면 rake db:reset그렇게하십시오.

나는 또한 이것이 rake db:test:prepare.


답변

테스트 데이터베이스를 삭제하여 시작했습니다.
rake db:drop RAILS_ENV=test

새 테스트 데이터베이스를 만들려고 할 때 내 사용자 계정이 데이터베이스를 소유 한 계정과 동일하지 않기 때문에 문제가 발생하여 대신 PostgreSQL에서 데이터베이스를 만들었습니다.

psql명령 프롬프트에 입력 한 다음 아래를 실행하여 자신의 계정이 아닌 다른 계정을 사용하는 테스트 데이터베이스를 만듭니다.
CREATE DATABASE your_database_name OWNER your_db_owner;

그런 다음 테스트 환경에서 마이그레이션을 실행하십시오.
rake db:migrate RAILS_ENV=test


답변