在Rspec测试中运行Rake任务

58

我正在构建一个集成测试套件,并且有一部分逻辑需要一个干净的数据库。如何在我的一个测试中运行db:test:purge任务?

我使用的是:ruby 1.9.2,rails 3.0.9,rspec 2.6


没有使用 RSpec 的相同操作:https://dev59.com/TnVD5IYBdhLWcg3wXaYd - Ciro Santilli OurBigBook.com
6个回答

62

您可以按照以下方式调用Rake任务:

require 'rake'
Rake::Task[name].invoke

在这种情况下,这将导致以下代码:
require 'rake'
Rake::Task['db:test:purge'].invoke

搞定了。谢谢。我一开始也把任务名称搞错了,这让我有些困惑。在Rails 3中,rake test:prepare似乎解决了问题。 - xentek
1
@jim 很好的建议。在这些情况下,您可以使用<code>Rake::Task[name].execute</code>,但是您需要确保满足任何依赖项(例如 :environment),因为在使用此方法调用任务时不会运行它们。 - xentek
17
有时候,通过调用MyRailsApp::Application.load_tasks来加载任务是必要的。 - Erdem Gezer
3
使用MyRailsApp::Application.load_tasks会导致测试污染问题,在测试套件中如果之前已经调用过load_tasks,则我的Rake任务将被多次调用。使用Rake.application.rake_requireRake::Task.define_task(:environment)可以避免这个问题。 - yuval
1
请注意,invoke仅会在每次load_tasks中运行一次任务。如果需要多次运行,请使用execute - B Seven
显示剩余2条评论

38

经过我尝试,原先被批准的答案并不能满足我的需求,因为我需要执行自己编写的rake任务。

以下是我的解决方案:

将其放置在spec文件的顶部

require 'rake'

将以下代码放置在需要执行自定义rake任务的位置,例如从文件example.rake运行rake update_data


load File.expand_path("../../../lib/tasks/example.rake", __FILE__)
# make sure you set correct relative path 
Rake::Task.define_task(:environment)
Rake::Task["update_data"].invoke

我的环境:

rails (4.0.0)
ruby (2.0.0p195)
rspec-core (2.14.7) 
rspec-expectations (2.14.3) 
rspec-mocks (2.14.4) 
rspec (2.14.1) 
rspec-rails (2.14.0) 

2
嗨,我使用了 Rails.application.load_tasks 代替 require 'rake'。这是一个好的解决方案吗? - coderVishal
Rake::Task.define_task(:environment) for the win in avoiding RuntimeError: Don't know how to build task 'environment' (see --tasks) - s2t2
5
我使用Rake.application.rake_require "tasks/task-name"来加载特定的任务进行测试,而不是使用Rails.application.load_tasks加载所有任务(Rails 5,Rspec 3.5)。 - Steve

18
如果我们需要使用多个 rake 任务,我们可以添加。
require "rake"
Rails.application.load_tasks

然后只需调用任何任务。

Rake::Task['sync:process_companies'].invoke

虽然我不能确认它是否更慢,因为它加载了所有的任务。


4
使用Rails.application.load_tasks会导致测试污染问题,如果在同一套件中之前已经调用了load_tasks,则我的Rake任务将被多次调用。使用上述解决方案可以避免这个问题。 - yuval

4

对于我来说(Rails 6)

Rails.application.load_tasks
Rake::Task['app:sync'].invoke

=> 我的情况下不需要require


4
许多上面的答案对我运行单个规范都有效。但是,当运行单个rake任务的多个规范时,我需要采取额外的步骤。
在每个规范之后,我必须运行Rake::Task.clear,因为(出于某种原因)如果已将任务注册为already_invoked(即如果Rake::Task ['my_task'].already_invoked返回true),则任务不会再次运行。
我在我的rake任务规范中添加了以下行:
after { Rake::Task.clear }

当运行同一个rake任务的多个测试时,一切都按预期工作。


1
Rake::Task#reenable - akostadinov

2
我们需要同时要求任务。
require 'rake'
Rake.application.rake_require 'tasks/new_adapter'

接下来,只需调用该任务即可

Rake::Task['new:adapter'].invoke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接