Based on https://nix.dev/tutorials/integration-testing-using-virtual-machines, but with a flake.
BH5XPS7CPEH4MNGTZONRZYABNOUUVYNNQ5YRXMBCHXIXTAAPH3RQC {description = "Example for running a VM network test";inputs.nixpkgs.url = "github:NixOS/nixpkgs";outputs = { self, nixpkgs }:let# Single source of truth for all tutorial constantsdatabase = "postgres";schema = "api";table = "todos";username = "authenticator";groupname = "authenticator";password = "mysecretpassword";webRole = "web_anon";postgrestPort = 3000;# NixOS module shared between server and clientsharedModule = {# Since it's common for CI not to have $DISPLAY available,# we have to explicitly tell the tests "please don't expect any screen available"virtualisation.graphics = false;};# NixOS tests only support Linux for now:pkgs = import nixpkgs { system = "x86_64-linux"; };vm-test = pkgs.nixosTest ({# Name of the testname = "vm-test";nodes = {server = { config, pkgs, ... }: {imports = [ sharedModule ];networking.firewall.allowedTCPPorts = [ postgrestPort ];services.postgresql = {enable = true;initialScript = pkgs.writeText "initialScript.sql" ''create schema ${schema};create table ${schema}.${table} (id serial primary key,done boolean not null default false,task text not null,due timestamptz);insert into ${schema}.${table} (task) values ('finish tutorial 0'), ('pat self on back');create role ${webRole} nologin;grant usage on schema ${schema} to ${webRole};grant select on ${schema}.${table} to ${webRole};create role ${username} inherit login password '${password}';grant ${webRole} to ${username};'';};users = {mutableUsers = false;users = {# For ease of debugging the VM as the `root` userroot.password = "";# Create a system user that matches the database user so that we# can use peer authentication. The tutorial defines a password,# but it's not necessary."${username}" = {isSystemUser = true;group = groupname;};};groups."${groupname}" = {};};systemd.services.postgrest = {wantedBy = [ "multi-user.target" ];after = [ "postgresql.service" ];script =letconfiguration = pkgs.writeText "tutorial.conf" ''db-uri = "postgres://${username}:${password}@localhost:${toString config.services.postgresql.port}/${database}"db-schema = "${schema}"db-anon-role = "${username}"'';in "${pkgs.haskellPackages.postgrest}/bin/postgrest ${configuration}";serviceConfig.User = username;};};client = {imports = [ sharedModule ];};};# Disable linting for simpler debugging of the testScriptskipLint = true;testScript = ''import jsonimport sysstart_all()server.wait_for_open_port(${toString postgrestPort})expected = [{"id": 1, "done": False, "task": "finish tutorial 0", "due": None},{"id": 2, "done": False, "task": "pat self on back", "due": None},]actual = json.loads(client.succeed("${pkgs.curl}/bin/curl http://server:${toString postgrestPort}/${table}"))assert expected == actual, "table query returns expected content"'';});in{checks.x86_64-linux.default = vm-test;packages.x86_64-linux.default = vm-test;};}
#!/usr/bin/env bash# shellcheck disable=SC1010,SC2288set -Eeuo pipefaildir="$(realpath --relative-to="${PWD}" "$(dirname "${BASH_SOURCE[0]}")")"source "${dir}/../bash/nix-container-demo-helper.sh"h "Integration testing using virtual machines", "This demo is based on https://nix.dev/tutorials/integration-testing-using-virtual-machines,", "but we adapt it to use flakes instead.", "One of the most powerful features in the Nix ecosystem is the ability to provide", "a set of declarative NixOS configurations and use a simple Python interface", "to interact with them using QEMU as the backend."h "Testing a typical web application backed by PostgreSQL", "This tutorial follows PostgREST tutorial, a generic RESTful API for PostgreSQL.", "If you skim over the official tutorial, you'll notice there's quite a bit of setup in order to test if all the steps work.", "We are going to set up:", " * A VM named 'server' running postgreSQL and postgREST.", " * A VM named 'client' running HTTP client queries using curl.", " * A testScript orchestrating testing logic between client and server."x pygmentize "${dir}/flake.nix"h "Let's run it!"n "One of these tests is just like any other derivation when it is built", "So if we've run a successful test before, the result will be in the Nix store", "and we will not re-run it automatically."x nix build "${dir}" -Ln "Force a rebuild so we can see what is happening"x nix build "${dir}" -L --rebuildh "Flake check", "'Checking' a flake involves making sure that all its output packages etc. build,", "as well as all explicit checks."x nix flake check "${dir}" -L