Running Tests
All Tests
Workspace-Specific Tests
End-to-End Tests
.env.localwith real credentials- PostgreSQL database accessible
- Supabase storage configured
BDD Tests (Playwright)
Performance Tests
- Real PostgreSQL 17 database
- Supabase local or production instance
- No cached builds (tests measure cold performance)
- API route latency (p95 budgets)
- Web route TTFB and FCP
- Security scan throughput
- Database query performance
Test Structure
TypeScript Tests (Vitest)
Tank uses Vitest for all TypeScript testing. Location pattern:__tests__/*.test.ts colocated with source code
Examples:
apps/cli/src/__tests__/install.test.ts— CLI install command testsapps/web/lib/__tests__/audit-score.test.ts— Audit scoring logic testspackages/shared/src/__tests__/permissions.test.ts— Permission schema tests
- CLI: 50+ tests (commands, packer, lockfile, linker)
- Web: 30+ tests (API routes, auth, DB, audit scoring)
- Shared: 10+ tests (schemas, resolver, validation)
- E2E: 5 test suites (producer, consumer, admin, integration, on-prem)
- Performance: 2 test suites (API routes, web routes)
Python Tests (pytest)
Tank uses pytest for Python testing. Location pattern:test_*.py files in test directories
Examples:
python-api/api/analyze/tests/test_analyze.py— Security scan endpoint testspython-api/lib/scan/test_snyk_scanner.py— Snyk integration testspython-api/tests/test_skills/test_skill_corpus.py— Skill corpus validation tests
Writing Tests
TypeScript Tests
Python Tests
Test Guidelines
General Principles
Test-Driven Development (TDD)
Test-Driven Development (TDD)
Follow the RED → GREEN → REFACTOR cycle:
- RED — Write a failing test first
- GREEN — Write minimal code to make it pass
- REFACTOR — Clean up the code while keeping tests green
Arrange, Act, Assert Pattern
Arrange, Act, Assert Pattern
Structure tests in three clear phases:
Descriptive Test Names
Descriptive Test Names
Use clear, readable test names that describe what’s being tested:Good:
should reject skill if permissions exceed budgetshould return 404 when skill not foundshould generate lockfile with SHA-512 hashes
test1it workstestInstall
Independent Tests
Independent Tests
Each test should be independent and not rely on other tests:
- Use
beforeEachfor setup instead of running tests in order - Clean up after tests with
afterEach - Don’t share mutable state between tests
One Assertion Per Test (when possible)
One Assertion Per Test (when possible)
Focus each test on one behavior:
Mocking
Vitest mocking:Testing API Routes
Next.js Route Handlers:Testing CLI Commands
Spawning real CLI:Testing Database Queries
Drizzle ORM tests:Performance Testing
Running Performance Tests
Performance Budgets
API routes (p95 latency):/api/v1/skills(search) — < 100ms/api/v1/skills/[name](metadata) — < 50ms/api/v1/skills/[name]/[version]— < 50ms
- Homepage — < 200ms
- Skill detail page — < 300ms
- CI fails if p95 exceeds budget
- Merge blocked until performance fixed
Coverage
Tank doesn’t enforce code coverage metrics, but aims for:- Critical paths — 100% coverage (auth, permissions, security)
- Business logic — High coverage (audit scoring, publish pipeline)
- Utilities — Moderate coverage (helpers, formatters)
CI Testing
GitHub Actions workflow:- Test job — Runs all unit and integration tests with fake credentials
- Performance job — Runs performance tests with real PostgreSQL 17 + Supabase local
- On every push to a branch
- On every pull request
- Before merge to
main
- PR checks fail
- Merge is blocked
- Review requires fixes
Debugging Tests
Vitest Debugging
pytest Debugging
Common Testing Patterns
Testing Error Cases
Testing Async Code
Testing Timeouts
Snapshot Testing
Next Steps
Setup
Set up your local development environment
Contributing
Learn how to contribute to Tank
Architecture
Understand the system design