Генерировать тестовые задачи Rake динамически (на основе существующих тестовых файлов) в Rakefile - PullRequest
5 голосов
/ 02 марта 2012

Я генерирую тестовые задачи динамически на основе существующих тестовых файлов в 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

. Приведенный выше код работает, он кажется слишком большим для простой генерации задач.И я до сих пор не нашел способ напечатать некоторый текст описания на консоль, например puts "Running #{name} tests:"

Есть ли более элегантный способ, чем описанный выше метод?

РЕДАКТИРОВАТЬ: Что я действительно ожидал получить, так это альтернативу циклу для динамического определения задач, но я предполагаю, что библиотека rake не предоставляет никакого помощника, поэтому я застрял в цикле.

Ответы [ 3 ]

13 голосов
/ 04 марта 2012

Вот еще один способ решения проблемы с использованием правил в Rake.

Правило рейка срабатывает всякий раз, когда rake хочет построить «X», и находит правила, которые говорят «чтобы построить 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

Предположим, у вас естьтестовый файл с именем "test / test_my_code.rb".Чтобы выполнить этот тестовый файл, просто введите:

rake test:my_code

Правило срабатывает всякий раз, когда существует цель, начинающаяся с «test:», которая не может быть сопоставлена ​​ни с какой другой задачей.Затем он ищет файл, заданный функцией lamdba.Лямбда преобразует целевое имя «test: XXX» в имя файла «test / test_XXX.rb».Если имя файла существует, выполняется тело правила.

Тело правила просто запускает тестовый файл как исполняемый файл.Обычно этого достаточно для запуска тестов одного файла.Если вам нужно добавить пути к библиотекам (например, «lib») к пути загрузки для тестов, вы можете изменить тело правила на что-то вроде

ruby "-Ilib", rule.source

Еще одно различие между этим и явным решением цикла заключается вэтот rake не будет выводить описания правил, поэтому вывод "rake -T" не будет включать в себя отдельные тесты.

Я не знаю, лучше ли это, чем оригинал, ноэто дает вам несколько вариантов.

1 голос
/ 03 марта 2012

Моя идея:

namespace :test do

  FileList['test_*.rb'].each do |rakefile|
    name = rakefile.gsub(/test_|\.rb\z/, '')

    desc "Run #{name} tests"
    task name do 
      require_relative rakefile
    end
    #Define default task for :test
    task :default => name
  end

end

desc "Run all tests"
task :test => 'test:default'
task :default => 'test'

Но я не уверен, стоит ли заменить Rake::TestTask.new на require_relative.

Мое решение содержит еще одно изменение: Я заменяю task test: all with test: default and define a new task test`.

Таким образом, вы получите следующий результат с rake -T:

rake test    # Run all tests
rake test:1  # Run 1 tests
rake test:2  # Run 2 tests

Если вы хотите запустить все тесты, вам нужно rake test, конкретные тесты можно выполнить с помощью rake test:<name>


Вы можете сделать это также через Rake::TestTask.new

require 'rake/testtask'
namespace :test do

  FileList['test_*.rb'].each do |rakefile|
    name = rakefile.gsub(/test_|\.rb\z/, '')

    Rake::TestTask.new(:"#{name}") do |t|
      t.pattern = rakefile
    end
    #Define default task for :test
    task :default => name
  end

end

desc "Run all tests"
task :test => 'test:default'
task :default => 'test'

С rake -T Я получаю:

rake test    # Run all tests
rake test:1  # Run tests for 1
rake test:2  # Run tests for 2

Описание генерируется.

Вы можете добавить:

    desc 'Alternative description'
    task name

Тогда вы получите:

rake test    # Run all tests
rake test:1  # Run tests for 1 / Alternative description
rake test:2  # Run tests for 2 / Alternative description

Если вы хотите изменить текст, вы можете добавить

    #replace description
    Rake.application[name].comment.replace("Run #{name} tests")

после end из Rake::TestTask.new. Это ужасный код, но Rake::TestTask не позволяет изменить описание (это было бы возможно, но это будет модификация класса).

0 голосов
/ 02 марта 2012

Хммм ... единственное изменение, которое я сделал, было обо всем, что я мог придумать. Не уверен, что это заслуживает полного ответа, но я хотел убедиться, что я ничего не испортил. Вы также можете попробовать опубликовать его на Обзор кода Stack Exchange

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
...