私はあなた自身の答えからrakefile/tasksをリミックスするつもりです。より多くの聴衆にアピールするために従うべきRuby/Rakeの慣習がいくつかあります。そして、私は素晴らしいrakefileを書く方法についていくつかの意見を持っています。特に...
1.Rakeタスクを直接呼び出し/実行しないでください
Rake::Task[:unitTestWithCoverage].execute( testAssembly )
invoke
直接Rakeやを台無しにしたくない理由はいろいろありますexecute
。それらの1つは依存タスクを呼び出さず、1つは依存タスクを1回だけ実行します...それは間抜けになります。適切に定義された依存タスクを構築する方法は常にあるはずです。
2.「内部」タスクをパラメーター化しないでください
exec :unitTestWithCoverage, [:testAssembly] do |cmd, testAssembly|
テストアセンブリの静的リストまたはワイルドカード一致リストがある可能性があります。パラメータを使用せずに具体的なタスクを作成できるはずです。パラメータ化されたタスクは、ユーザーがコマンドラインからのカスタム入力で呼び出すことができる場合にのみ使用します。
3.各タスク内にパスを作成する必要はありません
testAssemblyRealPath = Pathname.new(testAssembly).realpath
testAssemblyName = File.basename(testAssemblyRealPath)
Rakeを調べて、ファイル名/パス/任意の文字列のFileList
カスタムの怠惰なマップされたリストを作成する方法を理解します。
リミックス(更新)
私は最初の答えで重大な間違いを犯しました(参考のために、これは一番下にあります)。私はあなた/私の教育のためにそのセクションで何がうまくいかなかったかを説明します!
以下は私の新しい推奨事項です。自分のビルドでmspecテストランナータスクで同じ間違いをしたので、これは私には明らかだったはずです。
dotcover_path = 'path/to/dotcover.exe'
xunit_runner_path = 'path/to/xunitrunner.exe'
test_assemblies = FileList['path/to/output/**/*.test.dll']
coverage_results = "#{test_results_path}/coverage_results.dcvr"
task :cover_all => [ :tests_with_coverage, :publish_coverage_results ]
exec :tests_with_coverage do |cmd|
cmd.comand = dotcover_path
cmd.parameters = [
"cover",
"/AnalyseTargetArguments=False",
"/TargetExecutable=\"#{xunit_runner_path}\"",
"/TargetArguments=\"#{test_assemblies.join ','}\"",
"/Output=\"#{coverage_results}\""
]
end
task :publish_coverage_results => [ :tests_with_coverage ] do
import_data 'dotNetCoverage', 'dotCover', coverage_results
end
def import_data(type, tool, file)
puts "##teamcity[importData type='#{type}' tool='#{tool}' path='#{file}']"
end
説明
デフォルトでは絶対パスに設定されています(通常はFile.expand_path
と__FILE__
定数を使用します)。相対パスを必要とするツール/タスクがありますが、いつでものようなメソッドで遊ぶことができますFile.basename
。
dotcover_path = 'path/to/dotcover.exe'
xunit_runner_path = 'path/to/xunitrunner.exe'
FileList
ビルドされたアセンブリのを使用して、ターゲットアセンブリを定義できます。テストタスクの本体が実行されるまで、それを評価しません。
test_assemblies = FileList['path/to/output/**/*.test.dll']
カバレッジランナーは、単一の結果ファイルで複数のアセンブリをサポートします。このようにして、別の複雑なものはありませんpathmap
。
coverage_results = "#{test_results_path}/coverage_results.dcvr"
CIサーバーからこれを呼び出して、公開されたテストとカバレッジ結果を実行します。
task :cover_all => [ :tests_with_coverage, :publish_coverage_results ]
このタスクは今や単純で単純です。いくつかの注意事項:1。join
ターゲットのリストを正しい形式の文字列に変換するために使用します。2.ファイルパス(エスケープが必要)を持つexecタスクパラメーターを引用する傾向があります\"
。
exec :tests_with_coverage do |cmd|
cmd.command = dotcover_path
cmd.parameters = [
"cover",
"/AnalyseTargetArguments=False",
"/TargetExecutable=\"#{xunit_runner_path}\"",
"/TargetArguments=\"#{test_assemblies.join ','}\"",
"/Output=\"#{coverage_results}\""
]
end
同じ古い公開タスク/メソッド。
task publish_coverage_results => [ :tests_with_coverage ] do
import_data 'dotNetCoverage', 'dotCover', coverage_results
end
def import_data(type, tool, file)
puts "##teamcity[importData type='#{type}' tool='#{tool}' path='#{file}']"
end
オールドリミックス
問題のある領域を示すために切り取って、残りが面白くないか、新しいソリューションにも存在すると仮定します。
テストアセンブリは、ビルドタスクが完了するまで存在しません。FileList
怠惰なので、通常は問題ありません。列挙するまで評価されません(たとえば、、、またはを使用しeach
てmap
)zip
。
ただし、すぐeach
にテストタスクを生成するためにそれを処理します...したがって、これは機能しません。リストには何も含まれず、タスクは生成されません。または、さらに悪いことに、前のビルドの出力を取得し、おそらく悪いことをします(出力ディレクトリを完全にクリーンアップしなかった場合)。
test_assemblies = FileList['path/to/output/**/*.test.dll']
coverage_results = test_assemblies.pathmap "#{test_results_path}/%n.dcvr"
cover_task_names = test_assemblies.pathmap "cover_%n"
test_assemblies.zip(coverage_results, cover_task_names) do |assembly, results, task_name|
exec task_name do |cmd|
cmd.command = dotcover_path
cmd.parameters = [
"cover",
"/AnalyseTargetArguments=False",
"/TargetExecutable=#{xunit_path}",
"/TargetArguments=#{assembly}",
"/Output=#{results}"
]
end
end