Publish test results to Azure Pipelines.
Syntax# Publish Test Results v2
# Publish test results to Azure Pipelines.
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit' # 'JUnit' | 'NUnit' | 'VSTest' | 'XUnit' | 'CTest'. Alias: testRunner. Required. Test result format. Default: JUnit.
testResultsFiles: '**/TEST-*.xml' # string. Required. Test results files. Default: **/TEST-*.xml.
#searchFolder: '$(System.DefaultWorkingDirectory)' # string. Search folder. Default: $(System.DefaultWorkingDirectory).
#mergeTestResults: false # boolean. Merge test results. Default: false.
#failTaskOnFailedTests: false # boolean. Fail if there are test failures. Default: false.
#failTaskOnFailureToPublishResults: false # boolean. Fail if there is failure in publishing test results. Default: false.
#failTaskOnMissingResultsFile: false # boolean. Fail if no result files are found. Default: false.
#testRunTitle: # string. Test run title.
# Advanced
#buildPlatform: # string. Alias: platform. Build Platform.
#buildConfiguration: # string. Alias: configuration. Build Configuration.
#publishRunAttachments: true # boolean. Upload test results files. Default: true.
# Publish Test Results v2
# Publish test results to Azure Pipelines.
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit' # 'JUnit' | 'NUnit' | 'VSTest' | 'XUnit' | 'CTest'. Alias: testRunner. Required. Test result format. Default: JUnit.
testResultsFiles: '**/TEST-*.xml' # string. Required. Test results files. Default: **/TEST-*.xml.
#searchFolder: '$(System.DefaultWorkingDirectory)' # string. Search folder. Default: $(System.DefaultWorkingDirectory).
#mergeTestResults: false # boolean. Merge test results. Default: false.
#failTaskOnFailedTests: false # boolean. Fail if there are test failures. Default: false.
#testRunTitle: # string. Test run title.
# Advanced
#buildPlatform: # string. Alias: platform. Build Platform.
#buildConfiguration: # string. Alias: configuration. Build Configuration.
#publishRunAttachments: true # boolean. Upload test results files. Default: true.
Inputs
testResultsFormat
- Test result format
Input alias: testRunner
. string
. Required. Allowed values: JUnit
, NUnit
, VSTest
, XUnit
, CTest
. Default value: JUnit
.
Specifies the format of the results files you want to publish. The following formats are supported: CTest, JUnit, NUnit 2, NUnit 3, Visual Studio Test (TRX) and xUnit 2.
Tip
VSTest
format refers to the TRX format. So, it works also if you are producing TRX with Microsoft.Testing.Platform (MTP) and is not specific to VSTest. The value is VSTest for historical reasons, before the introduction of MTP.
testResultsFiles
- Test results filesstring
. Required. Default value: **/TEST-*.xml
.
Specifies one or more test results files.
*
) and recursive wildcards (**
). For example, **/TEST-*.xml
searches for all the XML files whose names start with TEST-
in all subdirectories. If using VSTest as the test result format, the file type should be changed to .trx
e.g. **/TEST-*.trx
For example, !TEST[1-3].xml
excludes files named TEST1.xml
, TEST2.xml
, or TEST3.xml
.
searchFolder
- Search folderstring
. Default value: $(System.DefaultWorkingDirectory)
.
Optional. Specifies the folder to search for the test result files.
mergeTestResults
- Merge test resultsboolean
. Default value: false
.
When this boolean's value is true
, the task reports test results from all the files against a single test run. If the value is false
, the task creates a separate test run for each test result file. To optimize for better performance, results will always be merged into a single run if there are more than 100 result files even if this option is set to false
.
Note
Use the merge test results setting to combine files from the same test framework to ensure results mapping and duration are calculated correctly.
failTaskOnFailedTests
- Fail if there are test failuresboolean
. Default value: false
.
Optional. When this boolean's value is true
, the task will fail if any of the tests in the results file are marked as failed. The default is false
, which will simply publish the results from the results file.
failTaskOnFailureToPublishResults
- Fail if there is failure in publishing test resultsboolean
. Default value: false
.
When true
, fails the task if there is failure in publishing test results.
failTaskOnMissingResultsFile
- Fail if no result files are foundboolean
. Default value: false
.
Fail the task if no result files are found.
testRunTitle
- Test run titlestring
.
Optional. Specifies a name for the test run against which the results will be reported. Variable names declared in the build or release pipeline can be used.
buildPlatform
- Build Platform
Input alias: platform
. string
.
Optional. Specifies the build platform against which the test run should be reported. For example: x64
or x86
. If you defined a variable for the platform in your build task, use it here.
buildConfiguration
- Build Configuration
Input alias: configuration
. string
.
Optional. Specifies the build configuration against which the test run should be reported. For example: Debug
or Release
. If you defined a variable for the configuration in your build task, use it here.
publishRunAttachments
- Upload test results filesboolean
. Default value: true
.
Optional. When this boolean's value is true
, the task uploads all the test result files as attachments to the test run.
All tasks have control options in addition to their task inputs. For more information, see Control options and common task properties.
Output variablesNone.
This task publishes test results to Azure Pipelines or TFS when tests are executed to provide a comprehensive test reporting and analytics experience. You can use the test runner of your choice that supports the results format you require. Supported results formats include CTest, JUnit (including PHPUnit), NUnit 2, NUnit 3, Visual Studio Test (TRX), and xUnit 2.
Other built-in tasks, such as Visual Studio Test task and Dot NetCore CLI task automatically publish test results to the pipeline. Tasks such as Ant, Maven, Gulp, Grunt, and Xcode provide publishing results as an option within the task, or build libraries such as Cobertura and JaCoCo. If you are using any of these tasks, you do not need a separate Publish Test Results task in the pipeline.
The published test results are displayed in the Tests tab in the pipeline summary. The results help you to measure pipeline quality, review traceability, troubleshoot failures, and drive failure ownership.
The following example shows the task is configured to publish test results.
You can also use this task in a build pipeline to publish code coverage results produced when running tests to Azure Pipelines or TFS in order to obtain coverage reporting.
PrerequisitesIf you're using a Windows self-hosted agent, your machine must have this prerequisite installed:
The default option uses JUnit format to publish test results. When using VSTest as the testRunner, the testResultsFiles option should be changed to **/TEST-*.trx
.
testResultsFormat is an alias for the testRunner input name. The results files can be produced by multiple runners, not just a specific runner. For example, the jUnit results format is supported by many runners and not just jUnit.
To publish test results for Python using YAML, see Python in the Ecosystems section of these topics, which also includes examples for other languages.
Result formats mappingThis table lists the fields reported in the Tests tab in a build or release summary, and the corresponding mapping with the attributes in the supported test result formats.
Scope Field Visual Studio Test (TRX) Test run Title Test run title specified in the task Date started /TestRun/Times.Attributes["start"].Value Date completed /TestRun/Times.Attributes["finish"].Value Duration Date completed - Date started Attachments Refer to Attachments support section below Test result Title /TestRun/Results/UnitTestResult.Attributes["testName"].Value Or /TestRun/Results/WebTestResult.Attributes["testName"].Value Or /TestRun/Results/TestResultAggregation.Attributes["testName"].Value Date started /TestRun/Results/UnitTestResult.Attributes["startTime"].Value Or /TestRun/Results/WebTestResult.Attributes["startTime"].Value Or /TestRun/Results/TestResultAggregation.Attributes["startTime"].Value Date completed /TestRun/Results/UnitTestResult.Attributes["startTime"].Value + /TestRun/Results/UnitTestResult.Attributes["duration"].Value Or /TestRun/Results/WebTestResult.Attributes["startTime"].Value + /TestRun/Results/WebTestResult.Attributes["duration"].Value Or /TestRun/Results/TestResultAggregation.Attributes["startTime"].Value + /TestRun/Results/TestResultAggregation.Attributes["duration"].Value Duration /TestRun/Results/UnitTestResult.Attributes["duration"].Value Or /TestRun/Results/WebTestResult.Attributes["duration"].Value Or /TestRun/Results/TestResultAggregation.Attributes["duration"].Value Owner /TestRun/TestDefinitions/UnitTest/Owners/Owner.Attributes["name"].Value Outcome /TestRun/Results/UnitTestResult.Attributes["outcome"].Value Or /TestRun/Results/WebTestResult.Attributes["outcome"].Value Or /TestRun/Results/TestResultAggregation.Attributes["outcome"].Value Error message /TestRun/Results/UnitTestResult/Output/ErrorInfo/Message.InnerText Or /TestRun/Results/WebTestResultOutput/ErrorInfo/Message.InnerText Or /TestRun/Results/TestResultAggregation/Output/ErrorInfo/Message.InnerText Stack trace /TestRun/Results/UnitTestResult/Output/ErrorInfo/StackTrace.InnerText Or /TestRun/Results/WebTestResultOutput/ErrorInfo/StackTrace.InnerText Or /TestRun/Results/TestResultAggregation/Output/ErrorInfo/StackTrace.InnerText Attachments Refer to Attachments support section below Console log /TestRun/Results/UnitTestResult/Output/StdOut.InnerText Or /TestRun/Results/WebTestResultOutput/Output/StdOut.InnerText Or /TestRun/Results/TestResultAggregation/Output/StdOut.InnerText Console error log /TestRun/Results/UnitTestResult/Output/StdErr.InnerText Or /TestRun/Results/WebTestResultOutput/Output/StdErr.InnerText Or /TestRun/Results/TestResultAggregation/Output/StdErr.InnerText Agent name /TestRun/Results/UnitTestResult.Attributes["computerName"].Value Or /TestRun/Results/WebTestResult.Attributes["computerName"].Value Or /TestRun/Results/TestResultAggregation.Attributes["computerName"].Value Test file /TestRun/TestDefinitions/UnitTest.Attributes["storage"].Value Priority /TestRun/TestDefinitions/UnitTest.Attributes["priority"].Value Scope Field JUnit Test run Title Test run title specified in the task Date started /testsuites/testsuite.Attributes["timestamp"].Value Date completed /testsuites/testsuite.Attributes["timestamp"].Value + SUM(/testsuites/testsuite/testcase.Attributes["time"].Value) for all test cases in the test suite Duration Date completed - Date started Attachments Results file, used to publish test results Test result Title /testsuites/testsuite/testcase/Attributes["name"].Value Date started /testsuites/testsuite.Attributes["timestamp"].Value Date completed /testsuites/testsuite.Attributes["timestamp"].Value + /testsuites/testsuite/testcase.Attributes["time"].Value Duration /testsuites/testsuite/testcase/.Attributes["time"].Value Owner /testsuites/testsuite/testcase/Attributes["owner"].Value Outcome Failed: if exists /Testsuites/testsuite/testcase/failure Or /Testsuites/testsuite/testcase/error Not Executed: if exists Testsuites/testsuite/testcase/skipped Passed: for all other cases Error message /Testsuites/testsuite/testcase/failure.Attributes["message"].Value Or /Testsuites/testsuite/testcase/error.Attributes["message"].Value Or /Testsuites/testsuite/testcase/skipped.Attributes["message"].Value Stack trace /Testsuites/testsuite/testcase/failure.InnerText Or /Testsuites/testsuite/testcase/error.InnerText Attachments - Console log /Testsuites/testsuite/testcase/system-out Console error log /Testsuites/testsuite/testcase/system-err Agent name /testsuites/testsuite.Attributes["hostname"].Value Test file /testsuites/testsuite/testcase/Attributes["classname"].Value Priority - Scope Field NUnit 2 Test run Title Test run title specified in the task Date started /test-results.Attributes["date"].Value + /test-results.Attributes["time"].Value Date completed Date started + /test-results/results/test-case.Attributes["time"].Value for all test cases Duration Date completed - Date started Attachments Results file used to publish test results Test result Title /test-results/results/test-case.Attributes["name"].Value Date started /test-results.Attributes["date"].Value + /test-results.Attributes["time"].Value Date completed Date started + /test-results/results/test-case.Attributes["time"].Value Duration /test-results/results/test-case.Attributes["time"].Value Owner build or release requested for user Outcome Failed: if exists /test-results/results/test-case/failure Not Executed: if exists /test-results/results/test-case.Attributes["result"].Value=="Ignored" Passed: for all other cases Error message /test-results/results/test-casefailure/message.InnerText Stack trace /test-results/results/test-case/failure/stack-trace.InnerText Attachments - Console log /test-results/results/test-case/failure/message.InnerText Console error log /test-results/results/test-case/output.InnerText Agent name /test-results/environment.Attributes["machine-name"].Value Test file /test-results/test-suite.Attributes["name"].Value Priority - Scope Field NUnit 3 Test run Title Test run title specified in the task Date started /test-run/start-time Date completed /test-run/end-time Duration Date completed - Date started Attachments Refer to Attachments support section below Test result Title /test-suite[@type='Assembly']/test-case.Attributes["name"].Value Date started /test-suite[@type='Assembly']/test-case.Attributes["start-time"].Value Date completed /test-suite[@type='Assembly']/test-case.Attributes["end-time"].Value Duration /test-suite[@type='Assembly']/test-case.Attributes["duration"].Value Owner build or release requested for user Outcome /test-results/test-suite/results/test-case.Attributes["result"].Value Error message /test-suite[@type='Assembly']/test-case/failure/message Stack trace /test-suite[@type='Assembly']//test-case/failure/stack-trace Attachments Refer to Attachments support section below Console log /test-suite[@type='Assembly']/test-case/failure/output Console error log - Agent name /test-suite[@type='Assembly']/environment.Attributes["machine-name"].Value Test file /test-suite[@type='Assembly'].Attributes["name"].Value Priority - Scope Field xUnit 2 Test run Title Test run title specified in the task Date started /assemblies/assembly/run-date + /assemblies/assembly/run-time Date completed Date started + /assemblies/assembly/time Duration Date completed - Date started Attachments Results file used to publish test results Test result Title /assemblies/assembly/collection/test.Attributes["method"].Value Date started /assemblies/assembly/run-date + /assemblies/assembly/run-time Date completed Date started + /assemblies/assembly/collection/test.Attributes["time"].Value Duration /assemblies/assembly/collection/test.Attributes["time"].Value Owner /assemblies/assembly/collection/test/traits/trait[@name='owner'].Attributes["value"].Value Outcome /assemblies/assembly/collection/test/failure.Attributes["result"].Value Error message /assemblies/assembly/collection/test/failure/message Stack trace /assemblies/assembly/collection/test/failure/stack-trace Attachments - Console log /assemblies/assembly/collection/test/failure/output Console error log - Agent name - Test file /assemblies/assembly.Attributes["name"].Value Priority /testcaseNode/traits/trait[@name='priority'].Attributes["value"].Value Scope Field CTest Test run Title Test run title specified in the task Date started /Site/Testing/StartTestTime.InnerText Date completed /Site/Testing/EndTestTime.InnerText Duration Date completed - Date started Attachments Results file, used to publish test results Test result Title /Site/Testing/Test/Name.InnerText Date started /Site/Testing/StartTestTime.InnerText Date completed Date Started + /Site/Testing/Test/Results/NamedMeasurement[@name= 'Execution Time']/Value.InnerText Duration /Site/Testing/Test/Results/NamedMeasurement[@name= 'Execution Time']/Value.InnerText Owner Build or release requested for user Outcome /Site/Testing/Test.Attributes["Status"].Value Error message - Stack trace /Site/Testing/Test/Results/Measurement/Value.InnerText Attachments - Console log - Console error log - Agent name - Test file /Site/Testing/Test/Path.InnerText Priority -Note
Duration is used only when Date started and Date completed are not available.
The fully qualified name format for testName is Namespace.Testclass.Methodname with a character limit of 512. If the test is data driven and has parameters, the character limit will include the parameters.
While publishing the test result, you may get this error: Failed to publish test results: Invalid Priority specified
This error occurs if any of the test methods has priority set above 255, fix the test method priority in the code and execute the tests again. You can review the trx file generated to see all the tests having priority greater than 255.
Attachments supportThe Publish Test Results task provides support for attachments for both test run and test results for the following formats. For public projects, we support 2GB of total attachments.
Visual Studio Test (TRX) Scope Type Path Test run Data Collector /TestRun/ResultSummary/CollectorDataEntries/Collector/UriAttachments/UriAttachment/A.Attributes["href"].Value Test Result /TestRun/ResultSummary/ResultFiles/ResultFile.Attributes["path"].Value Code Coverage /TestRun/TestSettings/Execution/AgentRule/DataCollectors/DataCollector/Configuration/CodeCoverage/Regular/CodeCoverageItem.Attributes["binaryFile"].Value And /TestRun/TestSettings/Execution/AgentRule/DataCollectors/DataCollector/Configuration/CodeCoverage/Regular/CodeCoverageItem.Attributes["pdbFile"].Value Test result Data Collectors /TestRun/Results/UnitTestResult/CollectorDataEntries/Collector/UriAttachments/UriAttachment/A.Attributes["href"].Value Or /TestRun/Results/WebTestResult/CollectorDataEntries/Collector/UriAttachments/UriAttachment/A.Attributes["href"].Value Or /TestRun/Results/TestResultAggregation/CollectorDataEntries/Collector/UriAttachments/UriAttachment/A.Attributes["href"].Value Test Result /TestRun/Results/UnitTestResult/ResultFiles/ResultFile.Attributes["path"].Value Or /TestRun/Results/WebTestResult/ResultFiles/ResultFile.Attributes["path"].Value Or /TestRun/Results/TestResultAggregation/ResultFiles/ResultFile.Attributes["path"].Value NUnit 3 Scope Path Test run /test-suite/attachments/attachment/filePath Test run /test-suite[@type='Assembly']/test-case/attachments/attachment/filePath JUnitJUnit attachment support was added in Azure DevOps sprint 229, and is not available in Azure DevOps Server 2022.1 and lower.
Scope Path Test Result /testsuites/testsuite/testcase/system-out/ -> Contents matching pattern [[ATTACHMENT|filePath]]Note
The option to upload the test results file as an attachment is a default option in the task, applicable to all formats.
Examples DockerFor Docker based apps, there are many ways to build your application and run tests:
In this approach, you build your code and run tests inside the container using a Docker file. The test results are then copied to the host to be published to the pipeline. To publish the test results to Azure Pipelines, you can use the Publish Test Results task. The final image will be published to Docker or Azure Container Registry.
Get the codeCreate a Dockerfile.build
file at the root of your project directory with the following:
# Build and run tests inside the docker container
FROM mcr.microsoft.com/dotnet/sdk:2.1
WORKDIR /app
# copy the contents of agent working directory on host to workdir in container
COPY . ./
# dotnet commands to build, test, and publish
RUN dotnet restore
RUN dotnet build -c Release
RUN dotnet test dotnetcore-tests/dotnetcore-tests.csproj -c Release --logger "trx;LogFileName=testresults.trx"
RUN dotnet publish -c Release -o out
ENTRYPOINT dotnet dotnetcore-sample/out/dotnetcore-sample.dll
This file contains the instructions to build code and run tests. The tests are then copied to a file testresults.trx
inside the container.
To make the final image as small as possible, containing only the runtime and deployment artifacts, replace the contents of the existing Dockerfile
with the following:
# This Dockerfile creates the final image to be published to Docker or
# Azure Container Registry
# Create a container with the compiled asp.net core app
FROM mcr.microsoft.com/dotnet/aspnet:2.1
# Create app directory
WORKDIR /app
# Copy only the deployment artifacts
COPY /out .
ENTRYPOINT ["dotnet", "dotnetcore-sample.dll"]
If you have a Docker Hub account, and want to push the image to your Docker registry, replace the contents of the .vsts-ci.docker.yml
file with the following:
# Build Docker image for this app, to be published to Docker Registry
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- script: |
docker build -f Dockerfile.build -t $(dockerId)/dotnetcore-build:$BUILD_BUILDID .
docker run --name dotnetcoreapp --rm -d $(dockerId)/dotnetcore-build:$BUILD_BUILDID
docker cp dotnetcoreapp:app/dotnetcore-tests/TestResults $(System.DefaultWorkingDirectory)
docker cp dotnetcoreapp:app/dotnetcore-sample/out $(System.DefaultWorkingDirectory)
docker stop dotnetcoreapp
- task: PublishTestResults@2
inputs:
testRunner: VSTest
testResultsFiles: '**/*.trx'
failTaskOnFailedTests: true
- script: |
docker build -f Dockerfile -t $(dockerId)/dotnetcore-sample:$BUILD_BUILDID .
docker login -u $(dockerId) -p $pswd
docker push $(dockerId)/dotnetcore-sample:$BUILD_BUILDID
env:
pswd: $(dockerPassword)
Alternatively, if you configure an Azure Container Registry and want to push the image to that registry, replace the contents of the .vsts-ci.yml
file with the following:
# Build Docker image for this app to be published to Azure Container Registry
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- script: |
docker build -f Dockerfile.build -t $(dockerId)/dotnetcore-build:$BUILD_BUILDID .
docker run --name dotnetcoreapp --rm -d $(dockerId)/dotnetcore-build:$BUILD_BUILDID
docker cp dotnetcoreapp:app/dotnetcore-tests/TestResults $(System.DefaultWorkingDirectory)
docker cp dotnetcoreapp:app/dotnetcore-sample/out $(System.DefaultWorkingDirectory)
docker stop dotnetcoreapp
- task: PublishTestResults@2
inputs:
testRunner: VSTest
testResultsFiles: '**/*.trx'
failTaskOnFailedTests: true
- script: |
docker build -f Dockerfile -t $(dockerId).azurecr.io/dotnetcore-sample:$BUILD_BUILDID .
docker login -u $(dockerId) -p $pswd $(dockerid).azurecr.io
docker push $(dockerId).azurecr.io/dotnetcore-sample:$BUILD_BUILDID
env:
pswd: $(dockerPassword)
Push the change to the main branch in your repository.
If you use Azure Container Registry, ensure you have pre-created the registry in the Azure portal. Copy the admin user name and password shown in the Access keys section of the registry settings in Azure portal.
Update your build pipeline with the following
Hosted Ubuntu 1604
/.vsts-ci.docker.yml
Queue a new build and watch it create and push a Docker image to your registry and the test results to Azure DevOps.
Create a new build pipeline using the Empty job.
Select Pipeline on the Tasks page of the build pipeline editor and edit its properties as follows
Hosted Ubuntu 1604
Add a Bash task and configure it as follows to build and copy artifacts to the host:
Type: Inline
Script: To build, test and copy artifacts to host, use the following script:
docker build -f Dockerfile.build -t $(dockerId)/dotnetcore-build:$BUILD_BUILDID .
docker run --name dotnetcoreapp --rm -d $(dockerId)/dotnetcore-build:$BUILD_BUILDID
docker cp dotnetcoreapp:app/dotnetcore-tests/TestResults $(System.DefaultWorkingDirectory)
docker cp dotnetcoreapp:app/dotnetcore-sample/out $(System.DefaultWorkingDirectory)
docker stop dotnetcoreapp
Add a Publish Test Results task to publish results to the pipeline, and edit its properties as follows:
VSTest
**/*.trx
Add a Bash task to publish the final image to the repository, and edit its properties as follows:
Type: Inline
Script:
To push to Docker Hub, use the following script:
docker build -f Dockerfile -t $(dockerId)/dotnetcore-sample:$BUILD_BUILDID .
docker login -u $(dockerId) -p $(dockerPassword)
docker push $(dockerId)/dotnetcore-sample:$BUILD_BUILDID
To push to Azure Container Registry, use the following script:
docker build -t $(dockerId).azurecr.io/dotnetcore-sample:$BUILD_BUILDID .
docker login -u $(dockerId) -p $(dockerPassword) $(dockerId).azurecr.io
docker push $(dockerId).azurecr.io/dotnetcore-sample:$BUILD_BUILDID
If you use Azure Container Registry, ensure you have pre-created the registry in the Azure portal. Copy the admin user name and password shown in the Access keys section of the registry settings in Azure Portal.
In the Variables tab of the build pipeline, define two variables:
Save the pipeline and queue a build. Watch it create and push a Docker image to your registry and the test results to Azure DevOps.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4