如果未运行测试,则使TeamCity构建失败

时间:2013-08-07 08:41:25

标签: c# visual-studio unit-testing teamcity dotcover

我们有一个设置,TeamCity构建软件并在其上运行单元测试。我们使用受this answer启发的powershell脚本,该脚本使用vstest运行单元测试并使用dotcover报告代码覆盖率。

有时,开发人员会进行更改,导致脚本根本不运行测试。 TeamCity没有对构建失败进行报告,而是将构建报告为成功,但没有提及测试(因为它们没有运行)。

如果未运行测试,我希望构建失败。

我如何做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以在度量标准更改上添加构建失败条件(请参阅构建配置管理区域的构建失败条件步骤)。有一个称为“测试次数”的度量标准。如果没有运行测试,则将其设置为0,以使构建失败。

答案 1 :(得分:1)

我看了一下你引用的powershell脚本。我看到测试可能无法运行的两个明显原因:

# Get list of folders with Test DLLs in them matching pattern *Tests\bin
$testFolders = Get-ChildItem -Recurse -Force $rootDirectory | 
  Where-Object { ($_.PSIsContainer -eq $true) -and (($_.FullName -like "*Tests\bin\" + $vsConfigName) -or ($_.FullName -like "*Tests\bin\x64\" + $vsConfigName)) }

如果没有文件夹与此gci中的模式匹配,则不会运行任何测试。

#grab the testing DLLs from the folder which match pattern *Tests.dll
$testDlls = Get-ChildItem -Force $folder.FullName -File |
  Where-Object { $_.Name -like "*Tests.dll" }

同样,如果没有dll匹配模式,则不会运行测试。

除了脚本应该尝试捕获它,然后你可以抛出,如果你找不到任何测试文件夹或任何测试dll。我编辑了您引用的代码示例以显示此内容:

#rootDirectory is the base directory to search for Test Projects. (Most likely your solution directory)
#configName is a string name that the code coverage output files will be placed in
#filters is a list of dotCover filters to be added to the /Filters argument
#vsConfigName is the configuration folder to find the Test DLLs in
Param([string]$rootDirectory,[string]$configName,[string]$filters,[string]$vsConfigName)

$vstestconsolepath = "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe"
$dotcoverpath = "C:\BuildAgent\tools\dotCover\dotCover.exe"
$dotcovertargetexecutable = "/TargetExecutable=" + $vstestconsolepath
$dotcoveroutput = "/Output=" + $configName + "/coverage.dcvr"
$dotcoverfilters = "/Filters=" + $filters

try
{
  # Get list of folders with Test DLLs in them matching pattern *Tests\bin
  $testFolders = Get-ChildItem -Recurse -Force $rootDirectory | Where-Object { ($_.PSIsContainer -eq $true) -and (($_.FullName -like "*Tests\bin\" + $vsConfigName) -or ($_.FullName -like "*Tests\bin\x64\" + $vsConfigName)) } | Select-Object
  if ($testFolder -eq $null) 
  {
    throw [Exception] "No test folders found."
  }

  foreach ($folder in $testFolders)
  {
      #look for Fakes DLLs. If we find one we can't do code coverage on this test assembly
      $fakesDLLs = Get-ChildItem -Recurse -Force $folder.FullName -File | Where-Object { $_.Name -like "*Fakes.dll" } | Select-Object

      #grab the testing DLLs from the folder which match pattern *Tests.dll
      $testDlls = Get-ChildItem -Force $folder.FullName -File | Where-Object { $_.Name -like "*Tests.dll" } | Select-Object

      foreach ($dll in $testDlls)
      {
          if ($fakesDLLs.length -eq 0)
          {
              $arr += @($dll.FullName)
          }
          else
          {
              $fakesArr += @($dll.FullName)
          }
      }
  }

  if ($arr -eq $null) 
  {
    throw [Exception] "No test dlls found."
  }

...

}
catch [Exception]
{
  Write-Host($_.Exception.GetType().FullName)
  Write-Host($_.Exception.Message)
  Write-Host($_.Exception.StackTrace)
  exit 1
}

当然你不一定需要去那么远,你可以exit 1而不是用try catch投掷。当然,你不应该真的抛出Exception,但这不是主题。