Skip to main content
TestDriver integrates seamlessly with all major CI/CD platforms. This guide covers the essential setup for running tests in continuous integration.

Quick Setup

Running TestDriver in CI requires just three things:
1

Install Dependencies

- run: npm install
2

Set API Key

env:
  TD_API_KEY: ${{ secrets.TD_API_KEY }}
3

Run Tests

- run: npx vitest run

Platform-Specific Setup

  • GitHub Actions
  • GitLab CI
  • CircleCI
  • Jenkins
.github/workflows/test.yml
name: E2E Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npx vitest run
        env:
          TD_API_KEY: ${{ secrets.TD_API_KEY }}

      - name: Upload artifacts
        if: failure()
        uses: actions/upload-artifact@v3
        with:
          name: test-artifacts
          path: |
            .testdriver/debug-screenshots/
            .testdriver/dashcam-urls.txt
Complete GitHub Actions guide

Storing API Keys

Store your TestDriver API key securely in CI secrets:

GitHub Actions

  1. Go to repository Settings → Secrets
  2. Click “New repository secret”
  3. Name: TD_API_KEY
  4. Value: Your API key

GitLab CI

  1. Go to Settings → CI/CD → Variables
  2. Click “Add variable”
  3. Key: TD_API_KEY
  4. Value: Your API key
  5. Check “Mask variable”

CircleCI

  1. Project Settings → Environment Variables
  2. Click “Add Environment Variable”
  3. Name: TD_API_KEY
  4. Value: Your API key

Jenkins

  1. Manage Jenkins → Credentials
  2. Add Credentials → Secret text
  3. ID: testdriver-api-key
  4. Secret: Your API key

Parallel Execution

Run tests in parallel for faster CI builds:
  • GitHub Actions Matrix
  • GitLab CI Parallel
  • CircleCI Parallelism
strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: npx vitest run --shard=${{ matrix.shard }}/4
Runs 4 parallel jobs, each handling 1/4 of tests.

Generating Reports

Create test reports for CI dashboards:
  • JUnit XML
  • HTML Report
  • JSON Report
npx vitest run --reporter=junit --outputFile=test-results.xml
- name: Publish Test Results
  uses: EnricoMi/publish-unit-test-result-action@v2
  if: always()
  with:
    files: test-results.xml

Handling Test Failures

Capture debug information when tests fail:
.github/workflows/test.yml
- name: Run tests
  id: tests
  run: npx vitest run
  continue-on-error: true
  env:
    TD_API_KEY: ${{ secrets.TD_API_KEY }}

- name: Upload debug artifacts
  if: steps.tests.outcome == 'failure'
  uses: actions/upload-artifact@v3
  with:
    name: test-failures
    path: |
      .testdriver/debug-screenshots/
      .testdriver/dashcam-urls.txt

- name: Comment on PR with failures
  if: steps.tests.outcome == 'failure' && github.event_name == 'pull_request'
  uses: actions/github-script@v6
  with:
    script: |
      const fs = require('fs');
      const dashcamUrls = fs.readFileSync('.testdriver/dashcam-urls.txt', 'utf8');

      await github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: `## ❌ Tests Failed\n\nView Dashcam replays:\n${dashcamUrls}`
      });

- name: Fail workflow if tests failed
  if: steps.tests.outcome == 'failure'
  run: exit 1

Caching for Faster Builds

Cache node_modules for faster CI runs:
  • GitHub Actions
  • GitLab CI
  • CircleCI
- name: Cache node modules
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-
TestDriver’s selector cache is stored server-side, so you automatically get faster test runs without any CI configuration!

Notifications

Send notifications on test failures:
  • Slack
  • Email
  • Teams
- name: Notify Slack
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "Tests failed on ${{ github.repository }}",
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "❌ Tests failed\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"
            }
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Branch Protection

Require tests to pass before merging:
1

GitHub

  1. Go to Settings → Branches
  2. Add rule for main branch
  3. Check “Require status checks to pass”
  4. Select “test” job
2

GitLab

  1. Settings → Repository → Protected branches
  2. Select main branch
  3. Set “Allowed to merge” to “Developers + Maintainers”
  4. Enable “Pipelines must succeed”

Cost Optimization

Reduce CI costs with TestDriver:
First CI run: Slow (builds cache) Subsequent runs: 1.7x faster (uses cache)No configuration needed - automatic!
# GitHub Actions
- run: npx vitest run --changed HEAD~1

# Only runs tests affected by PR changes
strategy:
  matrix:
    shard: [1, 2, 3, 4]
4x parallel = 4x faster, but same total cost.
on:
  push:
    paths-ignore:
      - '**.md'
      - 'docs/**'

Monitoring CI Performance

Track test performance over time:
- name: Upload timing data
  if: always()
  run: |
    npx vitest run --reporter=json > test-results.json

- name: Analyze performance
  run: |
    # Send to your analytics service
    curl -X POST https://analytics.company.com/test-metrics \
      -H "Content-Type: application/json" \
      -d @test-results.json
View performance trends at console.testdriver.ai.

Troubleshooting CI

Common causes:
  1. Environment differences - Check Node version matches
  2. Missing environment variables - Verify TD_API_KEY is set
  3. Timeout too short - Increase test timeout
  4. Network restrictions - Check firewall allows TestDriver API
Debug:
- run: node --version
- run: npm --version
- run: env | grep TD_
- run: npx vitest run --reporter=verbose
Solutions:
  1. Increase timeout:
    vitest.config.mjs
    export default defineConfig({
      test: {
        testTimeout: 180000, // 3 minutes in CI
      },
    });
    
  2. Add retries:
    vitest.config.mjs
    export default defineConfig({
      test: {
        retry: 2, // Retry failed tests twice
      },
    });
    
  3. Check Dashcam replays for both passing and failing runs
If running many tests concurrently:
vitest.config.mjs
export default defineConfig({
  test: {
    maxConcurrency: 5, // Limit concurrent tests
  },
});
Contact sales for higher rate limits.

Next Steps