Skip to content
SHC Docs

SHC test suite

Test suite for Self-Hosted Cloud (SHC).

tests/
├── unit/ # Go unit tests (plus in-package tests beside the code)
├── integration/ # Go integration tests (build tag `integration`)
├── parity/ # Golden-scenario CLI-surface pinning
├── e2e/ # End-to-end tests (single-node, BATS)
├── proxmox/ # Multi-node E2E on Proxmox VMs (BATS + terraform)
├── hetzner/ # Live hcloud E2E lane (costs money)
├── clouds/ # Per-cloud live smoke lanes (aws, azure, …; cost money)
├── tui/ # HUD tests (tui-test, pnpm)
├── manual/ # Hand-run scripts
└── TESTBOOK.md # Manual QA runbook (mixed-runtime 3-node cluster)
Terminal window
# Go tests (unit + integration)
make test
# Single-node E2E suite (builds bin/shc + bin/shcd, boots a dev daemon)
make test/e2e
# Multi-node E2E on a Proxmox host (provisions VMs via terraform)
make test/proxmox

Single-node end-to-end tests using BATS, driven by tests/e2e/scripts/test.sh (the make test/e2e entrypoint). The harness launches the freshly-built bin/shcd + bin/shc directly — no installation required.

Test FilePurpose
test_workflows.batsMain happy-path workflow: repo setup → install → operations (info, backup, clone, …) → uninstall
test_api_audit.batsAPI endpoint availability + audit log viewing/filtering/output formats
test_config_vault.batsConfig, vault, and node smoke tests
test_container_state.batsContainer state synchronization
test_dns.batsManaged DNS against a real PowerDNS container (connections-first path)
test_internal_api_bind.batsInternal API (:4003) loopback-bind knob
test_cluster_ca_rotation.batsCluster-CA rotation (single node)
test_cluster_ca_rotation_global.batsGlobal-root CA rotation (single node)

What’s NOT covered here (use the Proxmox suite): multi-node operations, cross-node move/clone, shared storage, quotas on a live cluster.

Note: apps that need real database containers can fail in the local sandbox — live backup/restore coverage belongs to the Proxmox lane.

Multi-node E2E requiring a Proxmox host. Provisioning + cluster formation run through terraform/modules/shc/proxmox + terraform-provider-shc built from the working tree; see tests/proxmox/Makefile. VMs persist between runs; the platform is reinstalled each run and VMs are destroyed only on request.

Test FilePurpose
test_multinode.batsConsolidated multi-node workflow tests
test_ingress_redesign.batsIngress / exposure / cert / proxy cluster regression net
test_ceph.batsMulti-node cephadm cluster + cephfs shared storage
test_quota.batsResource-quota enforcement on a live cluster
Terminal window
make test/proxmox # build .deb + run the suite
make test/proxmox/provision # create VMs + stage + form cluster (first time)
make test/proxmox/clean # uninstall SHC from the VMs (keep them)
make test/proxmox/destroy # delete the VMs
Terminal window
make test/unit # hermetic default lane (CGO_ENABLED=0);
# covers ./cmd, ./internal, ./migrations, ./tests/unit
make test/integration # build tag `integration`, race detector on
make test # both

Live-engine unit tests (rqlited process, cluster join, engine flip) skip unless a rqlited binary is resolvable — point SHC_RQLITED_BIN at one (or make vendor/rqlite on linux) to include them.

Golden CLI-surface scenarios (tests/parity/)

Section titled “Golden CLI-surface scenarios (tests/parity/)”
Terminal window
make parity-golden # golden CLI-surface scenarios against bin/shc

(The manifest half of the old Go-vs-Python parity firewall — parity-check + migration/manifest.yaml — was retired once the port was complete; the golden lane stays because it pins the CLI surface against regression.)

make test/e2e is the entrypoint; the script accepts a file or filter:

Terminal window
./tests/e2e/scripts/test.sh # all tests
./tests/e2e/scripts/test.sh test_workflows.bats # one file
./tests/e2e/scripts/test.sh --filter dns # files matching a pattern
./tests/e2e/scripts/test.sh --no-cleanup # keep the server after tests
make test/e2e/no-cleanup # same, via make
make test/e2e/clean # tear residual state down

Filtering inside a file uses standard bats flags:

Terminal window
bats tests/e2e/test_workflows.bats --filter "backup"
bats tests/e2e/test_workflows.bats --tap

(Running bats directly assumes make build has produced current bin/shc + bin/shcd; prefer the script, which handles server lifecycle and cleanup.)

The GitLab pipeline (.gitlab-ci.yml) builds and publishes: packages, container images, terraform modules/provider, the apps index, and pages. It runs no verification suites. The two gates it does keep are build work rather than checks — the packaging checks on the binaries and debs it is about to publish, and the leak scan over the publishable corpus.

Everything else runs locally:

Terminal window
make ci/checks # every gate the pipeline no longer runs
make lint # formatting, linters, architecture fitness
make test # unit + integration

E2E lanes are run from a workstation (make test/e2e) or against infrastructure (make test/proxmox, make test/hetzner, make test/<cloud> — the latter two cost money).

VariablePurposeDefault
SHC_VAULT_PASSWORDVault password the harness seeds/unlocks withshc
NO_CLEANUP1 = keep server + state after make test/e2e0
SHC_RQLITED_BINrqlited binary for live-engine unit tests

See environment-variables.md for the full SHC_* surface (including the test-only overrides).

#!/usr/bin/env bats
load "scripts/helpers.sh"
setup_file() {
# One-time setup (helpers.sh's setup() runs per-test)
}
@test "TEST-001: description of test" {
run shc some-command
[ "$status" -eq 0 ]
assert_output_contains "expected"
}

tests/e2e/scripts/helpers.sh provides the shared harness — a sampling:

Terminal window
start_server / stop_server # dev daemon lifecycle
shc / shc_nontty / api_call # CLI + API wrappers
assert_output_contains "text"
assert_output_not_contains "text"
validate_json
wait_for_stack / wait_for_stack_status / wait_for_stack_gone
wait_for_container / wait_for_repo
cleanup_stacks / cleanup_docker_containers
Terminal window
# The harness logs the dev daemon here (STATE_DIR from helpers.sh):
tail -f /tmp/shc-e2e/server.log
# Check status of a harness-launched daemon
./tests/e2e/scripts/status.sh
Terminal window
# Verbose output
bats tests/e2e/test_workflows.bats -t
# Keep state for post-mortem
make test/e2e/no-cleanup
./tests/e2e/scripts/logs.sh
Terminal window
# Auth/env is cached by the sub-make (tests/proxmox/.env.auth)
make test/proxmox/auth
# Check VM/platform status
make test/proxmox/status
  • tests/TESTBOOK.md — mixed-runtime 3-node cluster QA runbook (compose + swarm, postgres/keycloak/ paperless-ngx, nip.io hostnames).
  • tests/manual/ — hand-run scripts for scenarios the suites don’t automate.