Skip to main content
The vtz runtime includes a built-in test runner powered by V8. No extra packages to install, no configuration required.
@vertz/test is a synthetic module provided automatically by the vtz runtime — like node:fs in Node.js. You do not need to run vtz add @vertz/test.

Quick start

Create a test file:
Run it:
That’s it. The runner discovers **/*.test.ts and **/*.test.tsx files automatically.

Writing tests

Structure

Use describe to group tests and it (or test) to define individual test cases:

Hooks

  • beforeEach(fn) — runs before each test in the current describe block
  • afterEach(fn) — runs after each test
  • beforeAll(fn) — runs once before all tests in the block
  • afterAll(fn) — runs once after all tests in the block
Hooks can be async. They compose hierarchically — parent beforeEach runs before child beforeEach.

Modifiers

Conditional skip

Parameterized tests

Assertions

The expect API is compatible with Vitest. Here are the most common matchers:

Asymmetric matchers

Use inside toEqual, toHaveBeenCalledWith, and other deep-equality matchers:
Available: expect.any(constructor), expect.anything(), expect.objectContaining(), expect.arrayContaining(), expect.stringContaining(), expect.stringMatching().

Mocking

Mock functions

Configure return values:
Available methods: mockReturnValue, mockReturnValueOnce, mockResolvedValue, mockResolvedValueOnce, mockRejectedValue, mockRejectedValueOnce, mockImplementation, mockImplementationOnce. Inspect calls via fn.mock.calls, fn.mock.results, and fn.mock.lastCall. Clean up with mockClear() (reset call history), mockReset() (clear + reset implementation), or mockRestore() (restore original for spies).

Spying on methods

vi namespace

For Vitest compatibility, the vi object provides the same utilities:

Fake timers

Available timer methods: useFakeTimers, useRealTimers, advanceTimersByTime, advanceTimersToNextTimer, runAllTimers, runOnlyPendingTimers, setSystemTime, getTimerCount, isFakeTimers.

Configuration

Configure the test runner in vertz.config.ts:
All fields are optional. Without a config file, vtz test uses sensible defaults.

CLI reference

OptionDescription
[PATH...]Specific files or directories to test (default: project root)
--filter <str>Filter tests by name substring
--watchRe-run tests when files change
--coverageCollect V8 code coverage (outputs coverage.lcov)
--coverage-threshold <n>Minimum coverage percentage as integer (default: 95)
--timeout <ms>Per-test timeout in milliseconds (default: 5000)
--concurrency <n>Max parallel test files (default: CPU count)
--reporter <fmt>Output format: terminal, json, or junit
--bailStop after the first failure
--no-preloadSkip preload scripts from config
--no-cacheSkip compilation cache
--root-dir <path>Workspace root for module resolution

Examples

Coming from Vitest or Jest

The @vertz/test API is intentionally compatible with Vitest. Your test logic stays the same — only the import path and runner change.
VitestVertz
Importimport { describe, it, expect } from 'vitest'import { describe, it, expect } from '@vertz/test'
Configvitest.config.tsvertz.config.ts
Runnpx vitestvtz test
Installnpm add -D vitestNothing — built into the runtime

Key differences

  • No package to install. @vertz/test is provided by the vtz runtime automatically.
  • Runs in V8, not Node.js. The test runner uses the same V8 engine as vtz dev.
  • Snapshot testing (toMatchSnapshot, toMatchInlineSnapshot) is not currently supported.

Migrating from bun:test

The vtz migrate-tests command rewrites imports from bun:test to @vertz/test and adjusts API differences:

Troubleshooting

“Cannot find module ‘@vertz/test’” — You’re running tests with a different runner (Node, Bun, Vitest). Use vtz test instead — @vertz/test is only available inside the vtz runtime. Coverage outputvtz test --coverage generates a coverage.lcov file in the project root. Use any LCOV-compatible viewer to inspect results.

Next steps

Server Testing

Type-safe test client for entity CRUD, service actions, and raw HTTP.

E2E Testing

Browser-based tests with Playwright and authenticated users.