Running Tests
This guide explains how to run the test suite for Mycelium API Gateway. Mycelium includes comprehensive unit tests, integration tests, and end-to-end tests to ensure code quality and reliability.
Prerequisites
Before running tests, ensure you have:
- Rust toolchain (version 1.70 or higher)
- Development dependencies installed
- Test environment configured (Postgres, Redis running)
Quick Start
Run all tests with a single command:
cargo test
This will compile and run all unit tests, integration tests, and documentation tests in the project.
Test Categories
Mycelium’s test suite is organized into several categories:
Unit Tests
Unit tests verify individual functions and modules in isolation.
Run all unit tests:
cargo test --lib
Run tests for a specific module:
cargo test --lib users
cargo test --lib auth
cargo test --lib routing
Run a specific test:
cargo test --lib test_user_creation
Integration Tests
Integration tests verify interactions between multiple components.
Run all integration tests:
cargo test --test '*'
Run a specific integration test:
cargo test --test api_integration
Documentation Tests
Documentation tests ensure code examples in documentation are correct.
Run documentation tests:
cargo test --doc
Test Environment Setup
Some tests require external services (Postgres, Redis). You can set these up in multiple ways:
Option 1: Using Docker Compose (Recommended)
Start test dependencies using Docker Compose:
# Start test services
docker-compose -f docker-compose.test.yaml up -d
# Run tests
cargo test
# Stop test services
docker-compose -f docker-compose.test.yaml down
Option 2: Local Services
If you have Postgres and Redis running locally:
# Set test database URL
export TEST_DATABASE_URL="postgres://postgres:postgres@localhost:5432/mycelium_test"
# Set test Redis URL
export TEST_REDIS_URL="redis://localhost:6379"
# Run tests
cargo test
Option 3: Using Test Containers
Mycelium supports testcontainers for automatic service provisioning:
# Tests will automatically start and stop required containers
cargo test --features testcontainers
Running Specific Tests
By Test Name
Run tests matching a pattern:
# Run all tests with "auth" in the name
cargo test auth
# Run all tests with "user_service" in the name
cargo test user_service
By Package
Run tests for a specific workspace package:
# Test the API package
cargo test -p mycelium-api
# Test the base package
cargo test -p mycelium-base
# Test all packages
cargo test --workspace
By Feature
Run tests for specific features:
# Test with all features enabled
cargo test --all-features
# Test without default features
cargo test --no-default-features
# Test with specific features
cargo test --features "vault,oauth2"
Test Output and Debugging
Verbose Output
See detailed test output:
cargo test -- --nocapture
Show Test Output (Even for Passing Tests)
cargo test -- --show-output
Run Tests in Single Thread (Useful for Debugging)
cargo test -- --test-threads=1
Enable Logging During Tests
RUST_LOG=debug cargo test -- --nocapture
Code Coverage
Generate code coverage reports using tarpaulin:
Install tarpaulin
cargo install cargo-tarpaulin
Generate Coverage Report
# Generate coverage and display in terminal
cargo tarpaulin --out Stdout
# Generate HTML coverage report
cargo tarpaulin --out Html
# Generate coverage for CI (Codecov, Coveralls)
cargo tarpaulin --out Xml
View Coverage Report
# Open HTML report
open tarpaulin-report.html # macOS
xdg-open tarpaulin-report.html # Linux
Benchmarking
Run performance benchmarks:
# Run all benchmarks
cargo bench
# Run specific benchmark
cargo bench routing_benchmark
Continuous Integration
Mycelium includes CI configurations for automated testing:
GitHub Actions
The repository includes GitHub Actions workflows that run on every push and pull request:
- Unit tests
- Integration tests
- Code coverage
- Linting (clippy)
- Formatting check
View workflow status:
# Check recent workflow runs
gh run list
# View specific run
gh run view <run-id>
Running CI Tests Locally
Simulate CI environment locally:
# Run all checks that CI runs
cargo fmt --check
cargo clippy -- -D warnings
cargo test --all-features
Test Database Management
Initialize Test Database
# Create test database
psql postgres://postgres:postgres@localhost:5432/postgres \
-c "CREATE DATABASE mycelium_test;"
# Run migrations
diesel migration run --database-url postgres://postgres:postgres@localhost:5432/mycelium_test
Reset Test Database
# Drop and recreate test database
psql postgres://postgres:postgres@localhost:5432/postgres \
-c "DROP DATABASE IF EXISTS mycelium_test;"
psql postgres://postgres:postgres@localhost:5432/postgres \
-c "CREATE DATABASE mycelium_test;"
# Run migrations again
diesel migration run --database-url postgres://postgres:postgres@localhost:5432/mycelium_test
Common Test Commands
Fast Test Cycle (Development)
# Run tests in watch mode (requires cargo-watch)
cargo install cargo-watch
cargo watch -x test
Pre-Commit Checks
# Run all checks before committing
cargo fmt --check && \
cargo clippy -- -D warnings && \
cargo test --all-features
Release Build Tests
# Test with release optimizations
cargo test --release
Test Organization
Mycelium tests are organized following Rust conventions:
mycelium/
├── src/
│ └── lib.rs # Unit tests in modules
├── tests/
│ ├── api_tests.rs # Integration tests
│ ├── auth_tests.rs
│ └── routing_tests.rs
└── benches/
└── routing_bench.rs # Benchmarks
Writing New Tests
Unit Test Example
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_user_creation() {
let user = User::new("test@example.com");
assert_eq!(user.email, "test@example.com");
}
#[tokio::test]
async fn test_async_operation() {
let result = async_function().await;
assert!(result.is_ok());
}
}
Integration Test Example
// tests/api_tests.rs
use mycelium_api::*;
#[tokio::test]
async fn test_health_endpoint() {
let app = setup_test_app().await;
let response = app.get("/health").await;
assert_eq!(response.status(), 200);
}
Troubleshooting
Tests Fail Due to Database Connection
Issue: Cannot connect to test database
Solution:
# Verify Postgres is running
pg_isready
# Check connection string
echo $TEST_DATABASE_URL
Tests Hang or Timeout
Issue: Tests hang indefinitely
Solution:
# Run with timeout
cargo test -- --test-threads=1 --timeout 30
Flaky Tests
Issue: Tests fail intermittently
Solution:
# Run tests multiple times to reproduce
for i in {1..10}; do cargo test test_name || break; done
Port Conflicts
Issue: Test services can’t bind to ports
Solution:
# Stop conflicting services
docker-compose down
killall myc-api
Test Best Practices
- Isolate tests: Each test should be independent
- Use test fixtures: Create reusable test data
- Clean up: Tests should clean up after themselves
- Mock external services: Use mocks for external dependencies
- Test edge cases: Don’t just test the happy path
- Keep tests fast: Optimize slow tests
- Use descriptive names: Test names should describe what they test
Next Steps
- Contributing Guidelines - Learn how to contribute
- Configuration Guide - Configure your development environment
- Authorization Model - Understand the security model
Additional Resources
- Rust Testing Guide
- Tokio Testing
- GitHub Issues - Report test failures