Test Fixtures
Test fixtures provide a way to set up test data and environments for consistent, repeatable testing in HypnoScript.
Overview
Test fixtures are predefined data sets and configurations that help ensure your tests run consistently across different environments and scenarios.
Creating Test Fixtures
1. Basic Test Fixture Structure
hyp
// test_fixtures.hyp
Session TestData {
// User data fixtures
induce testUser: record = {
"name": "John Doe",
"email": "john@example.com",
"age": 30,
"active": true
};
induce adminUser: record = {
"name": "Admin User",
"email": "admin@example.com",
"age": 35,
"active": true,
"role": "admin"
};
// Array fixtures
induce numberArray: number[] = [1, 2, 3, 4, 5, 10, 15, 20];
induce stringArray: string[] = ["apple", "banana", "cherry", "date"];
induce mixedArray: any[] = [1, "hello", true, 3.14];
// Configuration fixtures
induce testConfig: record = {
"timeout": 5000,
"retries": 3,
"debug": true,
"logLevel": "INFO"
};
}
2. Loading Fixtures in Tests
hyp
// test_with_fixtures.hyp
Focus {
// Load test fixtures
MindLink TestData;
// Use fixture data in tests
induce user: record = testUser;
Observe("Testing with user: " + user["name"]);
// Validate user data
Assert(IsString(user["name"]), "User name should be a string");
Assert(IsNumber(user["age"]), "User age should be a number");
Assert(user["age"] > 0, "User age should be positive");
// Test with different fixtures
induce admin: record = adminUser;
Assert(admin["role"] == "admin", "Admin should have admin role");
// Test array fixtures
induce numbers: number[] = numberArray;
Assert(Length(numbers) == 8, "Number array should have 8 elements");
Assert(numbers[0] == 1, "First element should be 1");
Observe("All fixture tests passed!");
} Relax
Advanced Fixture Patterns
1. Dynamic Fixture Generation
hyp
// dynamic_fixtures.hyp
Focus {
function GenerateUserFixture(name: string, age: number, role: string): record {
return {
"name": name,
"email": ToLowerCase(name) + "@example.com",
"age": age,
"role": role,
"active": true,
"createdAt": GetCurrentTime()
};
}
function GenerateNumberArray(size: number, start: number, step: number): number[] {
induce result: number[] = [];
induce current: number = start;
for (induce i: number = 0; i < size; i = i + 1) {
result = ArrayPush(result, current);
current = current + step;
}
return result;
}
// Generate test data dynamically
induce dynamicUser: record = GenerateUserFixture("Jane Smith", 28, "user");
induce fibonacci: number[] = GenerateNumberArray(10, 1, 1);
// Test dynamic fixtures
Assert(dynamicUser["name"] == "Jane Smith", "Dynamic user name should match");
Assert(Length(fibonacci) == 10, "Fibonacci array should have 10 elements");
Observe("Dynamic fixture generation successful!");
} Relax
2. Fixture Validation
hyp
// fixture_validation.hyp
Focus {
function ValidateUserFixture(user: record): boolean {
// Check required fields
if (!HasKey(user, "name") || IsNullOrEmpty(user["name"])) {
return false;
}
if (!HasKey(user, "email") || IsNullOrEmpty(user["email"])) {
return false;
}
if (!HasKey(user, "age") || !IsNumber(user["age"])) {
return false;
}
// Validate email format
if (!IsValidEmail(user["email"])) {
return false;
}
// Validate age range
if (user["age"] < 0 || user["age"] > 150) {
return false;
}
return true;
}
function ValidateArrayFixture(arr: any[], expectedType: string): boolean {
if (!IsArray(arr)) {
return false;
}
if (Length(arr) == 0) {
return false;
}
// Check type consistency
for (induce i: number = 0; i < Length(arr); i = i + 1) {
if (expectedType == "number" && !IsNumber(arr[i])) {
return false;
}
if (expectedType == "string" && !IsString(arr[i])) {
return false;
}
}
return true;
}
// Test fixture validation
MindLink TestData;
Assert(ValidateUserFixture(testUser), "Test user fixture should be valid");
Assert(ValidateUserFixture(adminUser), "Admin user fixture should be valid");
Assert(ValidateArrayFixture(numberArray, "number"), "Number array fixture should be valid");
Assert(ValidateArrayFixture(stringArray, "string"), "String array fixture should be valid");
Observe("Fixture validation tests passed!");
} Relax
3. Fixture Cleanup and Reset
hyp
// fixture_cleanup.hyp
Focus {
function ResetTestEnvironment(): void {
// Clear any test data
ClearScreen();
Observe("Test environment reset");
}
function CleanupTestData(): void {
// Perform cleanup operations
Observe("Cleaning up test data...");
// Reset any global state
// Clear caches
// Reset configurations
Observe("Test data cleanup completed");
}
// Test with cleanup
MindLink TestData;
// Run tests
induce user: record = testUser;
Assert(user["name"] == "John Doe", "User name should match fixture");
// Cleanup after tests
CleanupTestData();
ResetTestEnvironment();
Observe("Test completed with proper cleanup!");
} Relax
Fixture Categories
1. Data Fixtures
hyp
// data_fixtures.hyp
Session DataFixtures {
// User data
induce users: record[] = [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"},
{"id": 3, "name": "Charlie", "email": "charlie@example.com"}
];
// Product data
induce products: record[] = [
{"id": "P001", "name": "Laptop", "price": 999.99, "category": "Electronics"},
{"id": "P002", "name": "Book", "price": 19.99, "category": "Books"},
{"id": "P003", "name": "Coffee", "price": 4.99, "category": "Food"}
];
// Configuration data
induce settings: record = {
"theme": "dark",
"language": "en",
"timezone": "UTC",
"notifications": true
};
}
2. State Fixtures
hyp
// state_fixtures.hyp
Session StateFixtures {
// Application state
induce appState: record = {
"isLoggedIn": true,
"currentUser": "admin",
"permissions": ["read", "write", "delete"],
"sessionTimeout": 3600
};
// Form state
induce formState: record = {
"isValid": true,
"isSubmitted": false,
"errors": [],
"values": {
"username": "testuser",
"email": "test@example.com",
"password": "********"
}
};
}
3. Error Fixtures
hyp
// error_fixtures.hyp
Session ErrorFixtures {
// Common error scenarios
induce validationErrors: record[] = [
{"field": "email", "message": "Invalid email format", "code": "EMAIL_INVALID"},
{"field": "password", "message": "Password too short", "code": "PASSWORD_SHORT"},
{"field": "age", "message": "Age must be positive", "code": "AGE_INVALID"}
];
induce networkErrors: record[] = [
{"code": 404, "message": "Resource not found", "type": "NOT_FOUND"},
{"code": 500, "message": "Internal server error", "type": "SERVER_ERROR"},
{"code": 403, "message": "Access forbidden", "type": "FORBIDDEN"}
];
}
Best Practices
1. Fixture Organization
hyp
// Organize fixtures by domain
Session UserFixtures {
// User-related test data
}
Session ProductFixtures {
// Product-related test data
}
Session ConfigFixtures {
// Configuration test data
}
2. Fixture Naming Conventions
hyp
// Use descriptive names
induce validUserFixture: record = {...};
induce invalidUserFixture: record = {...};
induce adminUserFixture: record = {...};
// Use consistent naming patterns
induce testData_Users: record[] = {...};
induce testData_Products: record[] = {...};
induce testData_Config: record = {...};
3. Fixture Documentation
hyp
// Document your fixtures
Session WellDocumentedFixtures {
// User fixture for testing authentication
// Contains valid user credentials and profile data
induce testUser: record = {
"username": "testuser",
"password": "testpass123",
"email": "test@example.com",
"profile": {
"firstName": "Test",
"lastName": "User",
"age": 25
}
};
// Admin user fixture for testing authorization
// Contains admin privileges and elevated permissions
induce adminUser: record = {
"username": "admin",
"password": "adminpass123",
"email": "admin@example.com",
"role": "admin",
"permissions": ["read", "write", "delete", "admin"]
};
}
4. Fixture Reusability
hyp
// Create reusable fixture components
function CreateBaseUser(name: string, email: string): record {
return {
"name": name,
"email": email,
"createdAt": GetCurrentTime(),
"isActive": true
};
}
function CreateUserWithRole(name: string, email: string, role: string): record {
induce baseUser: record = CreateBaseUser(name, email);
baseUser["role"] = role;
return baseUser;
}
Integration with Test Framework
1. Using Fixtures in Test Commands
bash
# Run tests with specific fixtures
dotnet run -- test test_with_fixtures.hyp --verbose
# Run tests with fixture validation
dotnet run -- test fixture_validation.hyp --debug
2. Fixture Loading in Tests
hyp
// test_integration.hyp
Focus {
// Load multiple fixture sessions
MindLink TestData;
MindLink DataFixtures;
MindLink ErrorFixtures;
// Test with combined fixtures
induce user: record = testUser;
induce products: record[] = products;
induce errors: record[] = validationErrors;
// Comprehensive testing
Assert(ValidateUserFixture(user), "User fixture should be valid");
Assert(Length(products) > 0, "Products fixture should not be empty");
Assert(Length(errors) > 0, "Error fixtures should be available");
Observe("Integration test with fixtures completed successfully!");
} Relax
Conclusion
Test fixtures are essential for creating reliable, maintainable tests in HypnoScript. By following these patterns and best practices, you can create comprehensive test suites that are easy to understand, maintain, and extend.
Remember to:
- Keep fixtures simple and focused
- Use descriptive names and documentation
- Validate fixture data
- Organize fixtures logically
- Reuse fixture components when possible
- Clean up after tests
This approach will help you build robust test suites that catch issues early and provide confidence in your code quality.