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
Related
I have a react app, created with npx create-react-app command, and configured a yaml based azure devops pipeline for CI/CD. Then I added some simple unit tests.
I added a script task in my yaml pipeline to generate coverage results as follows.
- script: |
cd reactonazure
npm run test -- --coverage --ci --reporters=default --reporters=jest-junit --coverageReporters=cobertura
displayName: 'test code coverage'
But this tasks displays the following output and then task continues to run and never ends. I have to cancel the pipeline run to ultimately stop it. Not sure whats happening. Any ideas?
No tests found related to files changed since last commit.
But when I prefix with CI=true to make the command as follows, then the command works fine and I get test results, but no where I find coverage report(cobertura-coverage.xml).
CI=true npm test -- --reporters=jest-junit --reporters=default --coverageReporters=cobertura
I added a simple script task shown below to list out the files and folders to enable me search for cobertura-coverage.xml. But no where I found the file. Note that jest.xml file is being created. And that is the reason why I am able to see the test results shown above. The problem is with test coverage report.
- script: |
pwd
cd ..
pwd
ls -Rla
displayName: 'list out the files and folders for inspection'
Also when I run the following command on vs code command prompt on my machine(Windows 10), I do see a file named cobertura-coverage.xml in coverage folder.
npm run test -- --coverage --ci --reporters=default --reporters=jest-junit --coverageReporters=cobertura
The full pipeline yaml is pasted below.
trigger:
- master
variables:
azureSubscription: 'AzureServiceConnection'
# Web app name
webAppName: BasicReactApp
# Environment name
environmentName: Dev
# Agent VM image name
vmImageName: 'ubuntu-latest'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: NodeTool#0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- script: |
cd reactonazure
npm install
npm run build --if-present
displayName: 'npm install, build '
- script: |
cd reactonazure
CI=true npm test -- --reporters=jest-junit --reporters=default --coverageReporters=cobertura
displayName: 'test code coverage'
- task: PublishTestResults#2
displayName: "Publish Test Results"
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'reactonazure/junit.xml'
failTaskOnFailedTests: true
mergeTestResults: true
condition: succeededOrFailed()
# The following, two are not functioning as no coverage.cobertura.xml file is being created.
- task: PublishCodeCoverageResults#1
displayName: "Publish code coverage"
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: "reactonazure/$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml"
reportDirectory: "reactonazure/$(System.DefaultWorkingDirectory)/coverage"
failIfCoverageEmpty: false
- task: PublishCodeCoverageResults#1
displayName: 'Publish code coverage report'
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
failIfCoverageEmpty: true
Are there any other ways to generate report on the pipeline?
The path you provided to the coverage file is incorrect. It should be $(System.DefaultWorkingDirectory)/reactonazure/coverage/cobertura-coverage.xml.
The task would look like this:
- task: PublishCodeCoverageResults#1
displayName: "Publish code coverage"
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: "$(System.DefaultWorkingDirectory)/reactonazure/coverage/cobertura-coverage.xml"
reportDirectory: "$(System.DefaultWorkingDirectory)/reactonazure/coverage"
failIfCoverageEmpty: false
The command to generate the report that I presented earlier is not working. The following is finally working.
CI=true npm run test -- --coverage --watchAll=false --ci --reporters=default --reporters=jest-junit --coverageReporters=cobertura
The full and final yaml after taking into account the suggested answer is below.
trigger:
- master
variables:
azureSubscription: 'AzureServiceConnection'
webAppName: BasicReactApp
environmentName: Dev
vmImageName: 'ubuntu-latest'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: NodeTool#0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- script: |
cd reactonazure
npm install
npm run build --if-present
displayName: 'npm install, build '
- script: |
cd reactonazure
CI=true npm run test -- --coverage --watchAll=false --ci --reporters=default --reporters=jest-junit --coverageReporters=cobertura
displayName: 'Test with code coverage'
- task: PublishTestResults#2
displayName: "Publish Test Results"
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'reactonazure/junit.xml'
failTaskOnFailedTests: true
mergeTestResults: true
condition: succeededOrFailed()
- task: PublishCodeCoverageResults#1
displayName: "Publish code coverage"
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: "$(System.DefaultWorkingDirectory)/reactonazure/coverage/cobertura-coverage.xml"
reportDirectory: "$(System.DefaultWorkingDirectory)/reactonazure/coverage"
failIfCoverageEmpty: false
- task: ArchiveFiles#2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)/reactonazure/build'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
- stage: Deploy
displayName: Deploy stage
dependsOn: Build
condition: succeeded()
jobs:
- deployment: Deploy
displayName: Deploy
environment: $(environmentName)
pool:
vmImage: $(vmImageName)
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp#1
displayName: 'Azure Web App Deploy'
inputs:
azureSubscription: $(azureSubscription)
#appType: webAppLinux
appType: webApp
appName: $(webAppName)
runtimeStack: 'NODE|16.x'
package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
startUpCommand: 'npm run start'
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 YAML pipeline which doesnt always obey the project build order
- 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: falsefo
inputs:
command: test
projects: '**/*test/*.csproj'
arguments: --configuration $(buildConfiguration)
publishTestResults: true
This means that for some executions of the pipeline I get the error
Unable to find package NETStandard.Library with version (>= 2.0.3)
This occurs on a project that is not first to build in Visual Studio
Is there anyway of enforcing the build order? Or getting this package?
Paul
Unable to find package NETStandard.Library with version (>= 2.0.3). Is
there anyway of enforcing the build order? Or getting this package?
The problem is that the NETStandard.Library package was not found. I think it has nothing to do with the build order of the projects. NETStandard.Library is a nuget package, you can try to add a nuget restore task to the pipeline.
- task: NuGetCommand#2
inputs:
command: 'restore'
feedsToUse: 'config'
nugetConfigPath: 'nuget.config'
Is there anyway of enforcing the build order? Or getting this package?
You could build/test the specify project at first:
- task: DotNetCoreCLI#2
enabled: true
displayName: dotnet test
continueOnError: falsefo
inputs:
command: test
projects: '**/*test/TheSpecifyProject.csproj'
arguments: --configuration $(buildConfiguration)
publishTestResults: true
Then build/test other projects:
- task: DotNetCoreCLI#2
enabled: true
displayName: dotnet test
continueOnError: falsefo
inputs:
command: test
projects: '**/*test/*.csproj'
arguments: --configuration $(buildConfiguration)
publishTestResults: true
Or
- task: DotNetCoreCLI#2
enabled: true
displayName: dotnet test
continueOnError: falsefo
inputs:
command: test
projects: |
**/*test/*.csproj
!**/*test/TheSpecifyProject.csproj
arguments: --configuration $(buildConfiguration)
publishTestResults: true
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 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.