Skip to main content

qa-test-run — Reference Material

Extracted reference tables, code templates, and patterns for the qa-test-run skill. This file is loaded by qa-test-run SKILL.md via inline pointers. Do not duplicate content back into SKILL.md.


Multi-Stack Test Commands

Node.js / TypeScript

TierRunnerCommandReporter FlagCoverage Flag
UnitVitestnpx vitest run --workspace=unit--reporter=json--coverage
UnitJestnpx jest --testPathPattern=unit--json --outputFile=results.json--coverage --coverageReporters=json-summary
IntegrationVitestnpx vitest run --workspace=integration--reporter=json--coverage
IntegrationJestnpx jest --testPathPattern=integration--json--coverage
E2EPlaywrightnpx playwright test--reporter=jsonN/A
E2ECypressnpx cypress run--reporter=jsonN/A

Package manager detection:

  • pnpm-lock.yaml → use pnpm exec instead of npx
  • yarn.lock → use yarn instead of npx
  • package-lock.json → use npx (default)

Environment variables:

  • NODE_ENV=test
  • DATABASE_URL from .env.test
  • CI=true for consistent snapshot behavior

PHP

TierRunnerCommandReporter FlagCoverage Flag
UnitPHPUnitvendor/bin/phpunit --testsuite=unit--log-junit=results.xml--coverage-clover=coverage.xml
UnitPestvendor/bin/pest --testsuite=unit--log-junit=results.xml--coverage-clover=coverage.xml
FeaturePHPUnitvendor/bin/phpunit --testsuite=feature--log-junit=results.xml--coverage-clover=coverage.xml
BrowserLaravel Duskphp artisan dusk--log-junit=results.xmlN/A
BrowserCodeceptionvendor/bin/codecept run acceptance--xml=results.xmlN/A

Coverage driver detection:

  • php -m | grep xdebug → Xdebug available
  • php -m | grep pcov → PCOV available (faster, preferred)
  • Set XDEBUG_MODE=coverage if using Xdebug

Go

TierCommandReporter FlagCoverage Flag
Unitgo test ./...-json-cover -coverprofile=coverage.out
Integrationgo test ./... -tags=integration-json-cover -coverprofile=coverage.out
E2Ego test ./... -tags=e2e-jsonN/A

Test timeout: Default 10m for unit, 30m for integration. Set with -timeout flag.


Parallel Execution Strategy

When to Parallelize

  • Unit tests: Almost always safe to parallelize (stateless by design)
  • Integration tests: Safe if each test uses isolated DB transactions or test containers
  • E2E tests: Playwright handles parallelism via separate browser workers with zero shared state

Per-Stack Configuration

Vitest (fastest config for CI):

// vitest.config.ts
export default defineConfig({
test: {
pool: 'threads',
poolOptions: { threads: { maxThreads: 8, minThreads: 4 } },
isolate: false, // Disable for stateless unit tests only
fileParallelism: true,
maxConcurrency: 10, // For .concurrent tests
},
})

Playwright (CI-optimized with sharding):

// playwright.config.ts
export default defineConfig({
fullyParallel: true,
workers: process.env.CI ? 4 : undefined,
maxFailures: process.env.CI ? 10 : undefined,
retries: process.env.CI ? 2 : 0,
use: {
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
})

CI sharding: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}

PHPUnit + ParaTest:

# Install: composer require --dev brianium/paratest
vendor/bin/paratest -p8 --runner WrapperRunner
# Laravel: php artisan test --parallel --processes=4

Go:

func TestAPICreate(t *testing.T) {
t.Parallel() // Mark I/O-bound tests as parallel-safe
}
go test ./... -parallel 128 -p 16 -count=1

Caution: Lightweight CPU-bound unit tests may be slower with t.Parallel() due to goroutine scheduling overhead.

pytest-xdist:

pip install pytest-xdist
pytest -n auto --dist loadscope # Group by module (keeps fixtures together)
pytest -n 8 --dist load # Max throughput

Coverage Tool Performance Comparison

StackProviderOverhead vs BaselineBranch CoverageRecommendation
JS/TSV8 (@vitest/coverage-v8)~10%Block-levelCI default -- no instrumentation needed
JS/TSIstanbul (@vitest/coverage-istanbul)~300%Statement-levelLocal only when V8 accuracy insufficient
PHPPCOV~34% (18.9s vs 14.0s baseline)Line onlyCI default -- 2.8x faster than Xdebug
PHPXdebug 3 (line mode)~280% (53.5s)Line + branchLocal debugging only
PHPXdebug 3 (path mode)~950% (146.8s)Full pathNever in CI
Gogo test -cover (set mode)<1%N/AAlways -- compile-time rewriting
Gogo test -cover (atomic mode)~3-5%N/ARequired for parallel tests
Pythoncoverage.py (line)~200-300%LineDefault
Pythoncoverage.py (branch)~500%BranchOnly when needed

