2015-11-19 189 views
3

我正在嘗試爲Rails 4.0.2(Ruby 2.2.3)項目創建Rake任務,該項目與種子一起創建測試數據庫,然後運行測試套件,並且最後通過刪除測試數據庫進行清理。下面是下面一個簡單的例子:'rake test'後執行rake任務

task better_test: :environment do 
    Rake::Task["test:setup"].execute 
    Rake::Task["test"].execute 
    Rake::Task["test:cleanup"].execute 
end 

上面的任務的確調用test:setup rake任務(創建/種子測試數據庫),然後調用test rake任務,最後調用test:cleanup rake任務。然而,問題是最後的test:cleanuptest rake任務完成運行之前被調用。無論如何要在完成前面的任務後調用清理耙子任務嗎?

下面是從跟蹤運行任務的輸出:

$ RAILS_ENV=test be rake better_test --trace 
/usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.0.2/lib/active_support/values/time_zone.rb:282: warning: circular argument reference - now 
/usr/local/rvm/gems/ruby-2.2.3/gems/honeybadger-1.16.3/lib/honeybadger/rack/user_feedback.rb:51: warning: circular argument reference - action 
** Invoke better_test (first_time) 
** Invoke environment (first_time) 
** Execute environment 
** Execute better_test 
** Execute test:setup 
Creating test database. 
** Execute db:test:setup 
** Execute db:test:create 
** Execute db:create 
** Execute db:test:load 
** Execute db:schema:load 
** Execute db:test_project:setup 
** Execute db:test_project:create 
** Invoke db:create (first_time) 
** Invoke environment 
** Execute db:create 
** Execute db:test_project:migrate:down 
** Execute db:test_project:migrate:up 
** Execute db:test_project:seed 
** Execute test 
** Invoke test:run (first_time) 
** Invoke test:units (first_time) 
** Invoke test:prepare (first_time) 
** Invoke db:test:prepare (first_time) 
** Invoke db:abort_if_pending_migrations (first_time) 
** Invoke environment 
** Invoke db:migrate:load (first_time) 
** Invoke environment 
** Execute db:migrate:load 
** Execute db:abort_if_pending_migrations 
** Execute db:test:prepare 
** Execute db:drop 
** Execute db:create 
** Execute db:load 
** Invoke db:schema:load (first_time) 
** Invoke environment 
** Execute db:schema:load 
** Execute test:prepare 
** Execute test:units 
** Invoke test:functionals (first_time) 
** Invoke test:prepare 
** Execute test:functionals 
** Invoke test:integration (first_time) 
** Invoke test:prepare 
** Execute test:integration 
** Execute test:run 
** Invoke test:decorators (first_time) 
** Invoke test:prepare 
** Execute test:decorators 
** Execute test:cleanup 
** Execute db:test:drop 
** Execute db:drop 
** Execute db:test_project:drop 
** Invoke db:drop (first_time) 
** Invoke environment 
** Execute db:drop 
Run options: --seed 19360 

# Running tests: 

EE.... 

Finished tests in 0.037493s, 160.0278 tests/s, 106.6852 assertions/s. 

正如你可以看到任務調用,以便但測試完成之前執行清理任務。任何想法來解決這個問題?

回答

2

事實證明,這與耙子有關,而與Minitest執行測試的方式有關。我在問題中提到,似乎rake任務正在以正確的順序被調用,但測試由於某種原因而稍後執行。原因是Minitest使用紅寶石內核方法at_exit來執行測試。在調用rake test時讀取測試文件,但所有測試都在ruby程序結束時執行,即使在我後續的rake任務之後也是如此。這裏有一篇博客文章更詳細地解釋了這個問題:http://blog.arkency.com/2013/06/are-we-abusing-at-exit/

+0

你有沒有解決這個問題? – neeraj

2

嘗試使用耙標準語法調用多個任務:

task better_test: ["test:setup", "test", "test:cleanup"] 

也許這將解決你的問題。

另外,似乎Rake實際上在執行它們之前建立了它應該運行的所有任務的列表,並且只運行一次。例如:

task :a 
task :b 
task :c 

task better_test: ["a", "b", "c", "b"] 

結果:

$ rake better_test -t 
** Invoke better_test (first_time) 
** Invoke a (first_time) 
** Execute a 
** Invoke b (first_time) 
** Execute b 
** Invoke c (first_time) 
** Execute c 
** Execute better_test 

正如你看到的,任務b只運行一次(第一個)。我相信你的test:setuptest莫名其妙取決於test:cleanup任務。所以它比預期的要早。

+0

德米特里,這是一個好主意,但結果相同。我真的覺得這與耙子更不相干,更多的是與minitest如何執行測試有關。 –

+0

我在回答中增加了一些其他的想法,可能是你的'test:setup'或'test'已經調用了清理(不知道爲什麼,但也許你或者一些gem增加了依賴來運行'cleanup')它根本不叫第二次。 –

0
Rake::Task["test"].enhance do 
    Rake::Task["test:cleanup"].invoke 
end 
+0

感謝Marcin。我也嘗試過這個路由,但是執行清理任務後測試仍然運行。它們是按順序調用的,但第二個任務不會等待第一個任務完成。 –