mirror of
https://github.com/nix-community/home-manager.git
synced 2025-11-08 19:46:05 +01:00
Most of it was focused around running the tests instead of how to create/modify them. Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
233 lines
6.2 KiB
Markdown
233 lines
6.2 KiB
Markdown
# Tests {#sec-tests}
|
|
|
|
Home Manager includes a basic test suite and it is highly recommended to
|
|
include at least one test when adding a module. Tests are typically in
|
|
the form of \"golden tests\" where, for example, a generated
|
|
configuration file is compared to a known correct file.
|
|
|
|
It is relatively easy to create tests by modeling the existing tests,
|
|
found in the `tests` project directory.
|
|
|
|
## Writing Basic Tests {#sec-tests-basic}
|
|
|
|
Home Manager tests use the **NMT** framework, which provides
|
|
a set of assertion functions to verify that modules generate the expected files
|
|
and configurations. Tests are written as Nix expressions that define both the
|
|
Home Manager configuration and the test assertions.
|
|
|
|
### Test Structure {#sec-tests-structure}
|
|
|
|
A basic test file structure looks like:
|
|
|
|
```nix
|
|
{
|
|
# Home Manager configuration
|
|
programs.myprogram = {
|
|
enable = true;
|
|
settings = {
|
|
option = "value";
|
|
};
|
|
};
|
|
|
|
# NMT test script with assertions
|
|
nmt.script = ''
|
|
assertFileExists "home-files/.config/myprogram/config.toml"
|
|
assertFileContent "home-files/.config/myprogram/config.toml" ${./expected-config.toml}
|
|
'';
|
|
}
|
|
```
|
|
|
|
### Test Organization {#sec-tests-organization}
|
|
|
|
Tests are organized in the `tests` directory structure:
|
|
|
|
- `tests/modules/programs/myprogram/default.nix` - Lists all test cases for the module
|
|
- `tests/modules/programs/myprogram/basic-configuration.nix` - A basic test case
|
|
- `tests/modules/programs/myprogram/expected-config.toml` - Expected output file
|
|
|
|
The `default.nix` file should list all test cases:
|
|
|
|
```nix
|
|
{
|
|
myprogram-basic-configuration = ./basic-configuration.nix;
|
|
myprogram-empty-settings = ./empty-settings.nix;
|
|
}
|
|
```
|
|
|
|
### Common NMT Assertions {#sec-tests-assertions}
|
|
|
|
NMT provides several assertion functions:
|
|
|
|
- `assertFileExists "path"` - Verify a file was created
|
|
- `assertPathNotExists "path"` - Verify a file was NOT created
|
|
- `assertFileContent "path" expected-file` - Compare file contents
|
|
- `assertFileRegex "path" "regex"` - Check file matches regex
|
|
|
|
For a full reference to the functions available in test scripts, you can look at NMT's
|
|
[bash-lib](https://git.sr.ht/~rycee/nmt/tree/master/item/bash-lib).
|
|
|
|
### Practical Examples {#sec-tests-examples}
|
|
|
|
Here are some real-world examples of common test patterns:
|
|
|
|
**Testing that a configuration file is generated:**
|
|
```nix
|
|
{
|
|
programs.alacritty = {
|
|
enable = true;
|
|
settings.font.size = 12;
|
|
};
|
|
|
|
nmt.script = ''
|
|
assertFileExists "home-files/.config/alacritty/alacritty.yml"
|
|
assertFileContains "home-files/.config/alacritty/alacritty.yml" "size: 12"
|
|
'';
|
|
}
|
|
```
|
|
|
|
**Testing that no files are created when disabled:**
|
|
```nix
|
|
{
|
|
programs.alacritty.enable = false;
|
|
|
|
nmt.script = ''
|
|
assertPathNotExists "home-files/.config/alacritty"
|
|
'';
|
|
}
|
|
```
|
|
|
|
**Testing exact file content against expected output:**
|
|
```nix
|
|
{
|
|
programs.fastfetch = {
|
|
enable = true;
|
|
settings.display.color = "blue";
|
|
};
|
|
|
|
nmt.script =
|
|
let
|
|
configFile = "home-files/.config/fastfetch/config.jsonc";
|
|
in
|
|
''
|
|
assertFileExists "${configFile}"
|
|
assertFileContent "${configFile}" ${./expected-config.jsonc}
|
|
'';
|
|
}
|
|
```
|
|
|
|
**Testing multiple conditions in one test:**
|
|
```nix
|
|
{
|
|
programs.myprogram = {
|
|
enable = true;
|
|
configFile = "custom.conf";
|
|
extraConfig = "debug = true";
|
|
};
|
|
|
|
nmt.script = ''
|
|
assertFileExists "home-files/.config/myprogram/custom.conf"
|
|
assertFileRegex "home-files/.config/myprogram/custom.conf" "debug = true"
|
|
assertFileRegex "home-files/.config/myprogram/custom.conf" "^# Generated by Home Manager"
|
|
'';
|
|
}
|
|
```
|
|
|
|
### Platform-Specific Tests {#sec-tests-platform-specific}
|
|
|
|
When a module is platform-specific (Linux-only or Darwin-only), the test's `default.nix`
|
|
file should use `lib.optionalAttrs` to conditionally expose tests based on the platform.
|
|
This prevents evaluation errors on unsupported platforms during the test suite runs.
|
|
|
|
**Linux-only module tests:**
|
|
```nix
|
|
{ lib, pkgs, ... }:
|
|
|
|
lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
|
|
rofi-valid-config = ./valid-config.nix;
|
|
rofi-custom-theme = ./custom-theme.nix;
|
|
}
|
|
```
|
|
|
|
**Darwin-only module tests:**
|
|
```nix
|
|
{ lib, pkgs, ... }:
|
|
|
|
lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
|
|
sketchybar-basic = ./basic-configuration.nix;
|
|
sketchybar-lua-config = ./lua-config.nix;
|
|
}
|
|
```
|
|
|
|
For cross-platform modules that have packages which need to be stubbed on Darwin,
|
|
add the package names to `tests/darwinScrublist.nix` to prevent build failures
|
|
during cross-platform test runs.
|
|
|
|
## Using the tests command {#sec-tests-command}
|
|
|
|
Home Manager provides a convenient `tests` command for discovering and running tests:
|
|
|
|
``` shell
|
|
# List all available tests
|
|
$ nix run .#tests -- -l
|
|
|
|
# List tests matching a pattern
|
|
$ nix run .#tests -- -l alacritty
|
|
|
|
# Run all tests matching a pattern
|
|
$ nix run .#tests -- alacritty
|
|
|
|
# Run a specific test
|
|
$ nix run .#tests -- test-alacritty-empty-settings
|
|
|
|
# Run integration tests
|
|
$ nix run .#tests -- -t -l
|
|
|
|
# Interactive test selection (requires fzf)
|
|
$ python3 tests/tests.py -i
|
|
|
|
# Pass additional nix build flags
|
|
$ nix run .#tests -- alacritty -- --verbose
|
|
```
|
|
|
|
## Manual test commands {#sec-tests-manual}
|
|
|
|
For advanced usage or CI environments, you can also run tests manually using nix build commands.
|
|
|
|
The full Home Manager test suite can be run by executing
|
|
|
|
``` shell
|
|
$ nix-build --pure --option allow-import-from-derivation false tests -A build.all
|
|
```
|
|
|
|
in the project root. List all test cases through
|
|
|
|
``` shell
|
|
$ nix-build --pure tests --option allow-import-from-derivation false -A list
|
|
```
|
|
|
|
and run an individual test, for example `alacritty-empty-settings`,
|
|
through
|
|
|
|
``` shell
|
|
$ nix-build --pure tests --option allow-import-from-derivation false -A build.alacritty-empty-settings
|
|
```
|
|
|
|
However, those invocations will impurely source the system's Nixpkgs,
|
|
and may cause failures. To run against the Nixpkgs from the `flake.lock` file,
|
|
use instead e.g.
|
|
|
|
``` shell
|
|
$ nix build --reference-lock-file flake.lock --option allow-import-from-derivation false ./tests#test-all
|
|
```
|
|
|
|
or
|
|
|
|
``` shell
|
|
$ nix build --reference-lock-file flake.lock --option allow-import-from-derivation false ./tests#test-alacritty-empty-settings
|
|
```
|
|
|
|
Some tests may be marked with `enableLegacyIfd`, those may be run by run with e.g.
|
|
|
|
``` shell
|
|
$ nix-build --pure tests --arg enableLegacyIfd true -A build.mytest
|
|
```
|