Files
atlas/docs/TESTING.md
othman.suseno 507961716e
Some checks failed
CI / test-build (push) Failing after 2m26s
add tui features
2025-12-15 01:08:17 +07:00

367 lines
7.2 KiB
Markdown

# Testing Infrastructure
## Overview
AtlasOS includes a comprehensive testing infrastructure with unit tests, integration tests, and test utilities to ensure code quality and reliability.
## Test Structure
```
atlas/
├── internal/
│ ├── validation/
│ │ └── validator_test.go # Unit tests for validation
│ ├── errors/
│ │ └── errors_test.go # Unit tests for error handling
│ └── testing/
│ └── helpers.go # Test utilities and helpers
└── test/
└── integration_test.go # Integration tests
```
## Running Tests
### Run All Tests
```bash
go test ./...
```
### Run Tests for Specific Package
```bash
# Validation tests
go test ./internal/validation -v
# Error handling tests
go test ./internal/errors -v
# Integration tests
go test ./test -v
```
### Run Tests with Coverage
```bash
go test ./... -cover
```
### Generate Coverage Report
```bash
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out
```
## Unit Tests
### Validation Tests
Tests for input validation functions:
```bash
go test ./internal/validation -v
```
**Coverage:**
- ZFS name validation
- Username validation
- Password validation
- Email validation
- Share name validation
- IQN validation
- Size format validation
- Path validation
- CIDR validation
- String sanitization
- Path sanitization
**Example:**
```go
func TestValidateZFSName(t *testing.T) {
err := ValidateZFSName("tank")
if err != nil {
t.Errorf("expected no error for valid name")
}
}
```
### Error Handling Tests
Tests for error handling and API errors:
```bash
go test ./internal/errors -v
```
**Coverage:**
- Error code validation
- HTTP status code mapping
- Error message formatting
- Error details attachment
## Integration Tests
### Test Server
The integration test framework provides a test server:
```go
ts := NewTestServer(t)
defer ts.Close()
```
**Features:**
- In-memory database for tests
- Test HTTP client
- Authentication helpers
- Request helpers
### Authentication Testing
```go
// Login and get token
ts.Login(t, "admin", "admin")
// Make authenticated request
resp := ts.Get(t, "/api/v1/pools")
```
### Request Helpers
```go
// GET request
resp := ts.Get(t, "/api/v1/pools")
// POST request
resp := ts.Post(t, "/api/v1/pools", map[string]interface{}{
"name": "tank",
"vdevs": []string{"/dev/sda"},
})
```
## Test Utilities
### Test Helpers Package
The `internal/testing` package provides utilities:
**MakeRequest**: Create and execute HTTP requests
```go
recorder := MakeRequest(t, handler, TestRequest{
Method: "GET",
Path: "/api/v1/pools",
})
```
**Assertions**:
- `AssertStatusCode`: Check HTTP status code
- `AssertJSONResponse`: Validate JSON response
- `AssertErrorResponse`: Check error response format
- `AssertSuccessResponse`: Validate success response
- `AssertHeader`: Check response headers
**Example:**
```go
recorder := MakeRequest(t, handler, TestRequest{
Method: "GET",
Path: "/api/v1/pools",
})
AssertStatusCode(t, recorder, http.StatusOK)
response := AssertJSONResponse(t, recorder)
```
### Mock Clients
**MockZFSClient**: Mock ZFS client for testing
```go
mockClient := NewMockZFSClient()
mockClient.AddPool(map[string]interface{}{
"name": "tank",
"size": "10TB",
})
```
## Writing Tests
### Unit Test Template
```go
func TestFunctionName(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
}{
{"valid input", "valid", false},
{"invalid input", "invalid", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := FunctionName(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("FunctionName(%q) error = %v, wantErr %v",
tt.input, err, tt.wantErr)
}
})
}
}
```
### Integration Test Template
```go
func TestEndpoint(t *testing.T) {
ts := NewTestServer(t)
defer ts.Close()
ts.Login(t, "admin", "admin")
resp := ts.Get(t, "/api/v1/endpoint")
if resp.StatusCode != http.StatusOK {
t.Errorf("expected status 200, got %d", resp.StatusCode)
}
}
```
## Test Coverage Goals
### Current Coverage
- **Validation Package**: ~95% coverage
- **Error Package**: ~90% coverage
- **Integration Tests**: Core endpoints covered
### Target Coverage
- **Unit Tests**: >80% coverage for all packages
- **Integration Tests**: All API endpoints
- **Edge Cases**: Error conditions and boundary cases
## Best Practices
### 1. Test Naming
Use descriptive test names:
```go
func TestValidateZFSName_ValidName_ReturnsNoError(t *testing.T) {
// ...
}
```
### 2. Table-Driven Tests
Use table-driven tests for multiple cases:
```go
tests := []struct {
name string
input string
wantErr bool
}{
// test cases
}
```
### 3. Test Isolation
Each test should be independent:
```go
func TestSomething(t *testing.T) {
// Setup
ts := NewTestServer(t)
defer ts.Close() // Cleanup
// Test
// ...
}
```
### 4. Error Testing
Test both success and error cases:
```go
// Success case
err := ValidateZFSName("tank")
if err != nil {
t.Error("expected no error")
}
// Error case
err = ValidateZFSName("")
if err == nil {
t.Error("expected error for empty name")
}
```
### 5. Use Test Helpers
Use helper functions for common patterns:
```go
recorder := MakeRequest(t, handler, TestRequest{
Method: "GET",
Path: "/api/v1/pools",
})
AssertStatusCode(t, recorder, http.StatusOK)
```
## Continuous Integration
### GitHub Actions Example
```yaml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.21'
- run: go test ./... -v
- run: go test ./... -coverprofile=coverage.out
- run: go tool cover -func=coverage.out
```
## Future Enhancements
1. **More Unit Tests**: Expand coverage for all packages
2. **Integration Tests**: Complete API endpoint coverage
3. **Performance Tests**: Benchmark critical paths
4. **Load Tests**: Stress testing with high concurrency
5. **Mock Services**: Mock external dependencies
6. **Test Fixtures**: Reusable test data
7. **Golden Files**: Compare outputs to expected results
8. **Fuzzing**: Property-based testing
9. **Race Detection**: Test for race conditions
10. **Test Documentation**: Generate test documentation
## Troubleshooting
### Tests Failing
1. **Check Test Output**: Run with `-v` flag for verbose output
2. **Check Dependencies**: Ensure all dependencies are available
3. **Check Environment**: Verify test environment setup
4. **Check Test Data**: Ensure test data is correct
### Coverage Issues
1. **Run Coverage**: `go test ./... -cover`
2. **View Report**: `go tool cover -html=coverage.out`
3. **Identify Gaps**: Look for untested code paths
4. **Add Tests**: Write tests for uncovered code
### Integration Test Issues
1. **Check Server**: Verify test server starts correctly
2. **Check Database**: Ensure in-memory database works
3. **Check Auth**: Verify authentication in tests
4. **Check Cleanup**: Ensure proper cleanup after tests