Skip to content

Testing Guide

Nantian Gateway’s testing system covers three layers: the control plane (Go), the data plane (Rust), and end-to-end integration tests. This page explains how to run each type of test, write new tests, and understand the CI pipeline.

Test TypeLanguageFrameworkDirectorySpeed
Control plane unit testsGotesting + testifygateway/internal/*/Fast (seconds)
Control plane integration testsGoenvtestgateway/internal/*/Medium (minutes)
Data plane unit testsRustcargo testdataplane/src/*/Fast (seconds)
Data plane integration testsRustcargo test --testdataplane/tests/Medium (minutes)
End-to-end testsGoGateway API Conformancegateway/test/e2e/Slow (tens of minutes)
Conformance testsGoGateway API Conformancegateway/test/conformance/Slow (tens of minutes)
Terminal window
cd gateway
# Run all unit tests
go test ./internal/...
# Run tests for a specific package
go test ./internal/translator/...
# Run a specific test function
go test -run TestTranslateHTTPRoute ./internal/translator/
# Run with verbose output
go test -v ./internal/...
# Run with coverage report
go test -coverprofile=coverage.out ./internal/...
go tool cover -html=coverage.out

The control plane’s integration tests use the controller-runtime envtest framework, which launches a real API Server binary locally:

Terminal window
# Run integration tests (requires envtest environment setup first)
go test -tags=integration ./internal/controller/...
# First-time setup requires installing the envtest binary
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest

Control plane tests follow standard Go community practices. Unit test files live in the same directory as source files, ending in _test.go.

gateway/internal/translator/httproute_test.go
package translator
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
)
func TestTranslateHTTPRoute(t *testing.T) {
route := &gwv1.HTTPRoute{
// ... construct test data
}
result, err := TranslateHTTPRoute(route)
require.NoError(t, err)
assert.Equal(t, "expected-name", result.Name)
assert.Len(t, result.Rules, 2)
}

Testing best practices:

  • Use testify/assert for assertions, testify/require for precondition checks
  • Name test functions following the Test<FunctionName>_<Scenario> format
  • Use table-driven tests to cover multiple input scenarios
  • Mock external dependencies (Kubernetes Client, gRPC client, etc.)
Terminal window
cd dataplane
# Run all tests
cargo test
# Run tests for a specific module
cargo test --lib proxy::http
# Run a specific test function
cargo test test_http_route_match
# Show test output
cargo test -- --nocapture
# Run in parallel (defaults to CPU core count)
cargo test -- --test-threads=4

Data plane integration tests are located in the dataplane/tests/ directory:

Terminal window
# Run all integration tests
cargo test --test integration
# Run a specific integration test file
cargo test --test proxy_integration

Rust tests are placed inside source files (unit tests) or in the tests/ directory (integration tests):

dataplane/src/proxy/http.rs
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_path_prefix_match() {
let matcher = PathMatcher::new("PathPrefix", "/api/v1");
assert!(matcher.matches("/api/v1/users"));
assert!(!matcher.matches("/other/path"));
}
#[tokio::test]
async fn test_http_route_resolution() {
let route = build_test_route();
let backend = resolve_backend(&route, &build_test_request()).await;
assert!(backend.is_some());
}
}

Testing best practices:

  • Place unit tests in #[cfg(test)] mod tests
  • Use #[tokio::test] attribute for async tests
  • Use assert!, assert_eq!, assert_ne! macros for assertions
  • For complex scenarios, use rstest or test-case crates for parameterized tests

End-to-end tests verify that the control plane and data plane work together correctly in a real Kubernetes cluster:

Terminal window
cd gateway
# Run end-to-end tests (requires a Kind cluster)
make test-e2e
# Run manually
go test -tags=e2e ./test/e2e/... -v

The end-to-end test workflow:

  1. Install Nantian Gateway in a Kind cluster
  2. Deploy sample backend services
  3. Create Gateway and HTTPRoute resources
  4. Send requests to the gateway via port forwarding
  5. Verify response content and status codes

Nantian Gateway runs the official Gateway API conformance test suite to verify the implementation’s compliance with the specification:

Terminal window
cd gateway
# Run conformance tests
make test-conformance
# Run manually
go test -tags=conformance ./test/conformance/... -v

Conformance tests produce a report listing all passing and failing features. This report serves as the basis for the project’s declared feature support.

Terminal window
cd gateway
# Code formatting
gofmt -w .
# Lint checks
golangci-lint run ./...
# Static analysis
go vet ./...
Terminal window
cd dataplane
# Code formatting
cargo fmt
# Lint checks
cargo clippy -- -D warnings
# Check for unused dependencies
cargo udeps
Terminal window
cd proto
# Format check
buf format -d
# Lint check
buf lint

Nantian Gateway uses GitHub Actions for continuous integration. Each PR triggers the following checks:

CheckDescriptionTrigger Condition
Go Unit TestsControl plane unit testsAll PRs
Go Integration TestsControl plane integration testsAll PRs
Rust Unit TestsData plane unit testsAll PRs
Rust Integration TestsData plane integration testsAll PRs
Go Lintgolangci-lintAll PRs
Rust Lintclippy + fmtAll PRs
Proto Lintbuf lintProto changes
E2E TestsEnd-to-end testsBefore merging to main
Conformance TestsGateway API conformance testsBefore merging to main

CI configuration files are located in the .github/workflows/ directory.

The project uses Codecov to track test coverage:

Terminal window
# Go coverage
cd gateway
go test -coverprofile=coverage.out ./internal/...
go tool cover -func=coverage.out
# Rust coverage (requires cargo-tarpaulin)
cd dataplane
cargo install cargo-tarpaulin
cargo tarpaulin --out Html

Coverage reports are automatically uploaded to Codecov as part of CI. The project doesn’t enforce a hard coverage threshold, but new code is encouraged to include corresponding test cases.