Files
cluster/deploy/dev/configurations/TESTING.md
2025-08-15 18:59:10 -04:00

244 lines
7.4 KiB
Markdown

# Testing Guide for Zitadel Configurator
This document explains the testing approach and methodology used in the Zitadel Configurator project, which uses CDKTF (Cloud Development Kit for Terraform) to manage Zitadel infrastructure.
## Overview
The project uses **unit testing** with Jest to test Infrastructure as Code (IaC) definitions. Tests verify that the synthesized Terraform configuration contains the expected resources and properties without creating actual cloud resources.
## Testing Framework
### Core Technologies
- **Jest**: JavaScript testing framework
- **ts-jest**: TypeScript support for Jest
- **CDKTF Testing**: Built-in testing utilities for CDKTF applications
- **TypeScript**: Primary language for both implementation and tests
### Configuration Files
- `jest.config.js`: Jest configuration with TypeScript support
- `setup.js`: CDKTF-specific Jest setup that enables testing matchers
- `package.json`: Test scripts and dependencies
## Test Structure
### Directory Organization
```
zitadel-configurator/
├── __tests__/ # Test files directory
│ └── main.test.ts # Main test suite
├── main.ts # Implementation to be tested
├── jest.config.js # Jest configuration
└── setup.js # CDKTF Jest setup
```
### Test File Naming
- Tests are located in the `__tests__/` directory
- Test files follow the pattern: `*.test.ts`
- Alternative patterns supported: `*.spec.ts`
## Running Tests
### Available Commands
```bash
# Run all tests once
npm test
# Run tests in watch mode (auto-rerun on file changes)
npm run test:watch
```
### Test Output
Tests provide clear feedback about:
- Resource creation verification
- Property validation
- Synthesized Terraform configuration structure
## Testing Approach
### Unit Testing Philosophy
The project follows a **unit testing** approach where:
- Tests validate the synthesized Terraform configuration
- No actual cloud resources are created during testing
- Fast execution with immediate feedback
- Focus on infrastructure definition correctness
### Test Categories
#### 1. Resource Existence Tests
Verify that expected resources are created in the Terraform configuration:
```typescript
it("should create an organization resource", () => {
const app = Testing.app();
const stack = new ZitadelStack(app, "test-stack");
// Test that the stack contains an Org resource
expect(Testing.synth(stack)).toHaveResource(Org);
});
```
#### 2. Resource Property Tests
Validate that resources have the correct properties:
```typescript
it("should create organization with name 'makers'", () => {
const app = Testing.app();
const stack = new ZitadelStack(app, "test-stack");
// Test the synthesized terraform to ensure it contains the expected resource properties
expect(Testing.synth(stack)).toHaveResourceWithProperties(Org, {
name: "makers"
});
});
```
#### 3. Public Interface Tests
Verify that the stack exposes the expected outputs:
```typescript
it("should create organization with name 'makers'", () => {
const app = Testing.app();
const stack = new ZitadelStack(app, "test-stack");
// Verify the organization was created and stored
expect(stack.createdOrg).toBeDefined();
});
```
## CDKTF Testing Utilities
### Key Testing Methods
#### `Testing.app()`
Creates a CDKTF app instance for testing purposes.
#### `Testing.synth(stack)`
Synthesizes the stack into Terraform JSON configuration for testing.
#### `toHaveResource(ResourceClass)`
Custom Jest matcher that checks if the synthesized configuration contains a specific resource type.
#### `toHaveResourceWithProperties(ResourceClass, properties)`
Custom Jest matcher that validates both resource existence and specific property values.
### Setup Requirements
The `setup.js` file is crucial as it:
```javascript
const cdktf = require("cdktf");
cdktf.Testing.setupJest();
```
This enables CDKTF-specific Jest matchers and testing utilities.
## Best Practices
### 1. Test Structure
- Use descriptive test suite names (`describe` blocks)
- Write clear, specific test case descriptions
- Group related tests logically
### 2. Test Isolation
- Each test creates its own app and stack instance
- Tests are independent and don't share state
- Use fresh instances for each test case
### 3. Comprehensive Coverage
- Test resource creation
- Validate resource properties
- Verify public interfaces and outputs
- Test different configuration scenarios
### 4. Meaningful Assertions
- Test both existence and correctness
- Use specific matchers for clear error messages
- Validate the actual synthesized configuration
## Example Test Implementation
```typescript
import "cdktf/lib/testing/adapters/jest"; // Load types for expect matchers
import { Testing } from "cdktf";
import { ZitadelStack } from "../main";
import { Org } from "../.gen/providers/zitadel/org";
describe("Zitadel Configurator", () => {
describe("Unit testing using assertions", () => {
it("should create an organization resource", () => {
const app = Testing.app();
const stack = new ZitadelStack(app, "test-stack");
// Test that the stack contains an Org resource
expect(Testing.synth(stack)).toHaveResource(Org);
});
it("should create organization with name 'makers'", () => {
const app = Testing.app();
const stack = new ZitadelStack(app, "test-stack");
// Verify the organization was created and stored
expect(stack.createdOrg).toBeDefined();
// Test the synthesized terraform to ensure it contains the expected resource properties
expect(Testing.synth(stack)).toHaveResourceWithProperties(Org, {
name: "makers"
});
});
});
});
```
## Benefits of This Testing Approach
### 1. Fast Feedback
- Tests run quickly without cloud API calls
- Immediate validation of infrastructure definitions
- Suitable for continuous integration
### 2. Cost-Effective
- No cloud resources created during testing
- No API rate limits or costs
- Safe for frequent execution
### 3. Reliable
- Tests are deterministic and repeatable
- No dependency on external services during testing
- Consistent results across different environments
### 4. Development-Friendly
- Supports test-driven development (TDD)
- Watch mode for rapid iteration
- Clear error messages for debugging
## Extending Tests
### Adding New Test Cases
When adding new resources or modifying existing ones:
1. **Test Resource Creation**: Verify the new resource type exists
2. **Test Properties**: Validate all important configuration properties
3. **Test Relationships**: Verify resource dependencies and references
4. **Test Public Interface**: Ensure any exposed outputs are accessible
### Advanced Testing Scenarios
Consider adding tests for:
- Error conditions and validation
- Different configuration environments
- Resource dependencies and relationships
- Complex property calculations
## Troubleshooting
### Common Issues
#### Missing CDKTF Setup
If you see errors about missing matchers, ensure `setup.js` is properly configured in `jest.config.js`.
#### TypeScript Compilation Errors
Ensure all necessary type definitions are imported:
```typescript
import "cdktf/lib/testing/adapters/jest"; // Load types for expect matchers
```
#### Resource Import Issues
Verify that generated provider resources are properly imported:
```typescript
import { Org } from "../.gen/providers/zitadel/org";
```
This testing approach ensures robust, reliable infrastructure definitions while maintaining development velocity and cost-effectiveness.