Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Writing Tests

Tests are named attributes whose values are callbacks. A callback receives the fixtures it requests and returns an ordered list of actions.

test."saves the document" = { terminal, filesystem }: [
  (filesystem.writeFile "document.txt" "draft\n")
  (terminal.open "${pkgs.lib.getExe pkgs.neovim} ${filesystem.root}/document.txt")
  (expect (terminal.getByText "draft")).toBeVisible
  (terminal.press "<esc>")
];

Actions Run In Order

Each item in the returned list is an action. Setup, interaction, and assertions are written in the same order a user or operator would perform them.

[
  (terminal.open application)
  (terminal.press "<enter>")
  (expect (terminal.getByText "ready")).toBeVisible
]

Fixtures

Fixtures describe the boundary under test. Request only what the test uses:

{ terminal, filesystem }:

Use terminal for local command-line applications and machine or machines for NixOS VMs. Semantic fixtures such as service, filesystem, network, http, and user build on the machine backend. See Fixtures and Assertions.

Locators And Assertions

Locators describe observable state; matchers assert against it:

(expect (terminal.getByText "ready")).toBeVisible
(expect (machine.service "example.service")).toBeActive
(expect (machine.file "/run/example/ready")).toExist

Assertions retry observations until the configured timeout. Actions such as keyboard input, service restarts, and mutating requests execute once.

Steps

test.step groups actions under a diagnostic name in the test log:

(test.step "service becomes usable" [
  (expect (machine.service "example.service")).toBeActive
  ((expect (machine.http.get "http://localhost/health")).toHaveStatus 200)
])

Steps may contain other steps.

Configuration

Set suite-wide defaults with test.configure:

test.configure = {
  timeout = 30;
  terminal = {
    columns = 100;
    rows = 30;
  };
};

The default assertion timeout is 15 seconds. Standalone terminal tests default to 140 columns by 42 rows.

Separate Test Files

Colocate tests with the code they cover using the *.test.nix suffix:

src/
├── terminal.nix
└── terminal.test.nix

A test file is a per-system module:

{ pkgs, expect, ... }:
{
  test."shows a greeting" = { terminal }: [
    (terminal.open pkgs.hello)
    (expect (terminal.getByText "Hello")).toBeVisible
  ];
}

Import it from perSystem:

perSystem = { ... }: {
  imports = [ ./src/terminal.test.nix ];
};