在rspec(和cucumber)中测试一个rake任务

14

我是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文件中。

我已经成功将此代码提取出来,在我的cucumber步骤中运行,如下所示:

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:instance_eval' /spec/spec_helper.rb:21:invoke!'中的块 /spec/spec_helper.rb:20:each' /spec/spec_helper.rb:20:invoke!' /spec/tasks/rakefile_spec.rb:12:在`block (2 levels) in'处

不幸的是,我只学了不到一周的 Ruby,所以元编程的东西超出了我的理解范围。有人能指点一下我吗?


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

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

在这里替换您的rake任务名称,同时请注意,如果您的load路径中没有lib文件夹,则require可能为“lib/tasks/cron”。

我同意您应该仅在Rake任务中进行最小工作,并将其余工作推到模型中以便于测试。也就是说,我认为在我的集成测试中确保代码实际上在我的cron任务中运行非常重要,因此我认为对rake任务进行轻微的测试是有道理的。


3
在我的测试中,我倾向于使用“执行”而不是“调用”,特别是如果许多步骤依赖于测试Rake任务,这样可以避免仅能运行Rake任务一次的问题。参考:https://dev59.com/Z3E85IYBdhLWcg3w8IbK - Luis R.

16

由于测试rake对我来说太困难了,我倾向于将这个问题搬到别处。每当我发现自己有一个想要测试的长的rake任务时,我会在lib/中创建一个模块/类,并将所有代码从任务中移动到那里。这将任务变成单行Ruby代码,委托给更容易测试的东西(类、模块等)。唯一未经测试的是rake任务是否调用了正确的代码行(并传递了正确的参数),但我认为这是可以接受的。

告诉我们你的spec_helper.rb的第21行可能会很有用。但考虑到你所发布的方法深入挖掘了rake(引用其实例变量),我建议完全放弃它,转而采用我在前一段中提出的方法。


5
我刚刚花了一点时间让cucumber运行一个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任务的信息。但是,它确实知道在哪里可以找到我们的Rakefile,假设我们已经使用了其中一个标准文件名:rakefileRakefilerakefile.rbRakefile.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)

将该代码放入位于features/support/目录下的文件中,然后在你的步骤中使用run_rake_task,例如:
When /^I import data from a CSV$/ do
  run_rake_task 'data:import', 'path/to/my/file.csv'
end

3
行为可能已经发生变化,因为正确答案发布后。我遇到了执行两个需要运行相同rake任务的场景的问题(尽管我使用.execute而不是.invoke),只有一个被执行。我想分享我的解决方法(Rails 4.2.5和Ruby 2.3.0)。
我用@rake标记了所有需要rake的场景,并定义了一个钩子来设置一次rake。
# hooks.rb
Before('@rake') do |scenario|
  unless $rake
    require 'rake'
    Rake.application.rake_require "tasks/daily_digest"
    # and require other tasks
    Rake::Task.define_task(:environment)
    $rake = Rake::Task
  end
end

在这里建议使用全局变量: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once

在步骤定义中,我只是调用了$rake

# step definition
Then(/^the daily digest task is run$/) do
  $rake['collector:daily_digest'].execute
end

任何反馈都受欢迎。

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