I am running a pytest-based suite of tests during my Azure DevOps build process. I have two jobs arranged to run these tests against two different environments.
In each job, I run the pytest tests using a script task and generate a junit-style xml output file, then have a PublishTestResults task publish that xml file. This is working great, and I'm able to peruse my test results in the azure build tests report UI -- but only if all the tests pass. If any tests fail, the publish task is skipped, and the tests aren't reported in the UI.
YML extract:
- job: 'RunTestsQA'
continueOnError: True
steps:
- task: UsePythonVersion#0
inputs:
versionSpec: '3.6'
architecture: 'x64'
- task: DownloadSecureFile#1
inputs:
secureFile: 'ConfigFile'
- script: pip install -r requirements.txt
displayName: 'Install Requirements'
- script: |
pytest -m smoke --ENV=qa --log-file $SYSTEM_ARTIFACTSDIRECTORY/smoke-qa.log --junitxml="TEST-qa-smoke.xml"
displayName: 'Test with pytest'
# PUBLISH JUNIT RESULTS
- task: PublishTestResults#2
inputs:
condition: succeededOrFailed()
testResultsFormat: 'JUnit' # Options: JUnit, NUnit, VSTest, xUnit
testResultsFiles: '**/TEST-*.xml'
#searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
mergeTestResults: false # Optional
testRunTitle: 'API_CHECK QA'
#buildPlatform: # Optional
#buildConfiguration: # Optional
publishRunAttachments: true # Optional
Through some experimentation, I've been able to confirm the XML file is always created. What do I need to fix here? A test report isn't super helpful if it only shows up when the tests pass.
In your task description, the condition is effectively listed as a task input, and hence won't be taken into account at all.
You had:
# PUBLISH JUNIT RESULTS
- task: PublishTestResults#2
inputs:
condition: succeededOrFailed()
testResultsFormat: 'JUnit' # Options: JUnit, NUnit, VSTest, xUnit
testResultsFiles: '**/TEST-*.xml'
The correct setup is
# PUBLISH JUNIT RESULTS
- task: PublishTestResults#2
inputs:
testResultsFormat: 'JUnit' # Options: JUnit, NUnit, VSTest, xUnit
testResultsFiles: '**/TEST-*.xml'
condition: succeededOrFailed()
The full list of things you can do with conditions is here
I'm using Ruby and Minitest, but I have found that the following setting allows the PublishTestResults task to run:
- script: |
pytest -m smoke --ENV=qa --log-file $SYSTEM_ARTIFACTSDIRECTORY/smoke-qa.log --junitxml="TEST-qa-smoke.xml"
displayName: 'Test with pytest'
continueOnError: true
The only issue that I have found with this setting is that if the build fails, it reports as "Partially Succeeded" and not "Failed".
edit:
Of course, if your build process has any deploy tasks after the test task, you may not want to use this setting.
Related
How do we include unit test in .Net azure build pipeline. Unit testing should happen before before the build process and when the unit test is Succeeded only then the build should happen.
You need to build your app first to be able to run unit tests. Or you can just run dotnet test command which makes sure that first your nuget packages are restored, app is build and then unit test run.
Please check this documentation
Here is an example pipeline:
- task: UseDotNet#2
inputs:
version: '5.0.x'
includePreviewVersions: true # Required for preview versions
- task: DotNetCoreCLI#2
displayName: 'dotnet build'
inputs:
command: 'build'
configuration: $(buildConfiguration)
- task: DotNetCoreCLI#2
displayName: 'dotnet test'
inputs:
command: 'test'
arguments: '--configuration $(buildConfiguration) --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura'
publishTestResults: true
projects: 'MyTestLibrary' # update with your test project directory
I have a build pipeline as shown below
variables:
- name: BuildParameters.solution
value: '**/*.sln'
- name: buildConfiguration
value: Release
name: $(date:yyyyMMdd)$(rev:.r)
trigger: none
resources:
repositories:
- repository: self
type: git
stages:
- stage: __default
jobs:
- job: Job_1
displayName: Agent job 1
pool:
vmImage: windows-2019
steps:
- task: UseDotNet#2
displayName: '.NET Core 3.1.404'
inputs:
version: '3.1.404'
packageType: sdk
- task: DotNetCoreCLI#2
enabled: true
displayName: dotnet test
continueOnError: true
timeoutInMinutes: 0
inputs:
command: test
projects: '**/*test/*.csproj'
arguments: --configuration $(buildConfiguration) --verbosity n --collect "Code coverage"
publishTestResults: true
- task: PublishTestResults#2
inputs:
testResultsFormat: XUnit
testResultsFiles: '**/TEST.xml'
mergeTestResults: true
failTaskOnFailedTests: true
I have broken a test on purpose
This test fails, but the publish test results task doesnt fail outright
I get the warning
##[warning]No test result files matching **/TEST.xml were found. xunit
Has anyone ever had this?
Annoyingly if a test fails the Azure pipeline classes this as a partial success which is not ideal. I am trying to get into a situation where if a test fails, my pipeline fails
This pipeline is used to verify pull requests - i.e. do a build of the code in the PR and ensure that all tests pass
When I searched for this there were references to installing .NET 4.6.2 or later, but this is being used inside a build pipeline, so not sure how to do that
Have I missed something in the dot net test task?
Paul
When you set publishTestResults field to true for dotnet test task. See below extract from here.
This option appends --logger trx --results-directory $(Agent.TempDirectory) to the command line arguments.
Above commands will generate the test result in VSTest(trx) format and output the result to folder $(Agent.TempDirectory)
So you need to change the PublishTestResults#2 task like below:
- task: PublishTestResults#2
inputs:
testResultsFormat: VSTest #change the format to VSTest
testResultsFiles: '**/*.trx' #change to find .trx file
mergeTestResults: true
failTaskOnFailedTests: true
searchFolder: '$(Agent.TempDirectory)' #search the .trx file in $(Agent.TempDirectory)
Usually the continueOnError field is set to false by default. And the dotnet test task will fail if there is any test fails, See below:
If the continueOnError field is set to true. The dotnet test task and the pipeline will show Warnig state.
So you can have a try setting the continueOnError field to false, which will fail the task and pipeline if there is any test fails. And there will not be no need to use PublishTestResults task. For publishTestResults is set to true for dotnet test task, the test result will be automatically published by the dotnet test task. See below:
- task: DotNetCoreCLI#2
enabled: true
displayName: dotnet test
continueOnError: false
timeoutInMinutes: 0
inputs:
command: test
projects: '**/*test/*.csproj'
arguments: --configuration $(buildConfiguration) --verbosity n --collect "Code coverage"
publishTestResults: true
I've an yaml based azure CI/CT pipeline. I've a task defined as below:
- task: PublishTestResults#2
displayName: 'Publish PCOM Test Results'
condition: always()
inputs:
testResultsFormat: NUnit
testResultsFiles: '*.xml'
searchFolder: '$(Common.TestResultsDirectory)/$(Build.SourceBranchName)/$(Build.BuildNumber)/test-results/PCOM'
mergeTestResults: true
testRunTitle: 'PCOM Tests'
It looks for all '*.xml' files under a particular s3 location. But the xml files will be created only if the below task is successful:
- bash: 'perl run_aws_cli.pl $(Build.BuildNumber) $(Build.SourceBranchName) $(s3Bucket) $(Build.SourcesDirectory)'
workingDirectory: 'azure-pipeline/scripts'
displayName: 'Run ECS Tasks'
So I want a custom condition to check if the later task is successful then only search xml files in the directory else don't search for it.
Currently it's searching always and the earlier task(Publish PCOM Test Results) is failing.
just do condition: succeeded() on your second task. this will only run if all the tasks before that run successfully. if you want a more sophisticated option, check this thread.
Alternatively, you can probably get more information on the build status from the API.
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/get?view=azure-devops-rest-5.1
I have a relative simple test project under Azure DevOps and I want to generate code coverage.
This works... kinda. I get this:
I get the files I needed ( I think at least) But the tab is missing.
I have those three steps:
Do .NET test task
Install report generator
Run report generator to convert ( -reporttypes:HtmlInline_AzurePipelines;Cobertura")
publish result (s)
But the tab is not showing up? Any ideas?
- stage: Run_Unit_tests
jobs:
- job: 'Tests'
pool:
vmImage: 'windows-latest'
variables:
buildConfiguration: 'Release'
continueOnError: true
steps:
- task: DotNetCoreCLI#2
inputs:
command: custom
custom: tool
arguments: install --tool-path . dotnet-reportgenerator-globaltool
displayName: Install ReportGenerator tool
- task: DotNetCoreCLI#2
displayName: Test .NET
inputs:
command: test
projects: '**/*Test/*.csproj'
arguments: '--configuration $(buildConfiguration) --logger trx --collect:"XPlat Code Coverage"'
condition: succeededOrFailed()
- task: reportgenerator#4
inputs:
reports: '$(Agent.TempDirectory)\**\coverage.cobertura.xml'
targetdir: '$(Build.SourcesDirectory)\coverlet\reports'
verbosity: 'Verbose'
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: $(Build.SourcesDirectory)\coverlet\reports\Cobertura.xml
failIfCoverageEmpty: false
reportDirectory: $(Build.SourcesDirectory)\coverlet\reports\
I tried with code generator, without, enable code coverage variable or disable, tried with report generator and without...
I had the same problem, and just pressed F5 and it appeared!
It's mad, but it actually does it consistently.
It seems there's occasionally a bug in the devops front-end code?
You can try below yaml to publish code coverage.
First you need to make sure your project reference to nuget package coverlet.msbuild
<PackageReference Include="coverlet.msbuild" Version="2.5.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Then in your dotnet test task to enable CollectCoverage
arguments: '/p:CollectCoverage=true /p:CoverletOutput=$(Build.SourcesDirectory)\TestResult\ /p:CoverletOutputFormat=cobertura'
Then in reportgenerator task specify the reports folder to the CoverletOutput folder reports: '$(Build.SourcesDirectory)\TestResult\**\coverage.cobertura.xml'
Please check below yaml for reference:
steps:
- task: UseDotNet#2
inputs:
version: 2.2.x
- task: DotNetCoreCLI#2
inputs:
command: restore
projects: '**\*.csproj'
- task: DotNetCoreCLI#2
inputs:
command: custom
custom: tool
arguments: install --tool-path . dotnet-reportgenerator-globaltool
displayName: Install ReportGenerator tool
- task: DotNetCoreCLI#2
displayName: Test .NET
inputs:
command: test
projects: '**\*Test*.csproj'
publishTestResults: false
arguments: '--configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutput=$(Build.SourcesDirectory)\TestResult\ /p:CoverletOutputFormat=cobertura'
condition: succeededOrFailed()
- task: reportgenerator#4
inputs:
reports: '$(Build.SourcesDirectory)\TestResult\**\coverage.cobertura.xml'
targetdir: '$(Build.SourcesDirectory)\coverlet\reports'
verbosity: 'Verbose'
condition: succeededOrFailed()
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: $(Build.SourcesDirectory)\coverlet\reports\Cobertura.xml
failIfCoverageEmpty: false
reportDirectory: $(Build.SourcesDirectory)\coverlet\reports\
condition: succeededOrFailed()
You can also refer to this blog.
I had this issue too and tracked it down to having a mixture of VS Test and dotnet test tasks in my pipeline. Once I removed the VS Test task it all worked.
It seems the VS Test task uploads its own code coverage results and the combination of publishing cobertura results + this VS Test task confused Azure Devops.
I have some unit tests written with jest. Obviously, sometimes they fail. I want to publish the result to the build Test section.
The problem is task PublishTestResults#2 never runs if a previous task fails, hence no data in test section of the build.
In this case, what I get is the message ##[error]Bash exited with code '1'..
Here is my azure-pipelines.yml:
- script: npm run test:publish
displayName: "Run Unit Tests"
- script: npm run build
displayName: "Build"
- task: PublishTestResults#2
displayName: "Publish unit test result"
inputs:
testResultsFiles: "unit_test_report.xml"
testRunTitle: "Unit tests with Jest"
mergeTestResults: false
searchFolder: "$(Build.SourcesDirectory)"
condition: always()
failTaskOnFailedTests: false
What am I missing?
You have indented condition: always() one place too far in your YAML, it should sit at the same level as displayName