Benchmarks from Sebastian Bergmann (PHP, Dec 2025) and Vitest v3.2.0+ docs.

E2E Authentication Caching (Playwright storageState)

Authenticate once in a setup project, reuse session across all tests:

// auth.setup.ts
import { test as setup } from '@playwright/test';
setup('authenticate', async ({ request }) => {
await request.post('/api/login', {
form: { user: 'testuser', password: 'pass123' },
});
await request.storageState({ path: '.auth/user.json' });
});
// playwright.config.ts projects
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
dependencies: ['setup'],
use: { storageState: '.auth/user.json' },
},
],

Health Check Matrix

Node.js

CheckDetectionAuto-Fix CommandSkip If
node_modules existsls node_modules/npm install / pnpm install / yarnAlready exists
Prisma client generatedls node_modules/.prisma/client/npx prisma generateNo prisma schema
.env.test existsls .env.testCopy .env.example.env.test (ask user for values)Already exists
Vitest config existsls vitest.config.*Report missing (cannot auto-create)Not using Vitest
Playwright installednpx playwright --versionnpx playwright installNot using Playwright
E2E server configCheck webServer in playwright.configReport if missingNot running E2E

PHP

CheckDetectionAuto-Fix CommandSkip If
vendor existsls vendor/composer installAlready exists
.env.testing existsls .env.testingCopy .env.example.env.testingAlready exists
Autoload freshcomposer dump-autoload timestampcomposer dump-autoloadRecent dump
DB migrationsphp artisan migrate:status --env=testingphp artisan migrate --env=testingNo artisan
APP_KEY setgrep APP_KEY .env.testingphp artisan key:generate --env=testingKey exists

Go

CheckDetectionAuto-Fix CommandSkip If
go.sum existsls go.sumgo mod tidyAlready exists
go generate freshCheck generated file timestampsgo generate ./...No generate directives
sqlc generatedls sqlc output dirssqlc generateNo sqlc.yaml
Test build succeedsgo test -run=^$ ./...Report errorsN/A

Error Pattern Detection

Node.js / TypeScript

