> ## Documentation Index
> Fetch the complete documentation index at: https://docs.testdino.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Playwright Azure DevOps Pipeline Setup

> Stream Playwright results from Azure DevOps Pipelines to TestDino live, with sharded jobs grouped into one run.

Set up an Azure DevOps pipeline that streams Playwright test results to TestDino during the run and view aggregated analytics, failure analysis, and flaky test detection on your dashboard.

## Prerequisites

* A <a href="https://app.testdino.com" target="_blank" rel="noopener noreferrer">TestDino account <Icon icon="arrow-up-right-from-square" size={12} /></a> with a project created
* A TestDino API key ([Generate API Keys](/guides/generate-api-keys))
* An Azure DevOps project with pipelines enabled
* A Playwright test project (or clone the <a href="https://github.com/testdino-hq/TestDino-Example" target="_blank" rel="noopener noreferrer">TestDino Example Repository <Icon icon="arrow-up-right-from-square" size={12} /></a> to get started)
* `@testdino/playwright` installed and configured in `playwright.config.ts|js|mjs`:

```bash theme={null}
npm install @testdino/playwright
```

```typescript playwright.config.ts theme={null}
import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    ['@testdino/playwright', {
      token: process.env.TESTDINO_TOKEN,
      serverUrl: "https://reporter.testdino.com",
    }],
  ],
});
```

## Set Up Your API Key

Store your TestDino API key as a secret pipeline variable so it is available to your pipeline without exposing it in logs or config files.

1. Open your Azure DevOps pipeline
2. Click **Edit** on the pipeline
3. Click **Variables**
4. Click **New variable**
5. Set the name to `TESTDINO_TOKEN`
6. Paste your TestDino API key as the value
7. Check **Keep this value secret**
8. Save the pipeline

<Warning>
  **Warning**
  Never commit your API key directly in pipeline files. Always use secret variables. Secret variables are not exposed in pipeline logs.
</Warning>

## Basic Pipeline Config

For a simple setup without sharding, run your tests with `TESTDINO_TOKEN` mapped into the script. Results stream to TestDino during the run, so no separate upload step is needed.

<Accordion title="azure-pipelines.yml: Basic pipeline">
  ```yaml azure-pipelines.yml theme={null}
  trigger:
    branches:
      include:
        - main

  pr:
    branches:
      include:
        - main

  variables:
    CI: "true"

  pool:
    vmImage: ubuntu-latest

  steps:
    - checkout: self

    - task: UseNode@1
      inputs:
        version: "20.x"
      displayName: Install Node.js

    - script: npm ci
      displayName: Install dependencies

    - script: npx playwright install --with-deps
      displayName: Install Playwright browsers

    - script: npx playwright test
      displayName: Run tests with TestDino
      env:
        TESTDINO_TOKEN: $(TESTDINO_TOKEN)
        TESTDINO_SERVER_URL: https://reporter.testdino.com
  ```
</Accordion>

<Tip>
  **Tip**
  The `env` block maps the secret variable to an environment variable `@testdino/playwright` reads. Results stream live even when tests fail, so failures land on the dashboard without a `condition: always()` upload step.
</Tip>

## Sharded Test Runs

For larger test suites, the Azure DevOps matrix strategy splits tests across multiple jobs. Each shard streams its own results, and TestDino groups them into one run when they share a `ci-run-id`.

### How it works

1. Azure DevOps runs Playwright across 4 shards using a matrix strategy
2. Each shard streams its results to TestDino during the run
3. Every shard passes the same `--ci-run-id` so TestDino merges them into a single run
4. No merge or upload stage runs after the shards finish

### Full sharded config

