In this article we tackle all of the common challenges encountered when trying to do continuous integration with Azure DevOps aka VSTS aka TFS. Some critical topics that are tackled here are:
- How to work with Azure DevOps environment variables
- How to create a build pipeline
By the way, if you aren’t aware, TFS, VSTS and Azure DevOps are all technically the same solution. Over several years, Microsoft did a lot of rebranding that created the confusion between all of these products. Hence it went from TFS to VSTS to Azure DevOps relatively quickly. Causing lots of confusion. The latest version is called Azure DevOps. I hope that it stays with this name for the foreseeable future 🙏
Sauce Labs with Azure DevOps
Sauce Labs is an extremely popular service for performing 360 degree testing in the cloud. Let’s talk about how to set it up to work with Azure DevOps.
Limitations
- As of March 2022, Sauce Labs does not have any plugins that can be used in Azure DevOps. You must write your own test commands to run tests and start Sauce Connect
- It’s not possible to view the videos and images of your Sauce Labs tests in Azure DevOps. Instead, we must navigate to saucelabs.com to see that information. However, you will get pass/fail information.
Pre-requisites
- Have a Sauce Labs account
- Have an existing Azure DevOps Pipeline
C# with Sauce Labs and Azure DevOps
1. Add your Sauce username and access key in ADO
Open your Pipeline and click Variables.
My recommendation is that you name the variables to something similar that I have above. Do not name your ADO variables the same as your Environment variables as that will cause you issues when you are trying to read them. So don't name your ADO variable SAUCE_USER_NAME for example
2. C# source code should reference environment variables like this
// testFile.cs var sauceUserName = Environment.GetEnvironmentVariable("SAUCE_USERNAME"); var sauceAccessKey = Environment.GetEnvironmentVariable("SAUCE_ACCESS_KEY");
Make sure that you do NOT set the EnvironmentVariableTarget.User as your 2nd parameter as Azure DevOps will not be able to read that variable.
3. Read values from Azure Variables in your .yml
- task: DotNetCoreCLI@2 displayName: 'Run tests' env: SAUCE_USERNAME: $(sauceUsername) #this will store the value from 'sauceUsername' into SAUCE_USERNAME SAUCE_ACCESS_KEY: $(sauceKey)
Here’s an example of displaying an environment variable
- bash: echo $(SAUCE_USERNAME) # will output our username stored in SAUCE_USERNAME env variable
Learn more about VSTS aka Azure DevOps logging commands. Check out this repo with a fully working example.
An excellent blog about environment variables in ADO.
Use YML and it will be easy. Use Classic Editor and this process will be hard.
NodeJS with SauceLabs and Azure DevOps
- Go to Pipelines and create a new pipeline
- Link the new pipeline to your repository. You will likely need to provide permissions to Azure Pipelines in your repository management system.
- Create a YML file that looks like the code below
# Node.js # Build a general Node.js project with npm. # Add steps that analyze code, save build artifacts, deploy, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/javascript trigger: - main pool: vmImage: ubuntu-latest # multiple pipelines can re-use variables that are stored in a variable group variables: - group: sauce-labs-variables steps: - task: NodeTool@0 inputs: versionSpec: '14.x' displayName: 'Install Node.js' # Below we navigate to the working directory, install node packages, run tests on Sauce. # Make sure to set SAUCE_USERNAME and SAUCE_ACCESS_KEY variables - script: | cd ./webdriverio/webdriver/examples/w3c/ npm install npm run test.saucelabs.us -- --logLevel "debug" #it's really wise to enable a high level of logging for CI env: SAUCE_USERNAME: $(sauceUsername) #this will read the value from 'sauceUsername' in ADO and will store it into SAUCE_USERNAME env variable SAUCE_ACCESS_KEY: $(sauceAccessKey) displayName: 'install and run WebdriverIO tests in Sauce Labs'
Ensure that you have your environment variables stored in Azure DevOps.
Learn more by following Azure DevOps docs on JavaScript and Node.js.
Java with Azure Pipelines and Sauce Labs
If you would like to reuse environment variables across multiple pipelines, then you need to use variable groups. It’s important to know that if use “group”, then you now need to list your other variables in a key/value pairs.
variables:
- group: sauce-labs-variables
- name: solution
value: '**/*.sln'
- name: buildPlatform
value: 'Any CPU'
- name: buildConfiguration
value: 'Release'
Automation pipeline in Azure DevOps with .NET Framework
In this section, we will cover automated testing pipelines in Azure Pipelines.
Working Azure DevOps pipeline with automated tests in .yml
Staged test execution in Azure DevOps
What if you want to run different suites in your Azure pipeline so that you have a gated release. For example, you should be trying to run unit tests first, followed by integration tests, followed by acceptance tests. In that case, you need the ability to filter.
By default, Azure DevOps will attempt to run all of your tests in your solution. Regardless of whether you are using NUnit or MsTest or something weird like XUnit (although I never tried with this and wouldn’t)
YAML file to run tests
Important points about YAML file
I couldn’t get searchFolder
to filter out directories
However, using testAssemblyVer2
worked really well
Filtering tests using Azure DevOps
In order to be able to have a staged test execution in our continuous integration pipeline, we need to be able to filter our tests. I have 100s of tests in this repo but I would only like to run the tests that have [Category(“BestPractices”)] from Nunit.
Furthermore, I would like to exclude all of the performance tests, even though they are also categorized as “BestPractices”. As a result, the configuration of our Azure DevOps task looks like this.
And here is what the same exact thing looks like in a .yml
steps:
- task: VSTest@2
displayName: 'Run Best Practices Tests without performance'
inputs:
testFiltercriteria: 'TestCategory=BestPractices&TestCategory!=Performance'
runInParallel: true
testRunTitle: 'Best Practices Tests'
More on the filtering capabilities in Azure DevOps aka VSTS aka TFS
How to package Nuget using Azure DevOps?
Phenomenal resource that will walk you through the process.
This is a resource that helps you to understand how to work with Nuget in .NET Standard.
Set up a Service connection to Nuget in your project settings
You do need to have an MSDN account and then you can create a Nuget.org account.
How to publish the Nuget package
- Download Nuget.exe
- Add a nuget.config file
- Run command
nuget restore
- Run command
.\nuget.exe push -Source "Simple.Sauce" -ApiKey az "C:\Source\SauceLabs\simple_sauce\dotnet\Simple.Sauce\bin\Debug\Simple.Sauce.0.1.1-debug.nupkg"
Why DevOps?
Adding continuous integration
- Select Builds > Edit > Triggers. Under Continuous integration, select on the name of your repository.
- Toggle on the checkbox labeled Enable continuous integration.
- You can select CI for both merges and Pull Requests – https://prnt.sc/kb0g6n
How to create scheduled builds
- Picking up from the section above, click the Add button under Scheduled section
- Update the time and the day of when you want to run your builds
- Save & queue
How to set up your test .dll paths
Docs from MS on file matching patterns
The hardest time I had was how to configure my paths for my automation .DLL files. It’s not intuitive to know what is the working directory of your code base.
Here are some examples of what’s worked for me:
Executable Paths
"C:\Source\Github\dot-net-sauce\SauceExamples\Web.Tests\bin\Debug\Web.Tests.dll" | '**\$(BuildConfiguration)\**\Web.Tests.dll' |
---|---|
"C:\Source\Github\dot-net-sauce\SauceExamples\SeleniumNunit\bin\Debug\SeleniumNunit.dll" | '**\$(BuildConfiguration)\**\SeleniumNunit.dll' |
How to pass parameters to test code from a build or release pipeline?
A: Use a runsettings file to pass values as parameters to your test code. For example, in a release that contains several stages, you can pass the appropriate app URL to each the test tasks in each one. The runsettings file and matching parameters must be specified in the Visual Studio Test task.
How to add a status badge to your Github repo
The instructions on this are really good from Microsoft and you can follow them here in the Get the status badge section
- Building open source projects with Azure DevOps
- Azure DevOps for .NET teams
- Get started with DevOps on Azure
- VS for Mac
- VS 2017 Productivity updates
Trackbacks/Pingbacks