5

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 libはそれに対するヘルパーを提供しないと思うので、ループで立ち往生しています。

4

3 に答える 3

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

「test/test_my_code.rb」という名前のテストファイルがあるとします。そのテストファイルを実行するには、次のように入力します。

rake test:my_code

ルールは、他のタスクと一致できない「test:」で始まるターゲットがある場合にトリガーされます。次に、lamdba関数によって指定されたファイルを探します。ラムダは、ターゲット名「test:XXX」をファイル名「test/test_XXX.rb」に変換します。ファイル名が存在する場合は、ルールの本文が実行されます。

ルールの本体は、実行可能ファイルとしてテストファイルを実行するだけです。これは通常、単一のファイルのテストを実行するのに十分です。テストのロードパスにライブラリパス(「lib」など)を追加する必要がある場合は、ルール本体を次のように変更できます。

ruby "-Ilib", rule.source

これと明示的なループソリューションのもう1つの違いは、rakeがルールの説明を出力しないため、「rake-T」出力に個々のテストが含まれないことです。

これがオリジナルよりも優れているかどうかはわかりませんが、いくつかのオプションがあります。

于 2012-03-03T21:07:55.843 に答える
1

私の考え:

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

私のソリューションには別の変更が含まれています:tasktest:all withtest:and define a new taskdefaulttest`を置き換えます。

したがって、次の結果が得られます 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")

の後endRake::TestTask.new。これは醜いコードですがRake::TestTask、説明を変更することはできません(可能ですが、クラスの変更になります)。

于 2012-03-02T21:25:37.653 に答える
0

うーん...私が行った1つの変更は、私が考えることができるすべてについてでした。それが完全な答えに値するかどうかはわかりませんが、私は何も破損していないことを確認したかったのです。StackExchangeのコードレビューに投稿してみることもできます

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
于 2012-03-02T19:50:52.347 に答える