Setup Snippets¶
Copy-paste CI setup for each test runner and each CI system. Every snippet runs your tests the way they already run, has the runner write a result file QASight reads, and records it with no qasight.yaml. Replace my-app with your project's name: runs recorded under the same cycle build its history.
Rather not copy anything? In the project folder, pip install qasight && qasight init detects the runners and writes these files for you, plus a qasight.yaml so qasight run works locally too (Command Reference § qasight init). qasight init --ci gitlab --dry-run prints one without writing it.
How each CI keeps the history between runs:
- GitHub Actions: the action caches it (
history: auto) and comments on pull requests. Inputs: CI-CD Pipeline Setup § GitHub Action. - GitLab CI and CircleCI: the snippet caches
.testo-history/per branch, falling back to the default branch's. - Jenkins: the history stays in the agent's workspace. For one history across agents and CI systems, run a team server and replace
qasight ingest ...withqasight ingest --server https://your-server --token "$TESTO_API_TOKEN" ....
Outside GitHub, the snippets install qasight with uv (one binary that brings its own Python, so the image needs only curl). An image that has Python can run pip install qasight instead. Each run's summary is saved as testo-summary.md next to the build.
Python (pytest)¶
Test command: mkdir -p test-results && pytest -q tests --junitxml=test-results/pytest.xml
Python (pytest): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -r requirements.txt
- run: mkdir -p test-results && pytest -q tests --junitxml=test-results/pytest.xml
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
Python (pytest): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
pytest:
stage: test
image: python:3.12
cache:
key: testo-history-pytest-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-pytest-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- pip install -r requirements.txt
- mkdir -p test-results && pytest -q tests --junitxml=test-results/pytest.xml
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
Python (pytest): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('pytest') {
steps {
sh 'pip install -r requirements.txt'
sh 'mkdir -p test-results && pytest -q tests --junitxml=test-results/pytest.xml'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
Python (pytest): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
pytest:
docker:
- image: cimg/python:3.12
steps:
- checkout
- restore_cache:
keys:
- testo-history-pytest-{{ .Branch }}-
- testo-history-pytest-
- run: pip install -r requirements.txt
- run: mkdir -p test-results && pytest -q tests --junitxml=test-results/pytest.xml
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-pytest-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- pytest
JavaScript (Jest)¶
Test command: mkdir -p test-results && npx jest --ci --json --outputFile=test-results/jest.json
JavaScript (Jest): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
- run: npm ci
- run: mkdir -p test-results && npx jest --ci --json --outputFile=test-results/jest.json
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
JavaScript (Jest): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
jest:
stage: test
image: node:22
cache:
key: testo-history-jest-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-jest-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- npm ci
- mkdir -p test-results && npx jest --ci --json --outputFile=test-results/jest.json
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
JavaScript (Jest): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('Jest') {
steps {
sh 'npm ci'
sh 'mkdir -p test-results && npx jest --ci --json --outputFile=test-results/jest.json'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
JavaScript (Jest): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
jest:
docker:
- image: cimg/node:lts
steps:
- checkout
- restore_cache:
keys:
- testo-history-jest-{{ .Branch }}-
- testo-history-jest-
- run: npm ci
- run: mkdir -p test-results && npx jest --ci --json --outputFile=test-results/jest.json
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-jest-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- jest
JavaScript (Vitest)¶
Test command: mkdir -p test-results && npx vitest run --reporter=default --reporter=json --outputFile.json=test-results/vitest.json
JavaScript (Vitest): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
- run: npm ci
- run: mkdir -p test-results && npx vitest run --reporter=default --reporter=json --outputFile.json=test-results/vitest.json
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
JavaScript (Vitest): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
vitest:
stage: test
image: node:22
cache:
key: testo-history-vitest-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-vitest-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- npm ci
- mkdir -p test-results && npx vitest run --reporter=default --reporter=json --outputFile.json=test-results/vitest.json
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
JavaScript (Vitest): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('Vitest') {
steps {
sh 'npm ci'
sh 'mkdir -p test-results && npx vitest run --reporter=default --reporter=json --outputFile.json=test-results/vitest.json'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
JavaScript (Vitest): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
vitest:
docker:
- image: cimg/node:lts
steps:
- checkout
- restore_cache:
keys:
- testo-history-vitest-{{ .Branch }}-
- testo-history-vitest-
- run: npm ci
- run: mkdir -p test-results && npx vitest run --reporter=default --reporter=json --outputFile.json=test-results/vitest.json
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-vitest-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- vitest
Browser tests (Playwright)¶
Test command: mkdir -p test-results && PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=list,json
Browser tests (Playwright): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
- run: npm ci
- run: npx playwright install --with-deps
- run: mkdir -p test-results && PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=list,json
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
Browser tests (Playwright): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
playwright:
stage: test
image: node:22
cache:
key: testo-history-playwright-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-playwright-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- npm ci
- npx playwright install --with-deps
- mkdir -p test-results && PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=list,json
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
Browser tests (Playwright): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('Playwright') {
steps {
sh 'npm ci'
sh 'npx playwright install --with-deps'
sh 'mkdir -p test-results && PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=list,json'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
Browser tests (Playwright): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
playwright:
docker:
- image: cimg/node:lts
steps:
- checkout
- restore_cache:
keys:
- testo-history-playwright-{{ .Branch }}-
- testo-history-playwright-
- run: npm ci
- run: npx playwright install --with-deps
- run: mkdir -p test-results && PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=list,json
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-playwright-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- playwright
Go (go test)¶
Test command: mkdir -p test-results && go test -json ./... > test-results/go-test.json
Go (go test): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: mkdir -p test-results && go test -json ./... > test-results/go-test.json
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
Go (go test): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
go:
stage: test
image: golang:1.23
cache:
key: testo-history-go-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-go-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- mkdir -p test-results && go test -json ./... > test-results/go-test.json
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
Go (go test): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('go test') {
steps {
sh 'mkdir -p test-results && go test -json ./... > test-results/go-test.json'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
Go (go test): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
go:
docker:
- image: cimg/go:1.23
steps:
- checkout
- restore_cache:
keys:
- testo-history-go-{{ .Branch }}-
- testo-history-go-
- run: mkdir -p test-results && go test -json ./... > test-results/go-test.json
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-go-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- go
.NET (dotnet test)¶
Test command: dotnet test --logger trx --results-directory test-results/dotnet
.NET (dotnet test): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
- run: dotnet test --logger trx --results-directory test-results/dotnet
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
.NET (dotnet test): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
dotnet:
stage: test
image: mcr.microsoft.com/dotnet/sdk:8.0
cache:
key: testo-history-dotnet-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-dotnet-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- dotnet test --logger trx --results-directory test-results/dotnet
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
.NET (dotnet test): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('dotnet test') {
steps {
sh 'dotnet test --logger trx --results-directory test-results/dotnet'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
.NET (dotnet test): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
dotnet:
docker:
- image: mcr.microsoft.com/dotnet/sdk:8.0
steps:
- checkout
- restore_cache:
keys:
- testo-history-dotnet-{{ .Branch }}-
- testo-history-dotnet-
- run: dotnet test --logger trx --results-directory test-results/dotnet
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-dotnet-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- dotnet
Java (Maven)¶
Test command: mvn -B test
Java (Maven): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: maven
- run: mvn -B test
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
Java (Maven): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
maven:
stage: test
image: maven:3-eclipse-temurin-21
cache:
key: testo-history-maven-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-maven-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- mvn -B test
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
Java (Maven): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('Maven (Surefire)') {
steps {
sh 'mvn -B test'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
Java (Maven): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
maven:
docker:
- image: cimg/openjdk:21.0
steps:
- checkout
- restore_cache:
keys:
- testo-history-maven-{{ .Branch }}-
- testo-history-maven-
- run: mvn -B test
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-maven-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- maven
Java or Kotlin (Gradle)¶
Test command: ./gradlew test
Java or Kotlin (Gradle): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: gradle
- run: ./gradlew test
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
Java or Kotlin (Gradle): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
gradle:
stage: test
image: gradle:jdk21
cache:
key: testo-history-gradle-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-gradle-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- ./gradlew test
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
Java or Kotlin (Gradle): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('Gradle') {
steps {
sh './gradlew test'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
Java or Kotlin (Gradle): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
gradle:
docker:
- image: cimg/openjdk:21.0
steps:
- checkout
- restore_cache:
keys:
- testo-history-gradle-{{ .Branch }}-
- testo-history-gradle-
- run: ./gradlew test
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-gradle-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- gradle
Ruby (RSpec)¶
Test command: mkdir -p test-results && bundle exec rspec --format progress --format json --out test-results/rspec.json
Ruby (RSpec): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: mkdir -p test-results && bundle exec rspec --format progress --format json --out test-results/rspec.json
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
Ruby (RSpec): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
rspec:
stage: test
image: ruby:3.3
cache:
key: testo-history-rspec-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-rspec-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- bundle install
- mkdir -p test-results && bundle exec rspec --format progress --format json --out test-results/rspec.json
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
Ruby (RSpec): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('RSpec') {
steps {
sh 'bundle install'
sh 'mkdir -p test-results && bundle exec rspec --format progress --format json --out test-results/rspec.json'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
Ruby (RSpec): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
rspec:
docker:
- image: cimg/ruby:3.3
steps:
- checkout
- restore_cache:
keys:
- testo-history-rspec-{{ .Branch }}-
- testo-history-rspec-
- run: bundle install
- run: mkdir -p test-results && bundle exec rspec --format progress --format json --out test-results/rspec.json
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-rspec-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- rspec
PHP (PHPUnit)¶
Test command: mkdir -p test-results && vendor/bin/phpunit --log-junit test-results/phpunit.xml
PHP (PHPUnit): GitHub Actions¶
.github/workflows/tests.yml
name: tests
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
pull-requests: write # the pull request comment
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
- run: composer install --no-interaction --prefer-dist
- run: mkdir -p test-results && vendor/bin/phpunit --log-junit test-results/phpunit.xml
- uses: arieleven/qasight@v1
if: ${{ !cancelled() }} # record red runs too
with:
cycle: "my-app"
PHP (PHPUnit): GitLab CI¶
.gitlab-ci.yml
# QASight: records each run's results and keeps their history in the GitLab cache.
# Docs: https://arieleven.github.io/qasight/docs/
stages: [test]
phpunit:
stage: test
image: composer:2
cache:
key: testo-history-phpunit-$CI_COMMIT_REF_SLUG
fallback_keys: [testo-history-phpunit-$CI_DEFAULT_BRANCH]
paths: [.testo-history/]
when: always
script:
- composer install --no-interaction --prefer-dist
- mkdir -p test-results && vendor/bin/phpunit --log-junit test-results/phpunit.xml
after_script:
- command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
- uv tool install --quiet qasight
- mkdir -p "$CI_PROJECT_DIR/.testo-history"
- export DATABASE_URL="sqlite:///$CI_PROJECT_DIR/.testo-history/testo_history.db"
- qasight ingest --cycle my-app
- qasight report markdown --cycle my-app --out testo-summary.md
artifacts:
when: always
paths: [testo-summary.md, test-results/]
PHP (PHPUnit): Jenkins¶
Jenkinsfile
// QASight: records each build's results. History lives in the workspace
// (.testo-history); for one history across agents, use a team server
// (qasight ingest --server). Docs: https://arieleven.github.io/qasight/docs/
pipeline {
agent any // needs the test tools and curl
stages {
stage('PHPUnit') {
steps {
sh 'composer install --no-interaction --prefer-dist'
sh 'mkdir -p test-results && vendor/bin/phpunit --log-junit test-results/phpunit.xml'
}
}
}
post {
always {
sh '''
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$WORKSPACE/.testo-history"
export DATABASE_URL="sqlite:///$WORKSPACE/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
'''
archiveArtifacts artifacts: 'testo-summary.md', allowEmptyArchive: true
}
}
}
PHP (PHPUnit): CircleCI¶
.circleci/config.yml
# QASight: records each run's results and keeps their history in the CircleCI cache.
# Docs: https://arieleven.github.io/qasight/docs/
version: 2.1
jobs:
phpunit:
docker:
- image: cimg/php:8.3
steps:
- checkout
- restore_cache:
keys:
- testo-history-phpunit-{{ .Branch }}-
- testo-history-phpunit-
- run: composer install --no-interaction --prefer-dist
- run: mkdir -p test-results && vendor/bin/phpunit --log-junit test-results/phpunit.xml
- run:
name: Record the results with QASight
when: always
command: |
command -v uv >/dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install --quiet qasight
mkdir -p "$HOME/.testo-history"
export DATABASE_URL="sqlite:///$HOME/.testo-history/testo_history.db"
qasight ingest --cycle my-app
qasight report markdown --cycle my-app --out testo-summary.md
- save_cache:
when: always
key: testo-history-phpunit-{{ .Branch }}-{{ .BuildNum }}
paths: [~/.testo-history]
- store_artifacts:
path: testo-summary.md
workflows:
tests:
jobs:
- phpunit