Attune Common Library - Integration Tests
This directory contains integration tests for the Attune common library, specifically testing the database repository layer and migrations.
Overview
The test suite includes:
- Migration Tests (
migration_tests.rs) - Verify database schema, migrations, and constraints - Repository Tests - Comprehensive CRUD and transaction tests for each repository:
pack_repository_tests.rs- Pack repository operationsaction_repository_tests.rs- Action repository operations- Additional repository tests for all other entities
- Test Helpers (
helpers.rs) - Fixtures, utilities, and common test setup
Prerequisites
Before running the tests, ensure you have:
- PostgreSQL installed and running
- Test database created and configured
- Environment variables set (via
.env.test)
Setting Up the Test Database
# Create the test database
make db-test-create
# Run migrations on test database
make db-test-migrate
# Or do both at once
make db-test-setup
To reset the test database:
make db-test-reset
Running Tests
Run All Integration Tests
# Automatic setup and run
make test-integration
# Or manually
cargo test --test '*' -p attune-common -- --test-threads=1
Run Specific Test Files
# Run only migration tests
cargo test --test migration_tests -p attune-common
# Run only pack repository tests
cargo test --test pack_repository_tests -p attune-common
# Run only action repository tests
cargo test --test action_repository_tests -p attune-common
Run Specific Tests
# Run a single test by name
cargo test test_create_pack -p attune-common
# Run tests matching a pattern
cargo test test_create -p attune-common
# Run with output
cargo test test_create_pack -p attune-common -- --nocapture
Test Configuration
Test configuration is loaded from .env.test in the project root. Key settings:
# Test database URL
ATTUNE__DATABASE__URL=postgresql://postgres:postgres@localhost:5432/attune_test
# Enable SQL logging for debugging
ATTUNE__DATABASE__LOG_STATEMENTS=true
# Verbose logging
ATTUNE__LOG__LEVEL=debug
RUST_LOG=debug,sqlx=warn
Test Structure
Test Helpers (helpers.rs)
The helpers module provides:
- Database Setup:
create_test_pool(),clean_database() - Fixtures: Builder pattern for creating test data
PackFixture- Create test packsActionFixture- Create test actionsRuntimeFixture- Create test runtimes- And more for all entities
- Utilities: Transaction helpers, assertions
Example fixture usage:
use helpers::*;
let pool = create_test_pool().await.unwrap();
clean_database(&pool).await.unwrap();
let pack_repo = PackRepository::new(&pool);
// Use fixture to create test data
let pack = PackFixture::new("test.pack")
.with_version("2.0.0")
.with_name("Custom Pack Name")
.create(&pack_repo)
.await
.unwrap();
Test Organization
Each test file follows this pattern:
- Import helpers module:
mod helpers; - Setup phase: Create pool and clean database
- Test execution: Perform operations
- Assertions: Verify expected outcomes
- Cleanup: Automatic via
clean_database()or transactions
Example test:
#[tokio::test]
async fn test_create_pack() {
// Setup
let pool = create_test_pool().await.unwrap();
clean_database(&pool).await.unwrap();
let repo = PackRepository::new(&pool);
// Execute
let pack = PackFixture::new("test.pack")
.create(&repo)
.await
.unwrap();
// Assert
assert_eq!(pack.ref_name, "test.pack");
assert!(pack.created_at.timestamp() > 0);
}
Test Categories
CRUD Operations
Tests verify basic Create, Read, Update, Delete operations:
- Creating entities with valid data
- Retrieving entities by ID and other fields
- Listing and pagination
- Updating partial and full records
- Deleting entities
Constraint Validation
Tests verify database constraints:
- Unique constraints (e.g., pack ref_name + version)
- Foreign key constraints
- NOT NULL constraints
- Check constraints
Transaction Support
Tests verify transaction behavior:
- Commit preserves changes
- Rollback discards changes
- Isolation between transactions
Error Handling
Tests verify proper error handling:
- Duplicate key violations
- Foreign key violations
- Not found scenarios
Cascading Deletes
Tests verify cascade delete behavior:
- Deleting a pack deletes associated actions
- Deleting a runtime deletes associated workers
- And other cascade relationships
Best Practices
1. Clean Database Before Tests
Always clean the database at the start of each test:
let pool = create_test_pool().await.unwrap();
clean_database(&pool).await.unwrap();
2. Use Fixtures for Test Data
Use fixture builders instead of manual creation:
// Good
let pack = PackFixture::new("test.pack").create(&repo).await.unwrap();
// Avoid
let create = CreatePack { /* ... */ };
let pack = repo.create(&create).await.unwrap();
3. Test Isolation
Each test should be independent:
- Don't rely on data from other tests
- Clean database between tests
- Use unique names/IDs
4. Single-Threaded Execution
Run integration tests single-threaded to avoid race conditions:
cargo test -- --test-threads=1
5. Descriptive Test Names
Use clear, descriptive test names:
#[tokio::test]
async fn test_create_pack_duplicate_ref_version() { /* ... */ }
6. Test Both Success and Failure
Test both happy paths and error cases:
#[tokio::test]
async fn test_create_pack() { /* success case */ }
#[tokio::test]
async fn test_create_pack_duplicate_ref_version() { /* error case */ }
Debugging Tests
Enable SQL Logging
Set in .env.test:
ATTUNE__DATABASE__LOG_STATEMENTS=true
RUST_LOG=debug,sqlx=debug
Run with Output
cargo test test_name -- --nocapture
Use Transaction Rollback
Wrap tests in transactions that rollback to inspect state:
let mut tx = pool.begin().await.unwrap();
// ... test operations ...
// Drop tx without commit to rollback
Check Database State
Connect to test database directly:
psql -d attune_test -U postgres
Continuous Integration
For CI environments:
# Setup test database
createdb attune_test
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/attune_test sqlx migrate run
# Run tests
cargo test --test '*' -p attune-common -- --test-threads=1
Common Issues
Database Connection Errors
Issue: Cannot connect to database
Solution:
- Ensure PostgreSQL is running
- Check credentials in
.env.test - Verify test database exists
Migration Errors
Issue: Migrations fail
Solution:
- Run
make db-test-resetto reset test database - Ensure migrations are in
migrations/directory
Flaky Tests
Issue: Tests fail intermittently
Solution:
- Run single-threaded:
--test-threads=1 - Clean database before each test
- Avoid time-dependent assertions
Foreign Key Violations
Issue: Cannot delete entity due to foreign keys
Solution:
- Use
clean_database()which handles dependencies - Test cascade deletes explicitly
- Delete in correct order (children before parents)
Adding New Tests
To add tests for a new repository:
- Create test file:
tests/<entity>_repository_tests.rs - Import helpers:
mod helpers; - Create fixtures in
helpers.rsif needed - Write comprehensive CRUD tests
- Test constraints and error cases
- Test transactions
- Run and verify:
cargo test --test <entity>_repository_tests
Test Coverage
To generate test coverage reports:
# Install tarpaulin
cargo install cargo-tarpaulin
# Generate coverage
cargo tarpaulin --out Html --output-dir coverage --test '*' -p attune-common
Additional Resources
Support
For issues or questions:
- Check existing tests for examples
- Review helper functions in
helpers.rs - Consult the main project documentation
- Open an issue on the project repository