[英]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:cleanup
在test
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:setup
或test
以某种方式取决于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.