<Accordion title="azure-pipelines.yml: Sharded pipeline">
  ```yaml azure-pipelines.yml theme={null}
  trigger:
    branches:
      include:
        - main

  pr:
    branches:
      include:
        - main

  variables:
    CI: "true"

  pool:
    vmImage: ubuntu-latest

  jobs:
    - job: Playwright
      strategy:
        matrix:
          shard1:
            SHARD: 1/4
          shard2:
            SHARD: 2/4
          shard3:
            SHARD: 3/4
          shard4:
            SHARD: 4/4
      steps:
        - checkout: self

        - task: UseNode@1
          inputs:
            version: "20.x"
          displayName: Install Node.js

        - script: npm ci
          displayName: Install dependencies

        - script: npx playwright install --with-deps
          displayName: Install Playwright browsers

        - script: npx tdpw test --ci-run-id "$(Build.BuildId)" -- --shard=$(SHARD)
          displayName: Run shard $(SHARD) with TestDino
          env:
            TESTDINO_TOKEN: $(TESTDINO_TOKEN)
            TESTDINO_SERVER_URL: https://reporter.testdino.com
  ```
</Accordion>

<Info>
  **Info**
  Every shard passes the same `--ci-run-id "$(Build.BuildId)"`, so TestDino merges them into a single run. The `env` block maps the secret variable into each shard's script.
</Info>

### Key details in the sharded config

| Config Block                     | What It Does                                                                     |
| :------------------------------- | :------------------------------------------------------------------------------- |
| `strategy: matrix`               | Defines 4 shards with `SHARD: 1/4` through `4/4`                                 |
| `--shard=$(SHARD)`               | Passes the shard value directly to Playwright (Azure DevOps uses 1-based values) |
| `--ci-run-id "$(Build.BuildId)"` | Groups all shards into one run on the dashboard                                  |
| `env: TESTDINO_TOKEN`            | Maps the secret variable to an environment variable `@testdino/playwright` reads |

Set the `ciRunId` reporter option in `playwright.config` to `$(Build.BuildId)` if you prefer running `npx playwright test` directly instead of `npx tdpw test`.

### Pipeline execution

After the pipeline runs, Azure DevOps shows all shard jobs in the pipeline view. Each shard streams its results, and TestDino merges them into one run.

<img src="https://tdstorageus.blob.core.windows.net/public/docs/installation-and-setup/ci-setup/playwright-azure-devops-pipeline/azuredevops-testrun-pipeline-execution.webp" alt="Azure DevOps pipeline execution view showing 4 Playwright shard jobs streaming results to TestDino" />

### Results in TestDino

The test run appears in your TestDino dashboard with full failure details, flaky detection, and trend data as tests complete.

<img src="https://tdstorageus.blob.core.windows.net/public/docs/installation-and-setup/ci-setup/playwright-azure-devops-pipeline/azuredevops-uploaded-testdino-testrunscreen.webp" alt="TestDino test run screen showing streamed results from Azure DevOps pipeline with pass/fail counts and failure details" />

## Troubleshooting

<AccordionGroup>
  <Accordion title="Results not appearing on the dashboard" icon="forward">
    * Confirm `@testdino/playwright` is in your `playwright.config` `reporter` array and `TESTDINO_TOKEN` is mapped into the script via the `env` block
    * Results stream during the run, so no separate upload step is required
  </Accordion>

  <Accordion title="Sharded runs show up as separate runs" icon="code-merge">
    * Pass the same `--ci-run-id "$(Build.BuildId)"` (or `ciRunId` reporter option) to every shard
    * Different values create one run per shard
  </Accordion>

  <Accordion title="TESTDINO_TOKEN not available in script" icon="key">
    * Secret variables in Azure DevOps are not automatically available as environment variables. You must map them explicitly using the `env` block in the script step
    * Verify the variable name matches exactly: `TESTDINO_TOKEN: $(TESTDINO_TOKEN)`
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="CI Optimization" icon="gauge-high" href="/guides/playwright-ci-optimization">
    Reduce CI time with smart reruns
  </Card>

  <Card title="Environment Mapping" icon="code-branch" href="/guides/environment-mapping">
    Route test results to Dev, Staging, or Production by branch
  </Card>

  <Card title="Integrations" icon="puzzle-piece" href="/integrations/overview">
    Connect Slack, Jira, Linear, Asana, and more
  </Card>

  <Card title="Azure DevOps Extension" icon="microsoft" href="/integrations/playwright-azure-devops">
    View test runs inside Azure DevOps
  </Card>
</CardGroup>
