Open-Source Wikis

/

Caddy

/

Packages

/

caddytest

caddyserver/caddy

caddytest

Package: github.com/caddyserver/caddy/v2/caddytest.

Integration-test harness that spins up a real Caddy instance against an isolated admin port and asserts HTTP behavior.

Purpose

Make it cheap and reliable to write end-to-end tests that:

  • Start a Caddy instance with a specific Caddyfile or JSON config.
  • Issue real HTTP/HTTPS requests against it.
  • Assert response status, body, headers, redirects.
  • Tear everything down at test end.

This is what caddytest/integration/... uses, and it's the right place to add tests for cross-module behavior.

Directory layout

Path Role
caddytest/caddytest.go The Tester type and its assertion helpers (~17 KB)
caddytest/caddytest_test.go Tests of the harness itself
caddytest/*.crt, *.key, *.pem, caddy.ca.cer Pre-issued test certificates (avoid hitting real ACME)
caddytest/integration/ Big collection of integration tests using Tester
caddytest/integration/caddyfile_adapt/ Caddyfile→JSON golden-file fixtures

Key abstractions

Type Where Description
Tester caddytest.go Holds the running Caddy admin URL, an HTTP client, and helper methods
NewTester(t *testing.T) caddytest.go Spawns a Caddy instance on isolated ports, returns the tester
InitServer(config string, configType string) caddytest.go Loads the given config (caddyfile or json) into the running instance
AssertGetResponse, AssertPostResponseBody, AssertResponseCode, AssertRedirect caddytest.go Common HTTP assertions

How it works

graph TD
    NewTester[NewTester(t)] --> Spawn[start in-process caddy]
    Spawn --> Admin[admin on localhost:2999]
    Test[test code] -->|InitServer| Admin
    Admin -->|/load| RunningCfg[running config]
    Test -->|HTTP request| Caddy[caddy on 9080/9443]
    Caddy --> Resp
    Resp --> Test
    TestEnd -->|t.Cleanup| Stop
    Stop -->|/stop| Admin

In-process Caddy

NewTester initializes the same module registry as a real Caddy binary (by importing modules/standard) and starts the admin endpoint on localhost:2999. The HTTP server, when later configured via InitServer, uses ports 9080 (HTTP) and 9443 (HTTPS) by convention.

Config loading

InitServer(config, "caddyfile") runs the Caddyfile adapter and POSTs the result to /load. InitServer(config, "json") posts the JSON directly. The convention block at the top of every test config is:

{
    skip_install_trust
    admin localhost:2999
    http_port 9080
    https_port 9443
    grace_period 1ns
}

skip_install_trust prevents the test from modifying the OS trust store; grace_period 1ns makes shutdown immediate.

Assertions

Helpers handle the common patterns:

  • AssertGetResponse(url, expectedStatus, expectedBody)
  • AssertResponseCode(req, expectedStatus)
  • AssertResponse(req, expectedStatus, expectedBody)
  • AssertRedirect(url, expectedLocation, expectedStatus)
  • AssertGetResponseBody(url, expectedStatus, expectedBody)

The bundled HTTP client trusts the test CA (caddy.ca.cer) so HTTPS works without extra setup.

Mock DNS

caddytest/integration/mockdns_test.go registers dns.providers.mock, an in-memory DNS provider used to test ACME-DNS-01 issuance flows without touching real DNS.

Caddyfile adapt fixtures

Under caddytest/integration/caddyfile_adapt/, each test reads a .txt Caddyfile, runs the adapter, and diffs the result against an expected JSON file. This is how the Caddyfile→JSON conversion is regression-tested.

Usage example

func TestStaticResponse(t *testing.T) {
    tester := caddytest.NewTester(t)
    tester.InitServer(`
    {
        admin localhost:2999
        http_port 9080
    }
    localhost:9080 {
        respond "hello"
    }`, "caddyfile")

    tester.AssertGetResponse("http://localhost:9080/", 200, "hello")
}

That's everything you need for a passing test. No mocks, no fakes — a real Caddy.

Integration points

  • Module registry: caddytest imports modules/standard, so all default modules are available.
  • CI: runs go test ./caddytest/integration/... as part of the normal test step.
  • Caddyfile adapter: the fixtures are the regression suite for adapter changes.

Entry points for modification

  • Add a new assertion helper? caddytest.go. Aim for the smallest helper that covers the case.
  • Add an integration test? Place it under caddytest/integration/<area>/ and use NewTester.
  • Add a new Caddyfile-adapt fixture? caddytest/integration/caddyfile_adapt/ with paired .txt (input) and the expected JSON file.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

caddytest – Caddy wiki | Factory