Azure DevOps单元测试失败时无法发布测试结果求助
问题分析与解决:Azure DevOps单元测试失败时无法获取trx文件
在Azure DevOps中发布单元测试结果时,测试全通过时流程正常,但部分测试失败时Docker镜像构建中断,导致无法获取trx测试结果文件。以下是问题详情、错误日志及解决方案:
现有配置
Dockerfile片段
RUN dotnet restore "IESA.TC.Invoices/IESA.TC.Invoices.csproj" COPY . . FROM build AS test LABEL test=true WORKDIR /src/IESA.TC.Invoices.Tests RUN dotnet test -c Release --logger trx FROM build AS publish WORKDIR "/src/IESA.TC.Invoices" RUN dotnet publish "IESA.TC.Invoices.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . COPY --from=test /src/IESA.TC.Invoices.Tests/TestResults ./TestResults
Azure Pipeline YAML配置
- stage: Build_Back_NewAKS displayName: Back - Build and push stage jobs: - job: Build displayName: Build pool: Dani test steps: - task: Docker@2 inputs: containerRegistry: $(dockerRegistryServiceConnectionAcrack) repository: $(imageRepositoryBack) command: 'build' Dockerfile: $(dockerfilePathBack) - pwsh: | $id=docker images --filter "label=test=true" -q | Select-Object -First 1 docker create --name testinvoices $id docker cp testinvoices:/app/TestResults ./TestResults docker rm testinvoices condition: succeededOrFailed() displayName: 'Copy test results' - task: PublishTestResults@2 condition: always() inputs: testResultsFormat: 'VSTest' testResultsFiles: '**/*.trx' searchFolder: '$(System.DefaultWorkingDirectory)/TestResults' displayName: 'Publish test results'
错误信息
Docker构建失败日志
#19 16.74 Failed! - Failed: 1, Passed: 128, Skipped: 0, Total: 129, Duration: 1 s - /src/IESA.TC.Invoices.Tests/bin/Release/net6.0/IESA.TC.Invoices.Tests.dll (net6.0) #19 ERROR: executor failed running [/bin/sh -c dotnet test -c Release --logger trx]: exit code: 1 [test 2/2] RUN dotnet test -c Release --logger trx: executor failed running [/bin/sh -c dotnet test -c Release --logger trx]: exit code: 1 ##[error]The process 'C:\Program Files\Docker\Docker\resources\bin\docker.exe' failed with exit code 1
测试结果复制失败日志
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'C:\agent_work_temp\0f7433c8-e7e9-491e-bfc7-ba396cb81e70.ps1'" "docker create" requires at least 1 argument. See 'docker create --help'. docker create [OPTIONS] IMAGE [COMMAND] [ARG...] Create a new container Error: No such container:path: testinvoices:/app/TestResults Error: No such container: testinvoices
问题根源
dotnet test执行失败时会返回非0退出码,导致Docker多阶段构建的test阶段中断,对应的镜像无法生成。后续Pipeline步骤通过docker images --filter "label=test=true"找不到目标镜像,因此复制测试结果的命令报错。
解决方案
方案1:分离测试与镜像构建(推荐)
不在Docker构建流程中执行测试,直接在Pipeline中单独运行测试生成trx文件,再进行镜像构建:
- task: DotNetCoreCLI@2 displayName: 'Run unit tests' inputs: command: 'test' projects: '**/*Tests.csproj' arguments: '-c Release --logger trx' # 测试失败时仍继续流程,确保能发布测试结果 continueOnError: true # 原Docker构建任务 - task: Docker@2 inputs: containerRegistry: $(dockerRegistryServiceConnectionAcrack) repository: $(imageRepositoryBack) command: 'build' Dockerfile: $(dockerfilePathBack) # 仅测试通过时才构建镜像 condition: succeeded()
同时修改Dockerfile,移除test阶段相关代码。
方案2:强制保留测试阶段镜像
修改Dockerfile,让test阶段即使测试失败也能完成构建,同时记录测试退出码:
FROM build AS test LABEL test=true WORKDIR /src/IESA.TC.Invoices.Tests # 执行测试生成trx,失败时强制继续构建 RUN dotnet test -c Release --logger trx || true # 保存测试退出码,用于后续判断结果 RUN echo $? > /test_exit_code.txt
然后调整Pipeline的复制步骤,根据退出码标记构建状态:
- pwsh: | $id=docker images --filter "label=test=true" -q | Select-Object -First 1 if ($id) { docker create --name testinvoices $id docker cp testinvoices:/src/IESA.TC.Invoices.Tests/TestResults ./TestResults docker cp testinvoices:/test_exit_code.txt ./test_exit_code.txt docker rm testinvoices $exitCode = Get-Content ./test_exit_code.txt if ($exitCode -ne 0) { Write-Host "##vso[task.setvariable variable=TestFailed]True" exit 1 } } else { Write-Host "Test stage image not found" exit 1 } condition: succeededOrFailed() displayName: 'Copy test results and check status'
方案3:分阶段构建镜像
先单独构建test阶段镜像,获取测试结果后,再决定是否构建最终镜像:
# 先构建测试阶段镜像 - task: Docker@2 displayName: 'Build test stage image' inputs: containerRegistry: $(dockerRegistryServiceConnectionAcrack) repository: $(imageRepositoryBack)-test command: 'build' Dockerfile: $(dockerfilePathBack) target: 'test' # 复制测试结果并验证 - pwsh: | $id=docker images --filter "label=test=true" -q | Select-Object -First 1 docker create --name testinvoices $id docker cp testinvoices:/src/IESA.TC.Invoices.Tests/TestResults ./TestResults docker rm testinvoices # 解析trx文件判断测试是否失败 $trxFile = Get-ChildItem ./TestResults/*.trx | Select-Object -First 1 if ($trxFile) { $xml = [xml](Get-Content $trxFile) $failed = $xml.TestRun.ResultSummary.Counters.failed if ($failed -gt 0) { Write-Host "##vso[task.setvariable variable=TestFailed]True" exit 1 } } condition: succeededOrFailed() displayName: 'Copy test results and validate' # 仅测试通过时构建最终镜像 - task: Docker@2 displayName: 'Build final image' inputs: containerRegistry: $(dockerRegistryServiceConnectionAcrack) repository: $(imageRepositoryBack) command: 'build' Dockerfile: $(dockerfilePathBack) target: 'final' condition: ne(variables.TestFailed, 'True')
内容的提问来源于stack exchange,提问作者Daniel A.
相关产品推荐
相关产品推荐