CategoryRegex PatternExample
Import/ModuleCannot find module '([^']+)'Cannot find module '@/services/user'
Import/ModuleModule not found: Error: Can't resolve '([^']+)'Module not found: Error: Can't resolve 'msw'
ORM/DB client@prisma/client did not initializePrisma client not generated
ORM/DB clientPrismaClientInitializationErrorDatabase connection failed
EnvironmentEnvironment variable ([A-Z_]+) is not setDATABASE_URL not set
Assertion`expect(received).to(EqualBe
Timeout/AsyncExceeded timeout of (\d+) ?msTest timed out
Timeout/Asyncact\(\) warningMissing act() wrapper
Database/Staterelation "([^"]+)" does not existTable not created
Mock/FixtureNo request handler found forMSW handler missing
Mock/FixtureSnapshot .+ mismatchedStale snapshot

PHP

CategoryRegex PatternExample
Import/ModuleClass '([^']+)' not foundClass 'App\Services\User' not found
ORM/DB clientSQLSTATE\[42S02\]Table doesn't exist
EnvironmentMissing (?:required )?environment variable: ([A-Z_]+)Missing DB credentials
AssertionFailed asserting thatAssertion mismatch
Timeout/AsyncMaximum execution time of (\d+) seconds exceededScript timeout
Database/StateSQLSTATE\[42S01\].*already existsMigration conflict

Go

CategoryRegex PatternExample
Import/Modulecannot find package "([^"]+)"Missing dependency
ORM/DB clientsql: database is closedConnection pool exhausted
Environmentrequired key ([A-Z_]+) missing valueMissing env var
Assertionexpected .+ got .+Assertion mismatch (testify)
Timeout/Asyncpanic: test timed out afterTest timeout
Timeout/Asyncgoroutine .+ \[chan send\]Goroutine leak
Database/Statepq: relation "([^"]+)" does not existMissing migration

Coverage Parsing Rules

Node.js (Istanbul/v8 JSON)

File: coverage/coverage-summary.json

{
"total": {
"lines": { "total": 1000, "covered": 800, "pct": 80 },
"branches": { "total": 200, "covered": 140, "pct": 70 },
"functions": { "total": 100, "covered": 85, "pct": 85 }
},
"path/to/file.ts": { ... }
}

Extract: total.lines.pct, total.branches.pct, per-file coverage for uncovered report.

PHP (Clover XML)

File: coverage.xml or build/logs/clover.xml

<coverage generated="...">
<project>
<metrics statements="1000" coveredstatements="800"
conditionals="200" coveredconditionals="140" />
</project>
</coverage>

Calculate: coveredstatements / statements * 100, coveredconditionals / conditionals * 100.

Go (coverprofile)

File: coverage.out

mode: atomic
package/file.go:10.2,12.5 1 1
package/file.go:14.2,16.5 1 0

Parse with: go tool cover -func=coverage.out for per-function coverage. Total line: total: (statements) 80.0%


Auto-Fix Procedures

Import/Module Resolution

Node.js:

  1. Check if module is a project dependency: grep {module} package.json
  2. If missing: report to user (don't auto-install packages)
  3. If path alias issue: check tsconfig.json paths and fix import

PHP:

  1. Run composer dump-autoload
  2. Check PSR-4 mapping in composer.json
  3. Verify namespace matches directory structure

Go:

  1. Run go mod tidy
  2. Check if import path matches module name in go.mod

ORM/DB Client Generation

Node.js (Prisma):

  1. npx prisma generate
  2. Verify node_modules/.prisma/client/ populated
  3. If schema changed: npx prisma db push --accept-data-loss (test DB only, ask first)

PHP (Eloquent):

  1. php artisan migrate:fresh --env=testing --seed
  2. Verify tables created

Go (sqlc):

  1. sqlc generate
  2. Verify generated files match schema

Environment Configuration

  1. Identify missing variable from error message
  2. Check .env.example for default/placeholder
  3. Use AskUserQuestion: "What value should {VAR_NAME} have in the test environment?"
  4. Write to .env.test / .env.testing

Selective Re-Run Commands

Node.js

RunnerRe-Run Failed OnlyRe-Run Specific FileRe-Run Specific Test
Vitestnpx vitest run {file1} {file2}npx vitest run path/to/test.tsnpx vitest run -t "test name"
Jestnpx jest --onlyFailuresnpx jest path/to/test.tsnpx jest -t "test name"
Playwrightnpx playwright test {file1} {file2}npx playwright test path/to/spec.tsnpx playwright test -g "test name"

PHP

RunnerRe-Run Failed OnlyRe-Run Specific FileRe-Run Specific Test
PHPUnitvendor/bin/phpunit --filter="TestName"vendor/bin/phpunit tests/Unit/UserTest.phpvendor/bin/phpunit --filter="testMethod"
Pestvendor/bin/pest --filter="test name"vendor/bin/pest tests/Unit/UserTest.phpvendor/bin/pest --filter="test name"

Go

Re-Run Failed OnlyRe-Run Specific FileRe-Run Specific Test
go test -json -run "TestName" ./package/...go test -json ./package/...go test -json -run "^TestSpecific$" ./package/...

Changed Code Only (Selective Execution)

Run only tests affected by recent code changes for faster feedback loops:

StackCommandHow It Works
JS/TS (Vitest)npx vitest --changed HEAD~1Uses git diff to find changed source files, runs related tests
JS/TS (Jest)npx jest --changedSince=mainRuns tests related to files changed since branch point
JS/TS (Playwright)npx playwright test --grep @smokeTag-based selection (no automatic changed-file detection)
PHPvendor/bin/phpunit --filter="TestClassName"Manual filter (no native git-diff integration)
Go`go test $(go list ./... | grep -f <(git diff --name-only main | sed 's/[^/]*$
Pythonpytest --lf (last failed) or pytest-testmontestmon tracks code-to-test mapping automatically

Monorepo tools (Nx, Turborepo) provide affected-project detection automatically:

  • Nx: npx nx affected --target=test
  • Turborepo: npx turbo run test --filter=...[HEAD~1]

Key Execution Rules

  1. Always use machine-parseable output -- JSON for Node/Go, XML for PHP. Never parse text output.
  2. Execute tiers sequentially -- unit first (fast feedback), then integration, then E2E.
  3. Stop tier on catastrophic failure -- if >80% of tests in a tier fail, likely a setup issue. Diagnose before continuing.
  4. Never auto-fix assertion failures -- these represent actual bugs. Only auto-fix infrastructure issues.
  5. Ask before modifying env files -- environment values may contain secrets. Always use AskUserQuestion.
  6. Track auto-fix results separately -- report which tests were fixed vs which still fail.
  7. Parse coverage before next tier -- coverage output may be overwritten by subsequent tiers.
  8. Use test DB only -- never run tests against production or staging databases.

Contract Validation Tier

The --contract tier delegates API contract validation to /jaan-to:qa-contract-validate rather than executing contract tools directly.

Rationale

  • qa-test-run does not have Spectral/oasdiff/Prism/Schemathesis in its allowed-tools
  • qa-contract-validate is the sole owner of contract validation logic
  • Delegation prevents ownership duplication and tool drift

Contract discovery

Search order:

  1. specs/openapi.yaml or specs/openapi.json in project root
  2. $JAAN_OUTPUTS_DIR/backend/api-contract/**/openapi.yaml

Output report integration

Contract StatusReport Entry
Contract found, delegation suggested"DELEGATED to qa-contract-validate"
No contract found"SKIPPED (no contract)"
Never"PASS" (contract tier cannot pass within qa-test-run)