Ruby on rails (显然)两个rake任务的相同测试;只有一个通过
我正在尝试用rspec为同一个文件中定义的两个rake任务编写测试(在rails3.0.11项目中)。由于某种原因,他们中只有一个人通过了考试。我已经写了一个小演示来抽象出任务的实际内容,同样的事情也发生了。当从命令行使用Ruby on rails (显然)两个rake任务的相同测试;只有一个通过,ruby-on-rails,rspec,rake,Ruby On Rails,Rspec,Rake,我正在尝试用rspec为同一个文件中定义的两个rake任务编写测试(在rails3.0.11项目中)。由于某种原因,他们中只有一个人通过了考试。我已经写了一个小演示来抽象出任务的实际内容,同样的事情也发生了。当从命令行使用rake调用这两个任务时,这两个任务都可以工作。发生什么事?这是我的演示: lib/tasks/demo_tasks.rake namespace :demo do task :test => :environment do puts "test!" en
rake
调用这两个任务时,这两个任务都可以工作。发生什么事?这是我的演示:
lib/tasks/demo_tasks.rake
namespace :demo do
task :test => :environment do
puts "test!"
end
task :test_two => :environment do
puts "second test!"
end
end
spec/lib/tasks/demo_spec.rb
require 'spec_helper'
require 'rake'
describe "test tasks" do
let(:rake) do
app = Rake::Application.new
app.options.silent = true
app
end
before :each do
Rake.application = rake
Rake.application.rake_require 'lib/tasks/demo_tasks',
[Rails.root.to_s]
Rake::Task.define_task :environment
end
describe "demo:test" do
it "runs" do
rake["demo:test"].invoke
end
end
describe "demo:test_two" do
it "also_runs" do
rake["demo:test_two"].invoke
end
end
end
test tasks
demo:test
test!
runs
demo:test_two
also_runs (FAILED - 1)
Failures:
1) test tasks demo:test_two also_runs
Failure/Error: rake["demo:test_two"].invoke
RuntimeError:
Don't know how to build task 'demo:test_two'
# ./spec/lib/tasks/demo_spec.rb:26:in `block (3 levels) in <top (required)>'
rspec spec/lib/tasks/demo_spec.rb
require 'spec_helper'
require 'rake'
describe "test tasks" do
let(:rake) do
app = Rake::Application.new
app.options.silent = true
app
end
before :each do
Rake.application = rake
Rake.application.rake_require 'lib/tasks/demo_tasks',
[Rails.root.to_s]
Rake::Task.define_task :environment
end
describe "demo:test" do
it "runs" do
rake["demo:test"].invoke
end
end
describe "demo:test_two" do
it "also_runs" do
rake["demo:test_two"].invoke
end
end
end
test tasks
demo:test
test!
runs
demo:test_two
also_runs (FAILED - 1)
Failures:
1) test tasks demo:test_two also_runs
Failure/Error: rake["demo:test_two"].invoke
RuntimeError:
Don't know how to build task 'demo:test_two'
# ./spec/lib/tasks/demo_spec.rb:26:in `block (3 levels) in <top (required)>'
测试任务
演示:测试
测试!
跑
演示:测试二
还运行\u(失败-1)
失败:
1) 测试任务演示:测试2也运行
失败/错误:rake[“demo:test_two”]。调用
运行时错误:
不知道如何构建任务“演示:测试2”
#./spec/lib/tasks/demo_spec.rb:26:in'block(3层)in'
简而言之:将之前的更改为之前的所有(而不是:每个)
或:将空数组作为第三个参数传递给rake\u require
Rake.application.rake_require 'lib/tasks/demo_tasks',
[Rails.root.to_s],
[]
详细信息
def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
fn = file_name + ".rake"
return false if loaded.include?(fn)
...
$”
是一个Ruby特殊变量,用于保存由require
加载的模块数组
Rake.application.rake_require 'lib/tasks/demo_tasks',
[Rails.root.to_s],
[]
如果您不传递可选参数,rake\u require
将使用Ruby加载的模块数组。这意味着该模块不会再次加载:Ruby知道该模块已加载,rake检查Ruby知道什么,并且它是每个测试的新rake实例
切换到之前:所有
都有效,因为这意味着让
块只运行一次:一个rake实例,一个模块加载,每个人都很高兴
总之,为什么要重新加载两次rake环境呢?您的目标是测试您的任务,这并不需要每个规范都有一个新的rake上下文
您可以完全消除本地规范,但代价是每个规范中都有一些细微的冗长:
describe "test tasks" do
before :all do
Rake.application = Rake::Application.new
Rake.application.rake_require 'lib/tasks/demo_tasks', [Rails.root.to_s]
Rake::Task.define_task :environment
end
describe "demo:test" do
it "runs" do
Rake::Task["demo:test"].invoke
end
end
end
您可以在before
块中定义一个实例变量,以避免Rake::Task
引用:
before :all do
@rake = Rake::Application.new
Rake.application = @rake
Rake.application.rake_require 'lib/tasks/demo_tasks', [Rails.root.to_s]
Rake::Task.define_task :environment
end
describe "demo:test" do
it "runs" do
@rake["demo:test"].invoke
在我看来,有很多原因不太可取。一个流行的搜索引擎把我带到了这里,就像在我的例子中,当一个给定的测试多次使用#invoke
时,我看到测试失败。下面的解决方案基于@dave newtown的答案
出现此问题的原因是,在编写时(Rake v12),#invoke
只运行一次任务,例如:
RSpec.description“demo:test”do
它“跑”了吗
expect(SomethingWeAreInvoking).到eql(proofifwas调用)
Rake::Task[“demo:test”]。调用
结束
它“跑”了吗
expect(SomethingWeAreInvoking).到eql(proofifwas调用)
Rake::Task[“demo:test”]。调用
结束
结束
如果测试写得很好并且任务调用正确,那么它可能会通过第一个运行的任何一个,但是第二个it
总是会失败,就像在给定的Rake中一样。应用程序,使用#invoke
只会运行一次任务。在任务内部显然记住状态之前已经运行过eRake.application
实例
是的,这确实意味着至少在测试的RakeV12下,很多在线文章显示了如何测试Rake任务是不正确的,或者说没有问题,因为它们在示例中只显示了对任何给定任务的单个测试
我们可以使用Rake的#execute
,但这不会运行依赖的任务,因此会导致其自身的一组问题,并使我们更加远离测试Rake堆栈,就好像它是在命令行上调用的一样
取而代之的是,将已被接受的答案与在线的其他信息混合在一起,产生了以下替代方案:
require'spec\u helper'
需要“耙子”
RSpec.description“演示:测试”do
以前:每个人都做
Rake.application=Rake::application.new
Rake.application.Rake_需要'lib/tasks/demo_tasks',[Rails.root.to_s],]
Rake::Task.define_任务(:环境)
结束
它“跑”了吗
expect(SomethingWeAreInvoking).到eql(proofifwas调用)
Rake.application.invoke_任务('demo.test')
结束
它“使用参数”do运行
expect(SomethingWeAreInvoking).到eql(proofifwas调用)
Rake.application.invoke_任务('demo.test[42]”)
结束
结束
- 它在每个
之前准备Rake
每次都会创建一个新的Rake.application
;这意味着我们可以在任意数量的测试中使用invoke
,尽管在任何单个测试中只能使用一次
如果我们只使用Rake.application
开箱即用的实例,我们就可以编写Rake.application.Rake\u require'tasks/demo\u tasks'
,因为所有路径等都已设置,但由于我们肯定需要为每个测试创建一个新的Rake应用实例,以避免在测试中“弄脏”其状态,因此“长柄”“需要来自@dave newtown的表格
我使用Rake.application.invoke_task
而不是Rake::task[…]。invoke
。这使得参数的语法与Rake命令行上使用的语法相同,我认为这是测试使用参数的任务的更“准确”和自然的方法
是的,这确实意味着至少在测试的RakeV12下,许多在线文章显示了如何测试Rake任务是不正确的,或者说没有问题,因为它们在示例中只显示了对任何给定任务的单个测试。很可能早期的Rake版本没有这样做,所以这些文章在编写时是正确的
希望有人觉得这有帮助
参考文章:
- -线索位于“如果需要,请调用任务”。先调用先决条件”(我的重点)
- 比较-“执行与此任务相关的操作”,未提及“如果需要”或先决条件
- 搜索引擎会产生诸如
(搜索引擎提示:测试rake rspec测试调用运行在