简体   繁体   English

在'rake test`之后执行rake任务

[英]Executing a rake task after `rake test`

I'm trying to create a rake task for a Rails 4.0.2 (Ruby 2.2.3) project that creates the test database along with seeding, then runs the test suite, and finally cleanups afterwards by dropping the test database. 我正在尝试为Rails 4.0.2(Ruby 2.2.3)项目创建一个rake任务,该项目创建测试数据库以及种子,然后运行测试套件,最后通过删除测试数据库进行清理。 Here's a simple example below: 这是一个简单的例子如下:

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

The task above does invoke the test:setup rake task (create/seed the test database), then invokes the test rake task, and finally invokes the test:cleanup rake task. 上面的任务确实调用了test:setup rake任务(创建/播种测试数据库),然后调用test rake任务,最后调用test:cleanup rake任务。 The problem however is that the last test:cleanup is invoked before the test rake task is finished running. 但问题是最后一次test:cleanuptest rake任务完成运行之前调用test:cleanup Is there anyway to invoke the cleanup rake task after the previous tasks are complete? 无论如何在上一个任务完成后调用清理rake任务?

Here's the output from running the task with trace: 以下是使用trace运行任务的输出:

$ 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.

As you can see the tasks are invoked in order but the cleanup task is executed before the tests have completed. 如您所见,按顺序调用任务,但在测试完成之前执行清理任务。 Any ideas to address this? 有什么想法解决这个问题?

As it turns out, this was less to do with rake and more to do with the way Minitest executes its tests. 事实证明,这与rake关系不大,而与Minitest执行测试的方式有关。 I mentioned in the question it appeared that the rake tasks were being invoked in the correct order but the tests were executed later for some reason. 我在问题中提到,似乎rake任务以正确的顺序被调用,但测试由于某种原因后来执行。 The reason is because Minitest utilizes the ruby Kernel method at_exit for execution of the tests. 原因是Minitest利用ruby Kernel方法at_exit来执行测试。 The test files are read in at the time the rake test was invoked but all tests are executed at the end of the ruby program, even after my subsequent rake tasks. 在调用rake test时读入测试文件,但所有测试都在ruby程序结束时执行,即使在我后续的rake任务之后也是如此。 Here's a blog article that explains the issue in more detail: http://blog.arkency.com/2013/06/are-we-abusing-at-exit/ . 这是一篇博客文章,更详细地解释了这个问题: http//blog.arkency.com/2013/06/are-we-abusing-at-exit/

Try to use the rake standard syntax for calling multiple tasks: 尝试使用rake标准语法来调用多个任务:

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

Maybe this will resolve you problem. 也许这会解决你的问题。

Also, it seems that Rake actually builds the list of all tasks it should run before executing them, and run each one only once. 此外,似乎Rake实际上构建了在执行它们之前应该运行的所有任务的列表,并且只运行一次。 For example: 例如:

task :a
task :b
task :c

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

results in: 结果是:

$ 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

As you see, the task b is run only once (the first one). 如您所见,任务b仅运行一次(第一个)。 I believe that your test:setup or test somehow depend on test:cleanup task. 我相信你的test:setuptest以某种方式取决于test:cleanup任务。 So it is called earlier than expected. 所以它比预期的要早。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM