Home Explore Blog CI



nixpkgs

1st chunk of `nixos/doc/manual/development/writing-nixos-tests.section.md`
4763b384d494813dea34f7771a3187917cdeab004eeb8dbf0000000100000f3c
# Writing Tests {#sec-writing-nixos-tests}

A NixOS test is a module that has the following structure:

```nix
{

  # One or more machines:
  nodes =
    { machine =
        { config, pkgs, ... }: { /* ... */ };
      machine2 =
        { config, pkgs, ... }: { /* ... */ };
      # …
    };

  testScript =
    ''
      Python code…
    '';
}
```

We refer to the whole test above as a test module, whereas the values
in [`nodes.<name>`](#test-opt-nodes) are NixOS modules themselves.

The option [`testScript`](#test-opt-testScript) is a piece of Python code that executes the
test (described below). During the test, it will start one or more
virtual machines, the configuration of which is described by
the option [`nodes`](#test-opt-nodes).

An example of a single-node test is
[`login.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix).
It only needs a single machine to test whether users can log in
on the virtual console, whether device ownership is correctly maintained
when switching between consoles, and so on. An interesting multi-node test is
[`nfs/simple.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix).
It uses two client nodes to test correct locking across server crashes.

## Calling a test {#sec-calling-nixos-tests}

Tests are invoked differently depending on whether the test is part of NixOS or lives in a different project.

### Testing within NixOS {#sec-call-nixos-test-in-nixos}

Tests that are part of NixOS are added to [`nixos/tests/all-tests.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/all-tests.nix).

```nix
{
  hostname = runTest ./hostname.nix;
}
```

Overrides can be added by defining an anonymous module in `all-tests.nix`.

```nix
{
  hostname = runTest {
    imports = [ ./hostname.nix ];
    defaults.networking.firewall.enable = false;
  };
}
```

You can run a test with attribute name `hostname` in `nixos/tests/all-tests.nix` by invoking:

```shell
cd /my/git/clone/of/nixpkgs
nix-build -A nixosTests.hostname
```

### Testing outside the NixOS project {#sec-call-nixos-test-outside-nixos}

Outside the `nixpkgs` repository, you can use the `runNixOSTest` function from
`pkgs.testers`:

```nix
let pkgs = import <nixpkgs> {};
in

pkgs.testers.runNixOSTest {
  imports = [ ./test.nix ];
  defaults.services.foo.package = mypkg;
}
```

`runNixOSTest` returns a derivation that runs the test.

## Configuring the nodes {#sec-nixos-test-nodes}

There are a few special NixOS options for test VMs:

`virtualisation.memorySize`

:   The memory of the VM in megabytes.

`virtualisation.vlans`

:   The virtual networks to which the VM is connected. See
    [`nat.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nat.nix)
    for an example.

`virtualisation.writableStore`

:   By default, the Nix store in the VM is not writable. If you enable
    this option, a writable union file system is mounted on top of the
    Nix store to make it appear writable. This is necessary for tests
    that run Nix operations that modify the store.

For more options, see the module
[`qemu-vm.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/qemu-vm.nix).

The test script is a sequence of Python statements that perform various
actions, such as starting VMs, executing commands in the VMs, and so on.
Each virtual machine is represented as an object stored in the variable
`name` if this is also the identifier of the machine in the declarative
config. If you specified a node `nodes.machine`, the following example starts the
machine, waits until it has finished booting, then executes a command
and checks that the output is more-or-less correct:

```py
machine.start()
machine.wait_for_unit("default.target")
t.assertIn("Linux", machine.succeed("uname"), "Wrong OS")
```

The first line is technically unnecessary; machines are implicitly started

Title: Writing and Calling NixOS Tests
Summary
This section describes the structure of a NixOS test, which includes a `nodes` section defining the virtual machines and a `testScript` containing Python code to execute the test. It explains how to call tests both within the NixOS project (by adding them to `all-tests.nix`) and outside the project (using `runNixOSTest`). It also covers configuring the virtual machines using special NixOS options like `virtualisation.memorySize`, `virtualisation.vlans`, and `virtualisation.writableStore`. Finally, it briefly introduces the Python test script and how to interact with the virtual machines.