279 lines
7.8 KiB
Markdown
279 lines
7.8 KiB
Markdown
# Testing Patterns
|
|
|
|
**Analysis Date:** 2026-02-23
|
|
|
|
## Test Framework
|
|
|
|
**Language-Specific Runners:**
|
|
|
|
**Go:**
|
|
- Runner: `go test` (standard library `testing` package)
|
|
- Config: No config file (uses built-in conventions)
|
|
- Run Commands:
|
|
```bash
|
|
go test ./... # Run all tests
|
|
go test -v ./... # Verbose output
|
|
go test -run TestContains ./... # Run specific test
|
|
go test -cover ./... # Show coverage
|
|
```
|
|
|
|
**Bash:**
|
|
- Runner: Custom shell scripts in `scripts/`
|
|
- No formal test framework; uses `set -euo pipefail` for error handling
|
|
- Manual health checks via `bash scripts/cluster_healthcheck.sh`
|
|
|
|
**Terraform:**
|
|
- Framework: No automated testing detected (no terraform test files, no tftest.hcl)
|
|
- Validation: Manual `terraform validate`, `terraform plan`, visual inspection
|
|
- Integration: Terragrunt applies validate before execution
|
|
|
|
## Test File Organization
|
|
|
|
**Location:**
|
|
- Go tests: Co-located with source code: `<service>/files/internal/scraper/validate_test.go`
|
|
- Shell/Infrastructure: No test files (manual validation/health checks only)
|
|
|
|
**Naming:**
|
|
- Go: `*_test.go` suffix
|
|
- Script tests: `.sh` for check/validation scripts
|
|
|
|
**Structure:**
|
|
```
|
|
stacks/f1-stream/files/internal/scraper/
|
|
├── main.go
|
|
├── validate.go
|
|
└── validate_test.go # Test file co-located
|
|
```
|
|
|
|
## Test Structure
|
|
|
|
**Go Table-Driven Tests:**
|
|
|
|
```golang
|
|
func TestContainsVideoMarkers(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
body string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "video tag",
|
|
body: `<div><video src="stream.mp4"></video></div>`,
|
|
want: true,
|
|
},
|
|
// ... more test cases
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := containsVideoMarkers(tt.body)
|
|
if got != tt.want {
|
|
t.Errorf("containsVideoMarkers(%q) = %v, want %v", truncate(tt.body, 60), got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
```
|
|
|
|
**Patterns:**
|
|
- Slice of anonymous structs with `name`, input fields, and `want` for expected result
|
|
- Loop with `t.Run(tt.name, ...)` for individual test case execution and reporting
|
|
- Descriptive test case names: `"video tag"`, `"HLS manifest reference"`, `"empty string"`
|
|
- Separate positive cases (upper) and negative cases (lower) with comments
|
|
|
|
**Bash Health Check Structure:**
|
|
```bash
|
|
check_nodes() {
|
|
section 1 "Node Status"
|
|
local nodes not_ready versions unique_versions detail=""
|
|
|
|
nodes=$($KUBECTL get nodes --no-headers 2>&1) || { fail "Cannot reach cluster"; json_add "node_status" "FAIL" "Cannot reach cluster"; return 0; }
|
|
# ... processing
|
|
if [[ -n "$not_ready" ]]; then
|
|
fail "NotReady nodes: $not_ready"
|
|
json_add "node_status" "FAIL" "$detail"
|
|
elif [[ "$unique_versions" -gt 1 ]]; then
|
|
warn "Version mismatch..."
|
|
json_add "node_status" "WARN" "$detail"
|
|
else
|
|
pass "All nodes Ready..."
|
|
json_add "node_status" "PASS" "$detail"
|
|
fi
|
|
}
|
|
```
|
|
|
|
**Patterns:**
|
|
- Each check function follows same structure: setup → validation → status reporting
|
|
- Status reported via `pass()`, `warn()`, `fail()` helper functions
|
|
- JSON output optional via `json_add()` for programmatic consumption
|
|
- Error handling inline with `||` fallback and graceful degradation
|
|
|
|
## Mocking
|
|
|
|
**Framework:**
|
|
- Go: No mocking framework detected (table-driven tests use real function calls)
|
|
- Bash: External commands mocked implicitly (KUBECONFIG override, kubectl invocation through `$KUBECTL` variable)
|
|
|
|
**Patterns (Go):**
|
|
- No mock objects or stubs
|
|
- Real function behavior tested directly
|
|
- Test data provided as input in struct fields
|
|
|
|
**Patterns (Bash):**
|
|
```bash
|
|
# Kubeconfig override allows testing against different clusters
|
|
KUBECTL="kubectl --kubeconfig $KUBECONFIG_PATH"
|
|
nodes=$($KUBECTL get nodes --no-headers 2>&1) || { fail "Cannot reach cluster"; return 0; }
|
|
```
|
|
|
|
**What NOT to Mock:**
|
|
- Core functionality being tested (test actual behavior)
|
|
- Standard library functions (test integration)
|
|
|
|
**What to Mock (Bash):**
|
|
- External kubectl calls via variable indirection: allows `KUBECONFIG` override
|
|
- Conditional output by flag: `--json`, `--quiet` flags change output, not behavior
|
|
|
|
## Fixtures and Factories
|
|
|
|
**Test Data (Go):**
|
|
- Inline strings in struct fields: HTML content, MIME types
|
|
- Examples from `validate_test.go`:
|
|
```golang
|
|
{
|
|
name: "HLS manifest reference",
|
|
body: `var url = "https://cdn.example.com/live.m3u8";`,
|
|
want: true,
|
|
},
|
|
```
|
|
|
|
**Location:**
|
|
- Embedded directly in test file as struct field values
|
|
- No separate fixture files or factories
|
|
|
|
**Bash Fixtures:**
|
|
- Real cluster fixtures: tests run against actual Kubernetes cluster
|
|
- No data files; tests fetch live state via kubectl
|
|
|
|
## Coverage
|
|
|
|
**Requirements:** None enforced (no coverage thresholds, targets, or CI/CD gates detected)
|
|
|
|
**View Coverage (Go):**
|
|
```bash
|
|
go test -cover ./... # Show coverage percentages
|
|
go test -coverprofile=coverage.out ./...
|
|
go tool cover -html=coverage.out # Open HTML report
|
|
```
|
|
|
|
**Note:** Coverage tools not integrated into CI/CD pipeline; manual check only.
|
|
|
|
## Test Types
|
|
|
|
**Unit Tests (Go):**
|
|
- Scope: Single function validation
|
|
- Approach: Table-driven with parameterized inputs
|
|
- Example: `TestContainsVideoMarkers()` tests HTML content detection
|
|
- Example: `TestIsDirectVideoContentType()` tests MIME type classification
|
|
- In file: `stacks/f1-stream/files/internal/scraper/validate_test.go`
|
|
|
|
**Integration Tests:**
|
|
- Bash health checks (`scripts/cluster_healthcheck.sh`) serve as integration tests
|
|
- Tests 24 separate checks against live Kubernetes cluster:
|
|
- Node status and readiness
|
|
- Node resource utilization
|
|
- Container metrics
|
|
- Pod crash loops
|
|
- Persistent volume health
|
|
- DNS resolution
|
|
- Networking
|
|
- RBAC
|
|
- Logs aggregation
|
|
- Can run with `--fix` flag for auto-remediation
|
|
- Can output JSON for CI integration
|
|
|
|
**E2E Tests:**
|
|
- Not formally implemented
|
|
- Manual validation via Terragrunt apply → cluster state verification
|
|
|
|
**Infrastructure Testing:**
|
|
- Terraform: `terraform validate` and `terraform plan` provide syntax/logic validation
|
|
- Application health: Manual checks via scripts and cluster_healthcheck.sh
|
|
- No automated test suite for infrastructure code
|
|
|
|
## Common Patterns
|
|
|
|
**Async Testing (Go):**
|
|
- Not applicable (synchronous function testing only)
|
|
|
|
**Error Testing (Go):**
|
|
```golang
|
|
{
|
|
name: "empty string",
|
|
body: "",
|
|
want: false,
|
|
},
|
|
```
|
|
- Negative test cases included in same table
|
|
- Error/edge cases named descriptively: `"empty string"`, `"reddit link page"`
|
|
- Expected failure behavior verified: `want: false` for invalid inputs
|
|
|
|
**Error Reporting (Go):**
|
|
```golang
|
|
t.Errorf("containsVideoMarkers(%q) = %v, want %v", truncate(tt.body, 60), got, tt.want)
|
|
```
|
|
- Formatted message includes: function name, input (truncated), actual, expected
|
|
- Test name automatically prefixed by `t.Run(tt.name, ...)`
|
|
|
|
**Status Reporting (Bash):**
|
|
- Color-coded status: `${GREEN}[PASS]${NC}`, `${YELLOW}[WARN]${NC}`, `${RED}[FAIL]${NC}`
|
|
- Counter incremented per status
|
|
- Optional quiet mode (`--quiet`) suppresses PASS output
|
|
- Optional JSON output (`--json`) for CI integration
|
|
- Summary printed at end: `$PASS_COUNT/$WARN_COUNT/$FAIL_COUNT`
|
|
|
|
## Running Tests
|
|
|
|
**Go Tests:**
|
|
```bash
|
|
# From service directory containing *_test.go
|
|
go test -v ./...
|
|
```
|
|
|
|
**Bash Health Checks:**
|
|
```bash
|
|
# Comprehensive checks
|
|
bash scripts/cluster_healthcheck.sh
|
|
|
|
# Quiet mode (WARN/FAIL only)
|
|
bash scripts/cluster_healthcheck.sh --quiet
|
|
|
|
# Auto-fix mode
|
|
bash scripts/cluster_healthcheck.sh --fix
|
|
|
|
# JSON output
|
|
bash scripts/cluster_healthcheck.sh --json
|
|
|
|
# Custom kubeconfig
|
|
bash scripts/cluster_healthcheck.sh --kubeconfig /path/to/config
|
|
```
|
|
|
|
**Terraform Validation:**
|
|
```bash
|
|
# Format check
|
|
terraform fmt -recursive
|
|
|
|
# Syntax validation
|
|
terraform validate
|
|
|
|
# Plan without apply
|
|
terraform plan
|
|
|
|
# From stack directory
|
|
cd stacks/<service> && terragrunt plan
|
|
cd stacks/<service> && terragrunt apply --non-interactive
|
|
```
|
|
|
|
---
|
|
|
|
*Testing analysis: 2026-02-23*
|