Provider Testing Template
Standardized test checklist for DNS provider implementations. Every provider must pass these baseline tests before shipping.
Philosophy: "Does what it says on the tin." — If a provider claims to support Create, it must handle create in all documented scenarios.
Test Categories
1. Connectivity
#
Test
Description
Priority
P1
Ping success
Ping() returns nil against a reachable server
Required
P2
Ping unreachable
Ping() returns error for non-routable address
Required
P3
Ping canceled context
Ping() returns error when context is already canceled
Required
P4
Ping timeout
Ping() returns error when server doesn't respond in time
Required
P5
Auth failure
Ping() returns error with bad credentials/API key
Recommended
2. Record CRUD
#
Test
Description
Priority
C1
Create A record
Round-trip: create, query, verify rdata
Required
C2
Create AAAA record
Round-trip with IPv6 address
Required
C3
Create CNAME record
Round-trip with target FQDN
Required
C4
Create TXT record
Round-trip with arbitrary text
Required
C5
Create MX record
Round-trip with priority
Recommended
C6
Create SRV record
Round-trip with priority, weight, port
Recommended
C7
Delete specific record
Create, delete, verify gone
Required
C8
Delete all by type
Create multiple, delete all of type, verify
Required
C9
Update target
Create, update rdata, verify old gone + new present
Required
C10
Update TTL
Create, update TTL only, verify
Recommended
C11
List records
Verify List() returns seeded records
Required
C12
List empty zone
List() on empty zone returns empty slice, not error
Required
3. Error Handling
#
Test
Description
Priority
E1
Out-of-zone create
Create record outside provider's zone → error
Required
E2
Out-of-zone delete
Delete record outside provider's zone → error
Required
E3
Network error
Correct error type when server is unreachable
Required
E4
Auth error
Correct error type for bad credentials
Recommended
E5
Context cancellation
Operations respect context cancellation mid-flight
Required
E6
Invalid record data
Reject malformed IPs, empty names, etc.
Required
4. Ownership
#
Test
Description
Priority
O1
Create ownership TXT
Provider creates _dnsweaver.<hostname> TXT record
Required
O2
Query ownership
Ownership record is visible in List()
Required
O3
Delete ownership
Ownership record is removed on cleanup
Required
O4
Ownership format
TXT value matches heritage=dnsweaver[,instance=<id>]
Required
5. Edge Cases
#
Test
Description
Priority
X1
Multiple records same name
Two A records for one hostname
Recommended
X2
Long TXT value
Near 255-char string limit
Recommended
X3
Full lifecycle
Create → query → update → query → delete → query
Required
X4
Idempotent create
Creating same record twice doesn't error or duplicate
Recommended
X5
Delete non-existent
Deleting a record that doesn't exist → graceful handling
Recommended
Implementation Pattern
//go:build integration
package myprovider_test
import (
"context"
"os"
"testing"
"time"
)
func testProvider ( t * testing . T ) * Provider {
t . Helper ()
apiURL := os . Getenv ( "MYPROVIDER_TEST_URL" )
apiKey := os . Getenv ( "MYPROVIDER_TEST_API_KEY" )
zone := os . Getenv ( "MYPROVIDER_TEST_ZONE" )
if apiURL == "" || zone == "" {
t . Skip ( "MYPROVIDER_TEST_URL and MYPROVIDER_TEST_ZONE must be set" )
}
// ... create and return provider
}
func TestIntegration_CreateAndQueryA ( t * testing . T ) {
p := testProvider ( t )
ctx , cancel := context . WithTimeout ( context . Background (), 10 * time . Second )
defer cancel ()
// ... test logic
}
The shared test harness provides standard conformance tests:
func TestConformance ( t * testing . T ) {
p := testProvider ( t )
testutil . RunProviderConformance ( t , p )
}
func TestCRUDConformance ( t * testing . T ) {
p := testProvider ( t )
testutil . RunProviderCRUDConformance ( t , p )
}
Environment Variables
Each provider should document its required test environment variables at the top of the integration test file:
// Required:
// MYPROVIDER_TEST_URL - API endpoint
// MYPROVIDER_TEST_ZONE - Test zone (must allow updates)
//
// Optional:
// MYPROVIDER_TEST_API_KEY - API key (if auth required)