【问题标题】:Dotnet Unit test with Coverlet- How to get coverage for entire solution and not just a project使用 Coverlet 进行 Dotnet 单元测试 - 如何覆盖整个解决方案而不仅仅是项目
【发布时间】:2018-11-12 01:50:03
【问题描述】:

我们正在使用 Coverlets (https://github.com/tonerdo/coverlet) 来测量包含多个项目的 .NET 解决方案中单元测试的代码覆盖率。结果分别针对解决方案中的每个项目显示。我们想要的是对整个解决方案有一个统一的结果。 谁能建议最好的方法来获得它? 如果有任何机会通过 Coverlet 无法实现,您能否建议任何可以使用 CLI 执行此操作的替代开源工具。我们本质上需要将其与 CI 工具集成,该工具应在覆盖率低于阈值时发出警告。

【问题讨论】:

    标签: .net unit-testing


    【解决方案1】:

    这就是我们使用coverlet.msbuild 为整个解决方案生成代码覆盖率的方式。

    1. 在解决方案的每个测试项目中引用 coverlet.msbuild
    2. 在 CI 脚本中,导航到包含解决方案文件的目录。那么,
    3. 运行类似如下的命令(语法为bash)
    dotnet test {solution_filename.sln} --logger:trx --results-directory ../TestResults \
       "/p:CollectCoverage=true" \
       "/p:CoverletOutput=../TestResults/" \
       "/p:MergeWith=../TestResults/coverlet.json" \
       "/p:CoverletOutputFormat=\"json,cobertura\"" 
    

    如果在 Windows 上运行它,您可能需要转义一些传递给这些参数的字符,例如逗号 (%2c)。

    为了合并多个项目的结果,我们生成了两种输出格式,json 和 cobertura。见参数/p:CoverletOutputFormat

    在为每个项目生成代码覆盖率时,coverlet 将使用/p:MergeWith 将当前项目的coverlet.json 与之前的coverlet.json 合并。

    这种方法为我们稍后可以在 CI 构建中使用的解决方案生成了一个 cobertura 结果文件。

    【讨论】:

    • 当我尝试将两种格式添加到最后一个参数时,我得到 MSBUILD : error MSB1006: Property is not valid。开关:cobertura
    • 它对我有用。添加引号的(看似多余的)\转义似乎很重要
    • @ssmith 抱歉回复延迟。您能否提供一个示例来说明您为 CoverletOutputFormat 参数包含的内容?我可以尝试复制和建议。如果我没记错的话,我们需要先放置json 输出格式。
    • 对于 Windows,逗号需要转义 (%2c)。要使最后一行正常工作,请改用 /p:CoverletOutputFormat=json%2ccobertura
    • 感谢@EricksonG,我更新了我的答案并附上了关于此的注释。
    【解决方案2】:

    如果您使用coverage.collector nuget,它将为每个项目生成单独的测试结果文件。

    然后您可以使用reportgenerator 工具将多个结果合并为一个。

    这是我们在 CI 中的做法:

    dotnet test <solution-file> --collect:"XPlat Code Coverage"
    dotnet tool install --global dotnet-reportgenerator-globaltool --version <version-number>
    reportgenerator -reports:<base-directory>/**/coverage.cobertura.xml -targetdir:<output-directory>/CoverageReport -reporttypes:Cobertura
    

    这将为您的所有测试项目生成一份综合报告。

    【讨论】:

      【解决方案3】:

      最近我遇到了同样的问题,乔尔的回答完美无缺。除非你需要 xml 而不是 json。在这种情况下,您必须一个接一个地运行测试项目,生成 json 输出并与以前的合并,但是以您需要的格式运行最后一个。

      这是我如何做到的一个例子:

      RUN dotnet test "tests/[project name].Test.Integration/[project name].Test.Integration.csproj" \
          --configuration Release \
          --no-restore \
          --no-build \
          --verbosity=minimal \
          -p:CollectCoverage=true \
          -p:CoverletOutputFormat="json" \
          -p:CoverletOutput=/src/cover.json
      
      RUN dotnet test "tests/[project name].Test.Unit/[project name].Test.Unit.csproj" \
          --configuration Release \
          --no-restore \
          --no-build \
          --verbosity=minimal \
          -p:CollectCoverage=true \
          -p:CoverletOutputFormat="opencover" \
          -p:CoverletOutput=/src/cover.xml \
          -p:MergeWith=../../cover.json
      

      我在 Docker 中运行它,我的文件夹结构可能看起来有点混乱 =)。在这里,为了避免任何混淆:

      src
      ---src
      ---tests
      ------[project name].Test.Integration
      ---------[project name].Test.Integration.csproj
      ------[project name].Test.Unit
      ---------[project name].Test.Unit.csproj
      ---[project name].sln
      ---cover.json <- this file gets created after the first command
      ---cover.xml <- this file gets created after the second command
      

      所以我首先为我的集成测试运行覆盖率,然后将它与所需格式的单元测试覆盖率合并(opencover,因为我需要它用于 SonarQube)

      【讨论】:

        【解决方案4】:

        当解决方案的整体覆盖率低于某个阈值时,上述答案都不能帮助您在 CI 中构建失败。您得到的只是 JSON、XML 或 HTML 报告,您需要使用额外的脚本对其进行解析,而且工作量太大。

        相反,这就是我所做的。

        首先,运行 dotnet test 并告诉 Coverlet 合并所有覆盖结果。 (你需要在你的测试项目中引用coverlet.msbuild)

        dotnet test your_solution.sln /p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json
        

        如果您将阈值开关(/p:Threshold 等)添加到同一命令,它会尝试将其单独应用于每个项目,但这不是我们想要的。

        所以要绕过这个限制,我们可以做的是再运行一次上述命令,将现有结果与您拥有的测试项目之一合并。将总数与小节合并不会改变您的总数。

        dotnet test one_of_your_test_projects.csproj /p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json /p:ThresholdType=branch /p:Threshold=80 /p:ThresholdStat=total
        

        现在,只有当您的解决方案的覆盖范围低于您的阈值时,该命令才会失败。这是我使用的一些用于 AzureDevOps 的 YAML 任务。其他的也应该有点相似。

        - task: DotNetCoreCLI@2
          displayName: 'Calculate code coverage'
          continueOnError: false
          inputs:
            command: test
            projects: '**/*.Test.csproj'
            arguments: '/p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json  /m:1'
            publishTestResults: false
        
        - task: DotNetCoreCLI@2
          displayName: 'Checkpoint: Total branch coverage >= $(codeCoverageBranchThreshold)'
          continueOnError: false
          inputs:
            command: test
            projects: './one_of_your_test_projects_dir/one_of_your_test_projects.csproj'
            arguments: '/p:CollectCoverage=true /p:CoverletOutput=../TestResults/ /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=../TestResults/coverage.json /p:ThresholdType=branch /p:Threshold=$(codeCoverageBranchThreshold) /p:ThresholdStat=total'
            publishTestResults: false
        

        【讨论】:

          【解决方案5】:

          根据 Abbas Cyclewala 的评论,任何使用 windows 的人都可以从 sln 运行命令:

          dotnet test --collect:"Xplat Code Coverage"

          然后:

          reportgenerator -reports:"../**/coverage.cobertura.xml" -targetdir:"/CoverageReport" -reporttypes:"html"

          报告将在根文件夹中。

          【讨论】:

            【解决方案6】:

            这只有在您以顺序方式运行构建/测试时才有效,作为参考,我将链接讨论在 repo https://github.com/tonerdo/coverlet/issues/598#issuecomment-551174529

            【讨论】:

              猜你喜欢
              • 2018-02-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-04-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多