Getting Started
Install
Section titled “Install”npm install --save-dev @averspec/core vitestAver uses Vitest as its test runner.
pip install averspecAver uses pytest as its test runner.
# RubyGems publish coming soon — install from source:git clone https://github.com/averspec/aver-rb.gitcd aver-rb && bundle installAver uses RSpec as its test runner.
go get github.com/averspec/aver-goAver uses Go’s built-in testing package.
# crates.io publish coming soon — install from git:# Cargo.toml: averspec = { git = "https://github.com/averspec/aver-rs" }Aver uses Rust’s built-in test framework.
// Maven Central publish coming soon — build from source:// git clone https://github.com/averspec/aver-jvm.git// ./gradlew publishToMavenLocal// build.gradle.kts:testImplementation("dev.averspec:averspec:0.1.0")Aver uses JUnit 5 as its test runner.
The 30-second version
Section titled “The 30-second version”npx aver initnpx aver runaver initaver runaver initaver run# Define domain, adapter, and test in Go filesgo test ./...# Define domain, adapter, and test in Rust filescargo test./gradlew testThat scaffolds a domain, a unit adapter, and a test — then runs it. You’ll see output like:
✓ create a task in backlog [unit] ✓ move task through workflow [unit]From here, replace the stubs with your real domain. The rest of this page explains the pieces and helps you choose the right starting path.
Where are you starting from?
Section titled “Where are you starting from?”Your entry point depends on what you have today.
I have existing code with no tests
Section titled “I have existing code with no tests”Start by locking in what exists. Install the approvals package and capture current behavior before changing anything:
npm install --save-dev @averspec/approvalsimport { test } from 'vitest'import { approve } from '@averspec/approvals'import { processOrder } from '../src/orders.js'
test('order processing output', async () => { const result = processOrder({ items: [{ sku: 'W-100', qty: 3 }] }) await approve(result)})Run npx aver approve to create baselines, then npx aver run to verify against them. Baselines are stored in __approvals__/ next to your test file — commit them to source control. You now have a safety net.
approve()is also exported ascharacterize()if that reads better for your characterization tests.
From here, extract a domain vocabulary as patterns emerge. The tutorial walks through this process end-to-end with a complete example.
I have existing code with tests I want to restructure
Section titled “I have existing code with tests I want to restructure”If you already have tests but they’re scattered across page objects, test helpers, and ad-hoc abstractions, Aver gives you a spine to consolidate them.
Look at your existing test helpers. They probably already encode domain operations — createUser(), loginAs(), verifyOrderStatus(). Those are your domain vocabulary candidates. Define them as a domain, write adapters that delegate to your existing infrastructure, and your old tests become acceptance tests.
Start with the tutorial to see the pattern, then apply it to your own test helpers.
I’m building something new
Section titled “I’m building something new”Scaffold a project:
npx aver initThis generates:
domains/task-board.ts— starter domain with actions and assertionsadapters/task-board.unit.ts— unit adapter with handler stubstests/task-board.spec.ts— example testaver.config.ts— adapter registration
aver initThis generates:
domains/task_board.py— starter domain with actions and assertionsadapters/task_board_unit.py— unit adapter with handler stubstests/test_task_board.py— example testaver_config.py— adapter registration
aver initThis generates:
domains/task_board.rb— starter domain with actions and assertionsadapters/task_board_unit.rb— unit adapter with handler stubsspec/task_board_spec.rb— example test
// domains/taskboard.go — define domain struct with marker fields// adapters/taskboard_unit.go — implement handlers// taskboard_test.go — write tests// src/domains/task_board.rs — define domain with markers// src/adapters/task_board_unit.rs — implement handlers// tests/task_board.rs — write tests// src/test/kotlin/domains/TaskBoard.kt — define domain// src/test/kotlin/adapters/TaskBoardUnit.kt — implement handlers// src/test/kotlin/tests/TaskBoardTest.kt — write testsRun the tests to verify the scaffold works, then replace the stubs with your real domain.
For greenfield projects, consider starting with an Example Mapping session to discover your domain vocabulary before writing code.
The pieces
Section titled “The pieces”Regardless of starting point, every Aver project has four pieces:
domains/ # What — vocabulary in business languageadapters/ # How — binds vocabulary to implementationstests/ # Verify — scenarios using domain languageaver.config.* # Wiring — registers adaptersDomain — declares actions (do something), queries (read something), and assertions (check something). No implementation details. See API Reference.
Adapter — implements every domain operation for a specific protocol. The unit protocol calls your code’s public interfaces directly. http and playwright are separate packages. The type system enforces that every domain operation has a handler — miss one and you get a compile error.
Tests — import the domain, never the adapter. suite(domain) gives you a typed test function. Tests use given/when/then (or act/query/assert) to compose domain operations into scenarios.
Config — registers adapters. When multiple adapters are registered for the same domain, every test runs against all of them automatically.
Configure your test runner
Section titled “Configure your test runner”Create or update vitest.config.ts to load the Aver config:
import { defineConfig } from 'vitest/config'
export default defineConfig({ test: { setupFiles: ['./aver.config.ts'], },})Aver auto-discovers aver_config.py via pytest plugin. No extra configuration needed.
Require Aver in your spec_helper.rb:
require 'averspec'Import the adapter in your test file:
import _ "yourproject/adapters"Aver auto-discovers adapters via the test harness. No extra configuration needed.
Aver auto-discovers adapters via JUnit 5 service loader. No extra configuration needed.
When to add what
Section titled “When to add what”| When you need… | Add… |
|---|---|
| A safety net for existing code | Approval testing — captures current behavior as a baseline |
| API-level testing | HTTP protocol adapter — runs tests against a real server |
| Browser testing | Playwright protocol adapter — drives real browser UI |
| Telemetry verification | Telemetry declarations on domain markers. See Telemetry Tutorial |
| AI-assisted workflow | Agent plugin (TypeScript only) — workflow skills + scenario pipeline. See AI-Assisted |
| CI integration | No extra packages — aver run in your pipeline. See CI Integration |
You don’t need everything on day one. Start with the core package and a unit adapter. Add protocols as your needs grow.
Next steps
Section titled “Next steps”- Tutorial: Legacy Code — from untested code to multi-adapter tests
- Tutorial: Greenfield — build a domain from scratch
- Tutorial: Telemetry — verify observability contracts alongside behavior
- Multi-Adapter Testing — add HTTP and Playwright adapters
- Architecture — how the three-layer model works and why
- API Reference — domains, adapters, protocols, and suites