在 rspec(和 cucumber)中测试 rake 任务
我是 Ruby 新手,一直在尝试学习 Rake、RSpec 和 Cucumber。我找到了一些可以帮助我测试 Rake 任务的代码,但我无法让它正常工作。有人告诉我这里: http://blog.codahale.com /2007/12/20/rake-vs-rspec-fight/ 将其
def describe_rake_task(task_name, filename, &block)
require "rake"
describe "Rake task #{task_name}" do
attr_reader :task
before(:all) do
@rake = Rake::Application.new
Rake.application = @rake
load filename
@task = Rake::Task[task_name]
end
after(:all) do
Rake.application = nil
end
def invoke!
for action in task.instance_eval { @actions }
instance_eval(&action)
end
end
instance_eval(&block)
end
end
放入我的 spec_helper.rb 文件中。
我已经设法取出这段代码并在我的黄瓜步骤中运行它,如下所示:
When /^I run the update_installers task$/ do
@rake = Rake::Application.new
Rake.application = @rake
load "lib/tasks/rakefile.rb"
@task = Rake::Task["update_installers"]
for action in @task.instance_eval { @actions }
instance_eval(&action)
end
instance_eval(&block)
Rake.application = nil
end
但是当我尝试在 rspec 中运行时,出现以下错误。
“Rake 任务中的参数错误” install_grapevine 应该安装到 mygrapevine 目录'
参数数量错误(1 为 2) /spec/spec_helper.rb: 21:in
instance_eval' /spec/spec_helper.rb: 21:in
调用中的块!' /spec/spec_helper.rb: 20:ineach' /spec/spec_helper.rb: 20:in 调用!' /spec/tasks/rakefile_spec.rb:12:in `块(2 级)中 '
不幸的是,我已经掌握了 Ruby 不到一周的时间,所以元编程的东西超出了我的能力范围。有人能指出我正确的方向吗?
I'm new to Ruby, and I've been trying to learn Rake, RSpec, and Cucumber. I found some code that will help me test my Rake tasks, but I'm having trouble getting it to work. I was told here: http://blog.codahale.com/2007/12/20/rake-vs-rspec-fight/ to drop this:
def describe_rake_task(task_name, filename, &block)
require "rake"
describe "Rake task #{task_name}" do
attr_reader :task
before(:all) do
@rake = Rake::Application.new
Rake.application = @rake
load filename
@task = Rake::Task[task_name]
end
after(:all) do
Rake.application = nil
end
def invoke!
for action in task.instance_eval { @actions }
instance_eval(&action)
end
end
instance_eval(&block)
end
end
into my spec_helper.rb file.
I've managed to take this code out and run it in my cucumber steps like this:
When /^I run the update_installers task$/ do
@rake = Rake::Application.new
Rake.application = @rake
load "lib/tasks/rakefile.rb"
@task = Rake::Task["update_installers"]
for action in @task.instance_eval { @actions }
instance_eval(&action)
end
instance_eval(&block)
Rake.application = nil
end
but when I try to get things working in rspec, I get the following error.
ArgumentError in 'Rake task
install_grapevine should install to
the mygrapevine directory'wrong number of arguments (1 for 2)
/spec/spec_helper.rb: 21:ininstance_eval'
block in invoke!'
/spec/spec_helper.rb: 21:in
/spec/spec_helper.rb: 20:ineach'
invoke!'
/spec/spec_helper.rb: 20:in
/spec/tasks/rakefile_spec.rb:12:in `block (2 levels) in
'
Unfortunately, I've got just under a week of ruby under by belt, so the metaprogramming stuff is over my head. Could anyone point me in the right direction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这对我有用:(Rails3/Ruby 1.9.2)
在此处替换您的 rake 任务名称,并请注意,如果您的加载路径中没有 lib 文件夹,您的要求可能是“lib/tasks/cron”。
我同意您应该只在 Rake 任务中做最少的工作,并将其余的工作推到模型中以便于测试。话虽如此,我认为在集成测试期间确保代码在我的 cron 任务中实际运行非常重要,因此我认为对 rake 任务进行非常温和的测试是合理的。
This works for me: (Rails3/ Ruby 1.9.2)
Substitute your rake task name here and also note that your require may be "lib/tasks/cron" if you don't have the lib folder in your load path.
I agree that you should only do minimal work in the Rake task and push the rest to models for ease of testing. That being said I think it's important to ensure that the code is ACTUALLY run in my cron tasks during my integration tests so I think very mild testing of the rake tasks is justified.
由于测试耙子对我来说太多了,所以我倾向于解决这个问题。每当我发现自己要测试一个很长的 rake 任务时,我都会在 lib/ 中创建一个模块/类,并将任务中的所有代码移到那里。这将任务留给了一行 Ruby 代码,将其委托给更可测试的东西(类、模块,凡是你能想到的)。唯一尚未测试的是 rake 任务是否调用正确的代码行(并传递正确的参数),但我认为这是可以的。
告诉我们您的
spec_helper.rb
的第 21 行可能会很有用。但考虑到您发布的方法深入挖掘了 rake(指其实例变量),我将完全放弃它,因为我在上一段中建议了它。Since testing rake is just too much for me, I tend to move this problem around. Whenever I find myself with a long rake task that I want to test, I create a module/class in
lib/
and move all the code from the task there. This leaves the task to a single line of Ruby code, that delegates to something more testable (class, module, you name it). The only thing that remains untested is whether the rake task invokes the right line of code (and passes the right parameters), but I think that is OK.It might be useful to tell us which is the 21nd line of your
spec_helper.rb
. But given that the approach you posted digs deep in rake (referring to its instance variables), I would entirely abandon it for what I suggested in the previous paragraph.我刚刚花了一点时间让黄瓜运行耙子任务,所以我想我应该分享我的方法。注意:这是使用 Ruby 2.0.0 和 Rake 10.0.4,但我认为自以前的版本以来该行为没有改变。
这有两个部分。第一个很简单:通过正确设置的
Rake::Application
实例,我们可以通过调用#[]
访问其上的任务(例如rake['数据:导入']
)。一旦我们有了任务,我们就可以通过调用#invoke并传入参数来运行它(例如rake['data:import'].invoke('path/to/my/file. csv')第二部分更尴尬:在完成
require 'rake'
后正确设置要使用的Rake::Application
实例。 code> 我们可以访问Rake
模块,它已经有一个应用程序实例,可以从Rake.application
获取,但它尚未设置 - 它不知道。但是,假设我们使用了标准文件名之一:rakefile
、Rakefile
、,它确实知道在哪里可以找到我们的 Rakefile。 >rakefile.rb
或Rakefile.rb
要加载 rakefile,我们只需在应用程序上调用
#load_rakefile
,但在此之前我们需要调用#handle_options
。调用#handle_options
会使用默认值填充options.rakelib
。 > 未设置,那么#load_rakefile
方法将会崩溃,因为它期望options.rakelib
是可枚举的。这是我最终得到的助手:
将该代码弹出到
features/support/
中的文件中,然后在您的步骤中使用run_rake_task
,例如:I've just spent a little while getting cucumber to run a rake task so I thought I'd share my approach. Note: This is using Ruby 2.0.0 and Rake 10.0.4, but I don't think the behaviour has changed since previous versions.
There are two parts to this. The first is easy: with a properly set up instance of
Rake::Application
then we can access tasks on it by calling#[]
(egrake['data:import']
). Once we have a task we can run it by calling#invoke
and passing in the arguments (egrake['data:import'].invoke('path/to/my/file.csv')
.The second part is more awkward: properly setting up an instance of
Rake::Application
to work with. Once we've donerequire 'rake'
we have access to theRake
module. It already has an application instance, available fromRake.application
, but it's not yet set up — it doesn't know about any of our rake tasks. It does, however, know where to find our Rakefile, assuming we've used one of the standard file names:rakefile
,Rakefile
,rakefile.rb
orRakefile.rb
.To load the rakefile we just need to call
#load_rakefile
on the application, but before we can do that we need to call#handle_options
. The call to#handle_options
populatesoptions.rakelib
with a default value. Ifoptions.rakelib
is not set then the#load_rakefile
method will blow up, as it expectsoptions.rakelib
to be enumerable.Here's the helper I've ended up with:
Pop that code into a file in
features/support/
and then just userun_rake_task
in your steps, eg:自发布正确答案以来,行为可能已发生变化。我在执行需要运行相同 rake 任务的两个场景时遇到问题(尽管我使用
.execute
而不是.invoke
,但只有一个正在执行)。我想分享我解决这个问题的方法(Rails 4.2.5 和 Ruby 2.3.0)。我用
@rake
标记了所有需要 rake 的场景,并且定义了一个钩子来仅设置 rake 一次。(这里建议使用全局变量: https: //github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)
在步骤定义中,我简单地调用了
$rake
欢迎任何反馈。
The behavior might have changed since the correct answer was posted. I was experiencing problems executing two scenarios that needed to run the same rake task (only one was being executed despite me using
.execute
instead of.invoke
). I thought to share my approach to solve the issue (Rails 4.2.5 and Ruby 2.3.0).I tagged all the scenarios that require rake with
@rake
and I defined a hook to setup rake only once.(Using a global variable is suggested here: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)
In the step definition I simply called
$rake
Any feedback is welcome.