簡體   English   中英

如何在不運行 rake 規范的情況下為 Rails rspec 測試准備測試數據庫?

[英]How do I prepare test database(s) for Rails rspec tests without running rake spec?

經過大量的故障排除后,我發現我需要運行一次rake spec (我可以使用 control-c 中止),然后才能直接運行 rspec(例如,在我們規范的一個子集上)。 我們正在運行 Rails 3.0.7 和 RSpec 2.5.0。

顯然,rake 正在運行一些重要的數據庫設置任務/代碼(我們在根級 rails Rakefile 和可能的其他地方有自定義代碼)。

如何在不運行rake spec情況下運行rake spec測試數據庫設置任務/代碼?

除了能夠在文件的子集上運行 rspec 之外,我還使用specjour將我們的規范傳播到多個內核(尚未成功將它們傳播到 LAN),但我看到了與運行 rspec 相同的行為直接:在specjour工作之前,我需要在每個測試數據庫(假設有兩個核心)上運行rake spec

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 有這個測試條目(對於並行測試 gems 很常見):

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

parallel_tests似乎正確設置了它的數據庫,但我們的許多規范都失敗了。

我還應該提到,運行specjour prepare會導致 Postgres 記錄無法找到數據庫的錯誤,但它會創建它們(沒有表)。 在后續運行中,不會記錄任何錯誤,也不會創建任何表。 有可能我的整個問題只是prepare一個錯誤,所以我在 github 上報告了它。

我認為我可以通過在 .specjour/hooks.rb 中設置Specjour::Configuration.prepare在每個 specjour 測試數據庫上運行任意代碼,所以如果我需要運行任何 rake 任務或其他代碼,它可能會在那里工作。

我建議刪除您的測試數據庫,然后重新創建它並遷移:

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 環境已加載,這會打開數據庫連接。 這會導致prepare調用失敗,因為無法刪除數據庫。 棘手的事情。

我在工作中設置 CI 系統時遇到了類似的問題,所以我逐漸建立了一個系統來處理這個問題。 這可能不是最好的解決方案,但它在我的情況下對我有用,我一直在尋找更好的做事方式。

我有一個需要設置的測試數據庫,但也需要為我們的測試加載種子數據才能工作。

對 rake 任務進行故障排除的基礎是使用 --trace 選項運行 rake 以查看幕后發生的事情。 當我這樣做時,我發現運行 rake spec 做了很多我可以在自定義 rake 任務中復制(或根據我認為合適的修改)的事情。

這是我們所做的一個例子。

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

這只是一個例子,具體到我們的情況,所以你需要弄清楚需要做什么來設置你的測試數據庫,但是使用 rake 的 --trace 選項很容易確定。

此外,如果您發現測試設置花費的時間太長(就像我們的情況一樣),您還可以將數據庫轉儲為 .sql 格式,並讓測試數據庫將其直接通過管道導入 mysql 以進行加載。 我們以這種方式在測試數據庫設置中節省了幾分鍾。 我沒有在這里展示它,因為它使事情變得非常復雜——它需要正確生成而不會變得陳舊等。

HTH

提供的解決方案都需要加載 Rails 環境,在大多數情況下,由於非常大的開銷和非常低的速度,這不是所需的行為。 DatabaseCleaner gem 也很慢,它為您的應用程序添加了另一個依賴項。

由於上述原因,在幾個月的懊惱和煩惱之后,我終於找到了以下解決方案,這正是我所需要的。 它很好,簡單且快速。 spec_helper.rb

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

最好的部分是:它只會清除您有效觸及的那些表(未觸及的模型不會被加載,因此不會出現在subclasses ,這也是測試這不起作用的原因)。 此外,它會在測試后執行,因此(希望)綠點會立即出現。

唯一的缺點是如果您在運行測試之前有一個臟數據庫,它將不會被清理。 但我懷疑這是一個主要問題,因為外部測試通常不會觸及測試數據庫。

編輯

看到這個答案已經獲得了一些人氣,我想對其進行編輯以確保完整性:如果您想清除所有表格,即使是未觸及的表格,您應該能夠執行類似於下面的“hacks”的操作。

Hack 1 - 為subclasses方法預加載所有模型

在調用subclasses之前評估它:

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

請注意,此方法可能需要一些時間!

Hack 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! require 'rspec/rails'之后的 rails_helper 中。

即您不必再擔心必須准備數據庫。

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

在一個彈簧化的 Rails 4 應用程序中,我的bin/setup通常被擴充為包含

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

這與利維坦的答案非常相似,加上測試數據庫的種子,如

rake db:setup # 創建數據庫,加載模式,並用種子數據初始化
(使用db:reset也可以先刪除數據庫)

正如評論中提到的,如果我們想先刪除數據庫, 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM