DevOps 3 min read

Azure DevOps Cloud Testing Integration

How to integrate Azure DevOps with cloud testing platforms — BrowserStack, Sauce Labs, and LambdaTest. Covers service connection setup, pipeline YAML for.

I
InnovateBits
InnovateBits

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

  1. Go to Project Settings → Service connections → New
  2. Type: BrowserStack (from Marketplace extension)
  3. Enter: BrowserStack username and access key

Or use a generic service connection and reference credentials via variable group.

Pipeline YAML — Playwright on BrowserStack

YAML
1trigger: 2 branches: 3 include: [main] 4 5pool: 6 vmImage: ubuntu-latest 7 8variables: 9 - group: browserstack-credentials 10 11steps: 12 - task: NodeTool@0 13 inputs: 14 versionSpec: '20.x' 15 16 - script: npm ci 17 displayName: Install packages 18 19 - script: npm install -g browserstack-local 20 displayName: Install BrowserStack Local 21 22 - script: | 23 # Start BrowserStack Local tunnel for staging (non-public) environments 24 BrowserStackLocal --key $(BROWSERSTACK_KEY) \ 25 --local-identifier $(Build.BuildId) & 26 sleep 5 27 displayName: Start local tunnel 28 condition: eq(variables['STAGING_IS_LOCAL'], 'true') 29 30 - script: | 31 npx playwright test \ 32 --config=playwright.browserstack.config.ts 33 displayName: Run tests on BrowserStack 34 env: 35 BROWSERSTACK_USERNAME: $(BROWSERSTACK_USERNAME) 36 BROWSERSTACK_ACCESS_KEY: $(BROWSERSTACK_KEY) 37 BUILD_NAME: $(Build.BuildNumber) 38 BUILD_ID: $(Build.BuildId) 39 40 - task: PublishTestResults@2 41 inputs: 42 testResultsFormat: JUnit 43 testResultsFiles: test-results/browserstack.xml 44 testRunTitle: BrowserStack — $(Build.BuildNumber) 45 condition: always()

Playwright BrowserStack config

TYPESCRIPT
1// playwright.browserstack.config.ts 2import { defineConfig } from '@playwright/test' 3 4export default defineConfig({ 5 reporter: [ 6 ['junit', { outputFile: 'test-results/browserstack.xml' }], 7 ['html'], 8 ], 9 projects: [ 10 { 11 name: 'Chrome/Windows10', 12 use: { 13 connectOptions: { 14 wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify({ 15 browser: 'chrome', 16 browser_version: 'latest', 17 os: 'Windows', 18 os_version: '10', 19 name: 'Chrome Windows 10', 20 build: process.env.BUILD_NAME, 21 'browserstack.username': process.env.BROWSERSTACK_USERNAME, 22 'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY, 23 }))}`, 24 }, 25 }, 26 }, 27 { 28 name: 'Safari/macOS13', 29 use: { 30 connectOptions: { 31 wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify({ 32 browser: 'playwright-webkit', 33 os: 'OS X', 34 os_version: 'Ventura', 35 name: 'Safari macOS Ventura', 36 build: process.env.BUILD_NAME, 37 'browserstack.username': process.env.BROWSERSTACK_USERNAME, 38 'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY, 39 }))}`, 40 }, 41 }, 42 }, 43 ], 44})

Sauce Labs integration

YAML
1steps: 2 - script: npm ci 3 4 - script: | 5 npx playwright test \ 6 --config=playwright.saucelabs.config.ts 7 env: 8 SAUCE_USERNAME: $(SAUCE_USERNAME) 9 SAUCE_ACCESS_KEY: $(SAUCE_ACCESS_KEY)
TYPESCRIPT
1// playwright.saucelabs.config.ts 2export default defineConfig({ 3 projects: [{ 4 name: 'Sauce Chrome', 5 use: { 6 connectOptions: { 7 wsEndpoint: `wss://ondemand.us-west-1.saucelabs.com/wd/hub?username=${process.env.SAUCE_USERNAME}&access_key=${process.env.SAUCE_ACCESS_KEY}`, 8 }, 9 }, 10 }], 11})

LambdaTest integration

YAML
1steps: 2 - script: | 3 npx playwright test \ 4 --config=playwright.lambdatest.config.ts 5 env: 6 LT_USERNAME: $(LT_USERNAME) 7 LT_ACCESS_KEY: $(LT_ACCESS_KEY)

Cost optimisation strategies

Cloud platforms charge per test minute. Keep costs manageable:

YAML
1# Run cloud tests only on main branch merges, not every PR 2- stage: CloudBrowserTests 3 condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) 4 jobs: 5 - job: BrowserStack 6 steps: 7 # Run only smoke tests on cloud — full regression locally 8 - script: npx playwright test --grep @cross-browser
YAML
1# Limit parallel sessions to control costs 2# In playwright.browserstack.config.ts: 3workers: 3, # BrowserStack free tier: 5 parallel sessions — use 3 for safety

Common 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.

Tags
#azure-devops#browserstack#sauce-labs#lambdatest#cloud-testing#cross-browser-testing#azure-pipelines

Share this article

Follow for more

Follow me on social media for more developer tips, tricks, and tutorials. Let's connect and build something great together!