2015-11-19 2 views
3

Я пытаюсь создать задачу rake для проекта Rails 4.0.2 (Ruby 2.2.3), который создает тестовую базу данных вместе с посещением, затем запускает набор тестов и наконец, очищается, отбрасывая тестовую базу данных. Вот простой пример ниже:Выполнение задачи рейка после `rake test`

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

Задача выше делает вызвать test:setup реки задачи (создать/засеять тестовую базу данных), а затем вызывает задачу test грабель, и, наконец, вызывает задачу test:cleanup грабель. Однако проблема заключается в том, что последний test:cleanup вызывается перед завершением работы rake-задачи test. Нужно ли в любом случае вызывать задачу грабли очистки после завершения предыдущих задач?

Вот выход из запуска задачи с трассой:

$ 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 выполняет свои тесты. Я упомянул в вопросе, что оказалось, что задачи рейка вызываются в правильном порядке, но тесты были выполнены позже по какой-то причине. Причина в том, что Minitest использует метод Ruby Kernel at_exit для выполнения тестов. Тестируемые файлы считываются во время вызова rake test, но все тесты выполняются в конце рубиновой программы даже после моих последующих рейк-задач. Вот статья в блоге, которая объясняет проблему более подробно: 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:setup или test как-то зависит от задачи test:cleanup. Поэтому он называется раньше, чем ожидалось.

+0

Дмитрий, это хорошая мысль, но такой же результат. Я действительно чувствую, что он имеет меньше общего с граблями и больше связан с тем, как minitest выполняет тесты. –

+0

Я добавил в ответ еще одну идею: возможно, ваш тест: setup или 'test' уже вызвал очистку (не уверен, почему, но, может быть, вы или какой-то gem добавили зависимость для запуска' cleanup'), поэтому он не называется во второй раз. –

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

Спасибо Marcin. Я тоже пробовал этот маршрут, но тесты все еще выполняются после выполнения задачи очистки. Они вызываются по порядку, но вторая задача не дождалась завершения первого. –

Смежные вопросы