Repository navigation
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.
Test command: mkdir -p test-results && pytest -q tests --junitxml=test-results/pytest.xml
.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".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/]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
}
}
}.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:
- pytestTest command: mkdir -p test-results && npx jest --ci --json --outputFile=test-results/jest.json
.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".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/]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
}
}
}.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:
- jestTest command: mkdir -p test-results && npx vitest run --reporter=default --reporter=json --outputFile.json=test-results/vitest.json
.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".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/]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
}
}
}.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:
- vitestTest command: mkdir -p test-results && PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/playwright.json npx playwright test --reporter=list,json
.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".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/]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
}
}
}.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:
- playwrightTest command: mkdir -p test-results && go test -json ./... > test-results/go-test.json
.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".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/]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
}
}
}.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:
- goTest command: dotnet test --logger trx --results-directory test-results/dotnet
.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".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/]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
}
}
}.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:
- dotnetTest command: mvn -B test
.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".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/]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
}
}
}.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:
- mavenTest command: ./gradlew test
.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".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/]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
}
}
}.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:
- gradleTest command: mkdir -p test-results && bundle exec rspec --format progress --format json --out test-results/rspec.json
.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".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/]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
}
}
}.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:
- rspecTest command: mkdir -p test-results && vendor/bin/phpunit --log-junit test-results/phpunit.xml
.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".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/]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
}
}
}.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:
- phpunitGenerated from docs/Processes & Guides/Setup Snippets.md. Edit it there; changes made in the wiki are overwritten.
Architecture
CLI Commands
Processes & Guides
- CI-CD Pipeline Setup
- E2E Harness Operations Guide
- GitLab Pages Demo
- Publishing Docker Images
- Publishing to Artifactory
- Publishing to PyPI
- Setup Snippets
- Shared Resource Pools
- Team Server
Prompts & Snippets
Roadmap & Strategy
- Feature Gaps and Quick Wins - 2026-10-31
- New User Journey Audit - 2026-11-01
- Paid Features to Offer Free - 2026-10-31
- Product Roadmap
Specs & ADRs
- Affected Test Selection - 2026-10-30
- Alerts Where Developers Look - 2026-10-22
- Architecture Consolidation - 2026-10-06
- Architecture Review - 2026-10-31
- BehaveX Reports - 2026-10-21
- Better Flaky Signal - 2026-11-01
- Command Adapter and JUnit Import - 2026-09-25
- Config JSON Schema - 2026-10-22
- Crash Detection - 2026-10-31
- Delta Comparison Policy
- Docs Site - 2026-10-19
- Docs Vault and Wiki Sync - 2026-10-07
- Easy Setup - 2026-11-01
- Engine Fixes - 2026-11-01
- Engineering Health Review - 2026-10-31
- Exporting Results - 2026-11-01
- Flaky Test Issues - 2026-11-01
- Flaky Test Quarantine - 2026-10-22
- Free Copies of Paid Features - 2026-11-01
- GitHub Action PR Comment - 2026-10-19
- Human-Run Resource Provider - 2026-10-30
- Importer and Integration Bug Hunt - 2026-10-31
- Ingest and Team Server - 2026-10-22
- Interview Readiness Fixes - 2026-10-07
- Library Packaging
- Lifecycle Fixes - 2026-11-02
- MCP Server - 2026-11-01
- New User Journey Automation - 2026-11-01
- Open Source Features - 2026-10-19
- OpenTelemetry Export - 2026-10-30
- Phase 3 Delta Comparison Engine Plan
- Phase 3 Unified Dashboard Plan
- Phase 4 BYOK and Failure Analysis
- Phase 5 UI Redesign - Cycles-First Navigation
- Playwright Adapter - 2026-10-19
- Playwright JSON Import - 2026-10-22
- Plugin API - 2026-10-19
- Product Roadmap Work - 2026-10-25
- Product to Ten - 2026-10-25
- Project Health - 2026-10-26
- QASight Logo - 2026-11-05
- Qualflare Follow-ups - 2026-10-26
- Quarantine From the UI - 2026-11-01
- Specs & ADRs
- Rename to QASight - 2026-11-04
- Repository Pattern - Database-Agnostic Refactor
- Resource Lifecycle Hooks - 2026-10-26
- Resource Pools and Leases - 2026-10-26
- Run Deletion and Stop - 2026-11-02
- Runner Coverage - 2026-10-26
- Scale Runs and Stages - 2026-10-24
- Security and Install Review - 2026-10-31
- Switchable Team Features - 2026-10-24
- Test Delivery Metrics - 2026-11-02
- Test Labels, Environments and Releases - 2026-11-02
- Test Source in AI Summaries - 2026-11-01
- Throwaway Stage Containers - 2026-10-24
- Tidy Cards and Demo Examples - 2026-11-05
- UI Design Review - 2026-10-31
- UI Polish - 2026-11-08
- UI Restyle - 2026-10-19
- UI Review Fixes - 2026-11-01
Testing Workflows
Vault