Skip to main content
testdino caches test metadata, retrieves failed tests, and uploads reports with all their attachments.

Prerequisites

  • testdino PyPI package version 1.0.22+
  • Python >= 3.9
  • pytest with Playwright, typically via pytest-playwright
  • Install package pytest-playwright-json
  • TestDino API token
  • Git initialized repository (required for commit and branch metadata)

Quick Start Steps

The upload flow requires a JSON report. Generate it during the pytest run.
1

Install the required packages

pip install pytest-playwright-json pytest-html testdino
2

Run tests and write JSON and HTML reports

pytest \
  --playwright-json=test-results/report.json \
  --html=test-results/index.html \
  --self-contained-html
3

Upload the report directory

testdino upload ./test-results --token="your-token"
4

Cache metadata for failed test reruns

testdino cache --working-dir test-results --token="your-token"

Common Workflows

pytest --playwright-json=test-results/report.json
testdino cache --working-dir test-results --token="your-token"
Print failed tests:
testdino last-failed --token="your-token"
Run only failed tests:
pytest $(testdino last-failed --token="your-token")
Upload the report directory:
testdino upload ./test-results --token="your-token"
Upload all supported attachments:
testdino upload ./test-results --token="your-token" --upload-full-json
pytest \
  --playwright-json=test-results/report.json \
  --html=test-results/index.html \
  --self-contained-html
Cache test metadata:
testdino cache --working-dir test-results --token="$TESTDINO_TOKEN"
Rerun failed tests if the first run had failures:
if [ $? -ne 0 ]; then
  FAILED=$(testdino last-failed --token="$TESTDINO_TOKEN")
  [ -n "$FAILED" ] && pytest $FAILED
fi

Commands

1. cache

Store test execution metadata after Playwright runs. This data powers the last-failed command and feeds into TestDino analytics. Usage Basic usage:
testdino cache --token="your-token"
With a custom working directory:
testdino cache --working-dir ./test-results --token="your-token"
With verbose logging:
testdino cache --verbose --token="your-token"
Options
OptionDescriptionDefault
--working-dir <path>Directory to scan for test resultsCurrent directory
--cache-id <value>Custom cache ID overrideAuto detected
-t, --token <value>TestDino API tokenRequired
-v, --verboseEnable verbose loggingfalse

2. last-failed

Retrieve cached test failures for intelligent reruns. Outputs test identifiers that pass directly to pytest. Usage Basic usage:
testdino last-failed --token="your-token"
Run only failed tests:
pytest $(testdino last-failed --token="your-token")
Get failed tests for specific shard:
testdino last-failed --shard="2/5" --token="your-token"
With custom branch and commit:
testdino last-failed --branch="main" --commit="abc123" --token="your-token"
Options
OptionDescriptionDefault
--cache-id <value>Custom cache ID overrideAuto detected
--branch <value>Custom branch name overrideAuto detected
--commit <value>Custom commit hash overrideAuto detected
--shard <value>Shard specification (e.g., “2/5” for shard 2 of 5)None
--environment <value>Environment name for filtering testsNone
-t, --token <value>TestDino API tokenRequired
-v, --verboseEnable verbose loggingfalse

3. upload <report-directory>

Upload Playwright test reports with attachments to TestDino.
The testdino upload command requires a JSON report to function.
You must:
  • Install required plugins:
    pip install pytest-playwright-json pytest-html
    
  • Run your tests with the --playwright-json flag:
    pytest --playwright-json=test-results/report.json
    
  • Optionally generate HTML reports:
    pytest --html=test-results/index.html --self-contained-html
    
Usage Basic upload:
testdino upload ./test-results --token="your-token"
Upload with environment tag:
testdino upload ./test-results --environment="staging" --token="your-token"
Upload with specific attachments:
testdino upload ./test-results --token="your-token" --upload-images --upload-videos
Upload all attachments:
testdino upload ./test-results --token="your-token" --upload-full-json
Options
OptionDescription
<report-directory>Directory containing Playwright reports (required)
-t, --token <value>TestDino API token (required)
--environment <value>Environment name (e.g., “staging”, “production”)
--upload-imagesUpload image attachments
--upload-videosUpload video attachments
--upload-htmlUpload HTML reports
--upload-tracesUpload trace files
--upload-filesUpload file attachments (.md, .pdf, .txt, .log)
--upload-full-jsonUpload all attachments
-v, --verboseEnable verbose logging

Environment Variables

Set your token as an environment variable instead of passing it with each command:
export TESTDINO_TOKEN="your-api-token"
Set a custom API endpoint:
export TESTDINO_API_URL="https://api.testdino.com"
Set a default environment tag:
export TESTDINO_TARGET_ENV="staging"

CI/CD Integration

.github/workflows/test.yml
name: Playwright Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4]
        shardTotal: [4]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          pip install pytest pytest-playwright pytest-playwright-json pytest-html testdino
          playwright install chromium --with-deps

      - name: Run Playwright Tests
        shell: bash
        env:
          TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
          TESTDINO_API_URL: ${{ env.TESTDINO_API_URL }}
          SHARD_INDEX: ${{ matrix.shardIndex }}
          SHARD_TOTAL: ${{ matrix.shardTotal }}
        run: |
          mkdir -p test-results
          echo "GitHub run attempt: ${{ github.run_attempt }}"
          # Case 1: Re-run failed jobs → run only failed tests
          if [[ "${{ github.run_attempt }}" -gt 1 ]]; then
            echo "Detected re-run. Executing only last failed tests via TestDino."
            
            testdino last-failed --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --token="$TESTDINO_TOKEN" > last-failed-flags.txt
            FAILED_TESTS="$(cat last-failed-flags.txt | tail -1)"
            
            if [[ -z "$FAILED_TESTS" ]]; then
              echo "No failed tests found. Exiting."
              exit 0
            fi
            
            echo "Running failed tests without sharding:"
            echo "$FAILED_TESTS"
            
            # IMPORTANT: Use eval to preserve quotes in the -k expression
            # This matches the JavaScript workflow pattern and ensures quotes are preserved
            eval "pytest $FAILED_TESTS --playwright-json=test-results/report.json --html=test-results/index.html --self-contained-html -p no:selenium -v" || true
            exit 0
          fi
          
          # Case 2: Normal execution (first run)
          echo "Running all Playwright tests"
          pytest \
            --playwright-json=test-results/report.json \
            --html=test-results/index.html \
            --self-contained-html \
            -p no:selenium \
            -v || true

      - name: Cache rerun metadata
        if: always()
        run: testdino cache --working-dir test-results --token="${{ secrets.TESTDINO_TOKEN }}" -v

      - name: Upload test reports
        if: always()
        run: testdino upload ./test-results --token="${{ secrets.TESTDINO_TOKEN }}" --upload-full-json

Authentication

Generate an API token in the TestDino app and store it as a secret.
  • Store the token in CI secrets or environment variables
  • Do not commit tokens to version control
  • Rotate tokens on a regular schedule