Docs

Testing

@alienplatform/testing deploys your stack from inside a test suite, so a test can hit its endpoints, send it commands, and tear it down. It runs a real local deployment, built the same way as production.

npm install --save-dev @alienplatform/testing vitest

The package runs the alien CLI, so install it first (see Quickstart). Set ALIEN_CLI_PATH to use a specific binary.

Write a test

This test deploys the running example, asks the api Worker for an upload URL, and calls the search command:

tests/stack.test.ts
import { type Deployment, deploy } from "@alienplatform/testing"
import { afterAll, beforeAll, describe, expect, it } from "vitest"

describe("acme-docs", () => {
  let deployment: Deployment

  beforeAll(async () => {
    deployment = await deploy({
      app: ".",
      environmentVariables: [{ name: "ACME_API_URL", value: "http://localhost:3000" }],
    })
  }, 300_000)

  afterAll(async () => {
    await deployment?.destroy()
  })

Each test reaches the deployment the way your backend would:

tests/stack.test.ts
  it("returns an upload URL and answers searches", async () => {
    const res = await fetch(`${deployment.url}/uploads`, {
      method: "POST",
      body: JSON.stringify({ name: "msa.pdf" }),
    })
    expect(res.ok).toBe(true)

    const { results } = await deployment.invokeCommand<{ results: string[] }>(
      "search",
      { prefix: "inbox/", limit: 10 },
      { target: "processor" },
    )
    expect(Array.isArray(results)).toBe(true)
  })
})

Run it with npx vitest run. The first build can take minutes, so give beforeAll a generous timeout.

What deploy does

deploy({ app }) runs alien dev on a free port with a status file, waits until the deployment is ready, and returns a Deployment:

MemberUse
urlThe public endpoint URL, or undefined when no resource exposes one
invokeCommand(name, params, { target })Sends a command. target picks the resource when several have commands enabled
setExternalSecret(vault, key, value)Writes a value into a vault, as an admin would in their secret store
destroy()Stops the session

deploy() deletes the app's .alien/ folder before it starts, so every run begins from empty resources. Don't point it at a folder where you keep a local session you care about.

Options:

  • config picks another stack file.
  • environmentVariables passes plain or secret variables, with optional targetResources.
  • verbose prints the CLI output.

Test cloud behavior

Local resources behave like their cloud counterparts for your code, but not for cloud-specific limits and IAM. To check those, pass platform: "aws", "gcp", or "azure".

The package then builds the stack, creates a release, and deploys it through the Alien API, which needs ALIEN_API_KEY in the environment. Run these tests less often than local ones; they create real resources.

In CI

Local tests need no cloud credentials. A GitHub Actions job installs Bun and the CLI, then runs the suite:

.github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: curl -fsSL https://alien.dev/install | INSTALL_DIR="$HOME/.local/bin" sh
      - run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
      - run: npm ci
      - run: npx vitest run

Next

On this page