Azure DevOps Integration with Cloud Testing Platforms
How to integrate Azure DevOps with cloud testing platforms — BrowserStack, Sauce Labs, and LambdaTest. Covers service connection setup, pipeline YAML for cloud browser tests, result reporting, and cost optimisation strategies.
Cloud testing platforms give your Azure DevOps pipeline access to thousands of real browsers and devices without managing any infrastructure. This guide covers integration with BrowserStack, Sauce Labs, and LambdaTest.
Why cloud testing platforms with Azure DevOps
Microsoft-hosted agents provide Chrome and Firefox. For comprehensive cross-browser and mobile testing you need real Safari on iOS, real Android devices, older browser versions, and specific OS combinations. Cloud platforms provide all of this on demand.
BrowserStack integration
Service connection setup
- Go to Project Settings → Service connections → New
- Type: BrowserStack (from Marketplace extension)
- Enter: BrowserStack username and access key
Or use a generic service connection and reference credentials via variable group.
Pipeline YAML — Playwright on BrowserStack
trigger:
branches:
include: [main]
pool:
vmImage: ubuntu-latest
variables:
- group: browserstack-credentials
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
- script: npm ci
displayName: Install packages
- script: npm install -g browserstack-local
displayName: Install BrowserStack Local
- script: |
# Start BrowserStack Local tunnel for staging (non-public) environments
BrowserStackLocal --key $(BROWSERSTACK_KEY) \
--local-identifier $(Build.BuildId) &
sleep 5
displayName: Start local tunnel
condition: eq(variables['STAGING_IS_LOCAL'], 'true')
- script: |
npx playwright test \
--config=playwright.browserstack.config.ts
displayName: Run tests on BrowserStack
env:
BROWSERSTACK_USERNAME: $(BROWSERSTACK_USERNAME)
BROWSERSTACK_ACCESS_KEY: $(BROWSERSTACK_KEY)
BUILD_NAME: $(Build.BuildNumber)
BUILD_ID: $(Build.BuildId)
- task: PublishTestResults@2
inputs:
testResultsFormat: JUnit
testResultsFiles: test-results/browserstack.xml
testRunTitle: BrowserStack — $(Build.BuildNumber)
condition: always()Playwright BrowserStack config
// playwright.browserstack.config.ts
import { defineConfig } from '@playwright/test'
export default defineConfig({
reporter: [
['junit', { outputFile: 'test-results/browserstack.xml' }],
['html'],
],
projects: [
{
name: 'Chrome/Windows10',
use: {
connectOptions: {
wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify({
browser: 'chrome',
browser_version: 'latest',
os: 'Windows',
os_version: '10',
name: 'Chrome Windows 10',
build: process.env.BUILD_NAME,
'browserstack.username': process.env.BROWSERSTACK_USERNAME,
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY,
}))}`,
},
},
},
{
name: 'Safari/macOS13',
use: {
connectOptions: {
wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify({
browser: 'playwright-webkit',
os: 'OS X',
os_version: 'Ventura',
name: 'Safari macOS Ventura',
build: process.env.BUILD_NAME,
'browserstack.username': process.env.BROWSERSTACK_USERNAME,
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY,
}))}`,
},
},
},
],
})Sauce Labs integration
steps:
- script: npm ci
- script: |
npx playwright test \
--config=playwright.saucelabs.config.ts
env:
SAUCE_USERNAME: $(SAUCE_USERNAME)
SAUCE_ACCESS_KEY: $(SAUCE_ACCESS_KEY)// playwright.saucelabs.config.ts
export default defineConfig({
projects: [{
name: 'Sauce Chrome',
use: {
connectOptions: {
wsEndpoint: `wss://ondemand.us-west-1.saucelabs.com/wd/hub?username=${process.env.SAUCE_USERNAME}&access_key=${process.env.SAUCE_ACCESS_KEY}`,
},
},
}],
})LambdaTest integration
steps:
- script: |
npx playwright test \
--config=playwright.lambdatest.config.ts
env:
LT_USERNAME: $(LT_USERNAME)
LT_ACCESS_KEY: $(LT_ACCESS_KEY)Cost optimisation strategies
Cloud platforms charge per test minute. Keep costs manageable:
# Run cloud tests only on main branch merges, not every PR
- stage: CloudBrowserTests
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- job: BrowserStack
steps:
# Run only smoke tests on cloud — full regression locally
- script: npx playwright test --grep @cross-browser# Limit parallel sessions to control costs
# In playwright.browserstack.config.ts:
workers: 3, # BrowserStack free tier: 5 parallel sessions — use 3 for safetyCommon errors and fixes
Error: BrowserStack tests fail with "Authentication failed"
Fix: Verify BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY are set correctly. The username is your email address, not a generated string.
Error: Tests connect but can't reach the staging URL Fix: If staging is not publicly accessible, start the BrowserStack Local tunnel before running tests. The tunnel creates a secure connection between BrowserStack's nodes and your private environment.
Error: Test results don't appear on BrowserStack dashboard
Fix: Include build and name in the capabilities object. Without these, BrowserStack creates sessions with auto-generated names that don't correlate to your pipeline runs.
Stay ahead in AI-driven QA
Get practical tutorials on test automation, AI testing, and quality engineering — straight to your inbox. No spam, unsubscribe any time.
Discussion
Sign in with GitHub to comment · powered by Giscus