我们有一个设置,TeamCity 在其中构建软件并在其上运行单元测试。我们使用受此答案启发的 powershell 脚本,它使用 vstest 运行单元测试并使用 dotcover 报告代码覆盖率。
有时,开发人员所做的更改会导致脚本根本无法运行测试。TeamCity 没有使构建失败,而是将构建报告为成功,但没有提及测试(因为它们没有运行)。
如果未运行测试,我希望构建失败。
我该如何做到这一点?
我们有一个设置,TeamCity 在其中构建软件并在其上运行单元测试。我们使用受此答案启发的 powershell 脚本,它使用 vstest 运行单元测试并使用 dotcover 报告代码覆盖率。
有时,开发人员所做的更改会导致脚本根本无法运行测试。TeamCity 没有使构建失败,而是将构建报告为成功,但没有提及测试(因为它们没有运行)。
如果未运行测试,我希望构建失败。
我该如何做到这一点?
您可以在指标更改时添加构建失败条件(请参阅构建配置管理区域的构建失败条件步骤)。有一个称为“测试次数”的指标。将其设置为 0,如果没有运行测试,则构建失败。
我查看了您引用的 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 与模式匹配,则不会运行测试。
除此之外,脚本真的应该有一个 try catch,如果你没有找到任何测试文件夹或任何测试 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
,但那是题外话。