4

exec相対パスを使用して Albacore タスクで dotCover を動作させるにはいくつか問題があります。

@xUnitRunnerPath = Pathname.new('../../Tools/xUnit/xunitcontrib-dotcover.2.0/xunit.runner.utility.dll').realpath
@myTestDll = 'C:\PathToProj\My.Project.Tests\bin\Release\My.project.Tests.dll'
@outputDir = 'C:\PathToTestResults\'

exec :testCoverage do |cmd|
    cmd.command = "C:/BuildAgent/tools/dotCover/dotCover.exe"
    cmd.parameters = [
        "cover",
        "/targetexecutable=$$#{@xUnitRunnerPath}$$",
        "/targetarguments=$$#{@myTestDll}$$",
        "/output=#{@outputDir}/My.Project.Tests.dll.dcvr"
    ]
end

dotCoverパスが間違っていることを伝えるだけで、エラーは役に立たない

Failed to convert relative paths to absolute in parameters for the 'cover' 
command. The given path's format is not supported. 

これはあまり役に立ちません。また、そのヘルプとして dotcover help cover も試しましたが、何が問題なのかについての手がかりはあまりありません。

rake と dotcover に関するこの投稿と、この質問をフォローしました。関連するドキュメントがここにない可能性がありますが、これを機能させることができれば非常に役立ちます。


編集:相対パスと絶対パスに関連するこれを見つけました。おそらく、絶対パスを使用しているため、次のものが必要です。明日わかるよ

/AnalyseTargetArguments=false
4

2 に答える 2

3

私はあなた自身の答えから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怠惰なので、通常は問題ありません。列挙するまで評価されません(たとえば、、、またはを使用しeachmapzip

ただし、すぐ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
于 2013-03-21T05:00:09.040 に答える
1

興味のある人は、ここで私の最後のレーキタスクが機能しています

task :unitTestsWithCoverageReport => [ :unitTestsWithCoverage, :coverageServiceMessage ]

exec :unitTestsWithCoverage do |cmd|
    fullPathAssemblies = []

    @unitTestAssemblies.each do |testAssembly|
        testAssemblyRealPath = Pathname.new(testAssembly).realpath
        fullPathAssemblies << testAssemblyRealPath
    end

    cmd.command = @dotCoverRealPath
    cmd.parameters = [
        "cover",
        "/AnalyseTargetArguments=False",
        "/TargetExecutable=#{@xUnitRunnerRealPath}",
        "/TargetArguments=\"#{fullPathAssemblies.join ';'}\"",
        "/Output=#{@testResultsRealPath}/coverage.dcvr"
        ]
end

task :coverageServiceMessage do |t|
    puts "##teamcity[importData type='dotNetCoverage' tool='dotcover' path='#{@testResultsRealPath}/coverage.dcvr']"
end

@AnthonyMastrean に感謝します。彼は、いくつかの本当に素敵な小さな Ruby のトリックと、レーキ ファイルを適切に構成する方法を教えてくれました。

于 2013-03-19T13:10:36.090 に答える