在Rakefile中动态生成Rake测试任务(基于现有测试文件)

jas*_*res 5 ruby rakefile rake-task

我正在基于Rakefile中的现有测试文件动态生成测试任务.考虑您有以模式命名的各种单元测试文件test_<name>.rb.所以我正在做的是创建一个以'test'命名空间内的文件名命名的任务.使用下面的代码,我可以调用所有测试rake test:<name>

require 'rake/testtask'

task :default => 'test:all'

namespace :test do

  desc "Run all tests"
  Rake::TestTask.new(:all) do |t|
    t.test_files = FileList['test_*.rb']
  end

  FileList['test_*.rb'].each do |task|
    name = task.gsub(/test_|\.rb\z/, '')
    desc "Run #{name} tests"
    Rake::TestTask.new(:"#{name}") do |t|
      t.pattern = task
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

上面的代码工作,它似乎太多代码用于简单的任务生成.我仍然没有找到一种方法将一些描述文本打印到控制台puts "Running #{name} tests:"

有比上述方法更优雅的方式吗?

编辑:我真正期望得到的是动态定义任务的循环的替代方案,但我想rake lib没有提供任何帮助,所以我坚持循环.

小智 13

这是使用Rake中的规则解决问题的另一种方法.

当rake想要构建"X"时,rake规则会启动,并且它会找到一条规则,即"构建X,使用Y".我们将设置一个规则,当某人以"test:XXX"格式指定目标时触发该规则,它将尝试使用名为"test/test_XXX.rb"的文件.

require 'rake/testtask'

task :default => 'test:all'

TEST_FILES = FileList['test/test_*.rb']

namespace :test do
  desc "Run all tests"
  Rake::TestTask.new(:all) do |t|
    t.test_files = TEST_FILES
  end

  rule /^test:/ => lambda { |tn| "test/test_%s.rb" % tn.gsub(/^test:/,'') } do |rule|
    ruby rule.source
  end
end
Run Code Online (Sandbox Code Playgroud)

假设您有一个名为"test/test_my_code.rb"的测试文件.要执行该测试文件,只需键入:

rake test:my_code
Run Code Online (Sandbox Code Playgroud)

只要存在以"test:"开头且无法与任何其他任务匹配的目标,就会触发该规则.然后它查找lamdba函数给出的文件.lambda将目标名称"test:XXX"转换为文件名"test/test_XXX.rb".如果文件名存在,则执行规则的主体.

规则的主体只是将测试文件作为可执行文件运行.这通常足以运行单个文件的测试.如果需要将库路径(例如"lib")添加到测试的加载路径,则可以将规则体更改为类似

ruby "-Ilib", rule.source
Run Code Online (Sandbox Code Playgroud)

此显式循环解决方案与显式循环解决方案之间的另一个区别是rake不会打印出规则的描述,因此"rake -T"输出将不包括其输出中的各个测试.

我不知道这是否比原版更好,但它确实给你一些选择.