Jef*_*f D 14 ruby rake rspec metaprogramming cucumber
我是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
Run Code Online (Sandbox Code Playgroud)
进入我的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
Run Code Online (Sandbox Code Playgroud)
但是当我尝试在rspec中运行时,我收到以下错误.
'Rake task install_grapevine中的ArgumentError应该安装到mygrapevine目录'
错误的参数数量(1表示2)/spec/spec_helper.rb:21:in
instance_eval' /spec/spec_helper.rb: 21:inblock in invoke!' /spec/spec_helper.rb:20:在each' /spec/spec_helper.rb: 20:in调用!' /spec/tasks/rakefile_spec.rb:12:in`block(2 levels)in'
不幸的是,我带着一个星期的红宝石,所以元编程的东西已经超出了我的想象.有人能指出我正确的方向吗?
Jac*_*lla 19
这对我有用:(Rails3/Ruby 1.9.2)
When /^the system does it's automated tasks$/ do
require "rake"
@rake = Rake::Application.new
Rake.application = @rake
Rake.application.rake_require "tasks/cron"
Rake::Task.define_task(:environment)
@rake['cron'].invoke
end
Run Code Online (Sandbox Code Playgroud)
在此处替换您的rake任务名称,如果您的加载路径中没有lib文件夹,请注意您的require可能是"lib/tasks/cron".
我同意你应该只在Rake任务中做最少的工作,并将其余部分推送到模型以便于测试.话虽如此,我认为在集成测试期间确保代码在我的cron任务中实际运行非常重要,所以我认为对rake任务进行非常温和的测试是合理的.
Ste*_*nev 16
由于测试rake对我来说太多了,我倾向于解决这个问题.每当我发现自己需要测试的漫长的rake任务时,我会创建一个模块/类lib/并从那里移动任务中的所有代码.这将任务留给了一行Ruby代码,它代表了一些更可测试的东西(类,模块,你可以命名).唯一未经测试的是rake任务是否调用正确的代码行(并传递正确的参数),但我认为这没关系.
告诉我们哪个是你的第21行可能是有用的spec_helper.rb.但考虑到您发布的办法中挖掘深耙(指其实例变量),我将完全放弃它为我在上一段中提出.
小智 5
我花了一点时间吃黄瓜来执行一个rake任务,所以我想我会分享我的方法.注意:这是使用Ruby 2.0.0和Rake 10.0.4,但我认为自从以前的版本以来,行为没有改变.
这有两个部分.第一个很简单:通过正确设置实例,Rake::Application我们可以通过调用#[](例如rake['data:import'])来访问它上面的任务.一旦我们有了一个任务,我们就可以通过调用#invoke和传入参数来运行它(例如rake['data:import'].invoke('path/to/my/file.csv').
第二部分更尴尬:正确设置要使用的实例Rake::Application.一旦我们完成,require 'rake'我们就可以访问该Rake模块.它已经有一个应用程序实例,可用Rake.application,但尚未设置 - 它不知道我们的任何rake任务.它,然而,知道在哪里可以找到我们的Rake文件,假设我们使用标准的文件名称之一:rakefile,Rakefile,rakefile.rb或Rakefile.rb.
要加载rakefile,我们只需要调用#load_rakefile应用程序,但在我们可以做之前我们需要调用#handle_options.调用使用默认值#handle_options填充options.rakelib.如果options.rakelib没有设置,那么该#load_rakefile方法将会爆炸,因为它预计options.rakelib是可枚举的.
这是我最终得到的帮手:
module RakeHelper
def run_rake_task(task_name, *args)
rake_application[task_name].invoke(*args)
end
def rake_application
require 'rake'
@rake_application ||= Rake.application.tap do |app|
app.handle_options
app.load_rakefile
end
end
end
World(RakeHelper)
Run Code Online (Sandbox Code Playgroud)
将该代码弹出到文件中features/support/,然后run_rake_task在您的步骤中使用,例如:
When /^I import data from a CSV$/ do
run_rake_task 'data:import', 'path/to/my/file.csv'
end
Run Code Online (Sandbox Code Playgroud)