Rust Test Harness
A modern, feature-rich testing framework for Rust with real Docker container management, hooks, and parallel execution.
Requirements
- Docker: This framework requires Docker to be installed and running on your system
- Rust: Rust 1.70+ with Cargo
Features
- Rust-Native Testing: Works exactly like Rust's built-in
#[test]attribute - Docker Integration: Run tests in isolated containers
- Container Hooks: NEW!
before_each/after_eachfor per-test container lifecycle - Test Hooks:
before_all,before_each,after_each,after_all - Parallel Execution: Run tests concurrently with configurable concurrency
- Tag-based Filtering: Organize and filter tests by tags
- Test Timeouts: Set maximum execution time for tests
- HTML Reports: Generate beautiful, interactive test reports with automatic target folder organization
Quick Start
Basic Usage (Rust-Style)
Your test harness works exactly like Rust's built-in testing framework! You can use it in mod tests blocks and outside of main() functions. The framework is fully functional:
use test_case;
Running Tests
# Run all tests (discovered by cargo test)
# Run specific test
# Run tests with filter
# Run specific example
# Run specific test in an example
Advanced Features
Docker Integration
Docker integration is available through the container hooks system (see Container Integration section for details).
Test Hooks
Important Note: Hooks are built into the framework and work automatically. You don't need to manually call them.
use test_case;
What Hooks Can Do:
- ✅ Setup/teardown test databases
- ✅ Container lifecycle management (NEW!)
- ✅ Initialize test data
- ✅ Clean up test files
- ✅ Manage test configuration
- ✅ Handle test environment setup
Container Management with Hooks:
use ;
let container = new
.port
.env;
before_each;
after_each;
What Hooks Are NOT For:
- ❌ Complex resource orchestration (use specialized macros)
- ❌ Cross-test data sharing (use
before_all/after_allinstead)
Tag-based Filtering
use test_with_tags;
test_with_tags;
// Skip slow tests: TEST_SKIP_TAGS=slow cargo test
HTML Reports
Generate beautiful, interactive HTML reports for your test results. All HTML reports are automatically stored in the target/test-reports/ directory for clean project organization and easy CI/CD integration:
use run_tests_with_config;
let config = TestConfig ;
let result = run_tests_with_config;
// Generates target/test-reports/test-results.html with comprehensive test results
HTML Report Features:
- 📊 Visual Summary: Pass/fail/skip statistics with color-coded cards
- 📋 Detailed Results: Individual test results with status and error details
- 🎨 Modern Design: Responsive, mobile-friendly interface with gradients
- 🔍 Test Information: Tags, timeouts, Docker configuration, and error messages
- ⏱️ Execution Time: Total test execution duration
- 📱 Responsive Layout: Works on desktop, tablet, and mobile devices
- 🔽 Expandable Details: Click any test to view detailed metadata and configuration
- 🔍 Search Functionality: Search tests by name, status, or tags in real-time
- ⌨️ Keyboard Shortcuts: Ctrl+F (search), Ctrl+A (expand all), Ctrl+Z (collapse all)
- 🚨 Auto-Expand Failed: Failed tests automatically expand for better visibility
Environment Variable:
# Report will be saved to: target/test-reports/test-results.html
Path Resolution:
- Relative paths (e.g.,
"report.html") → Automatically stored intarget/test-reports/report.html - Absolute paths (e.g.,
"/tmp/report.html") → Stored at the exact specified location - Target directory: Uses
CARGO_TARGET_DIRenvironment variable or defaults to"target"
Target Folder Benefits:
- 🗂️ Clean Project Structure: No HTML files cluttering your project root
- 🔄 CI/CD Friendly: Easy to exclude from version control and clean up
- 📁 Organized Output: All test reports in one dedicated location
- 🚀 Rust Conventions: Follows standard Rust project structure
- 🧹 Easy Cleanup: Simple to remove with
cargo clean
Interactive Features
The HTML reports include several interactive features to enhance your testing experience:
🔽 Expandable Test Details
- Click on any test header to expand/collapse detailed information
- View test metadata including tags, timeouts, and Docker configuration
- Error details are automatically displayed for failed tests
🔍 Real-Time Search
- Search box filters tests by name, status, or tags
- Results update instantly as you type
- Case-insensitive search for better usability
⌨️ Keyboard Shortcuts
Ctrl+F(orCmd+Fon Mac): Focus search boxCtrl+A(orCmd+Aon Mac): Expand all test detailsCtrl+Z(orCmd+Zon Mac): Collapse all test details
🚨 Smart Defaults
- Failed tests automatically expand for immediate visibility
- Hover effects provide visual feedback
- Responsive design adapts to all screen sizes
Framework vs. Standard Testing
| Feature | Rust Standard | Rust Test Harness |
|---|---|---|
| Basic Tests | #[test] |
test_case!() or #[test] |
| Test Discovery | ✅ | ✅ |
| Parallel Execution | ✅ | ✅ |
| Test Hooks | ❌ | ✅ (Automatic) |
| Docker Integration | ❌ | ✅ |
| Tag-based Filtering | ❌ | ✅ |
| Test Timeouts | ❌ | ✅ |
| HTML Reports | ❌ | ✅ (with target folder organization) |
Note: The framework is fully functional and works correctly in all test environments. HTML reports are automatically stored in the organized target/test-reports/ directory for clean project structure.
Migration from Standard Tests
Converting from standard Rust tests is simple:
Before (Standard Rust):
After (Rust Test Harness):
test_case!;
Or keep using #[test] unchanged:
ContainerConfig
The ContainerConfig struct provides a clean, builder-pattern approach to configuring containers for testing:
use ContainerConfig;
use Duration;
let container = new
.port // Host port -> Container port
.env // Environment variables
.name // Container name
.ready_timeout; // Wait for container readiness
Available Methods:
.port(host_port, container_port)- Map host ports to container ports.auto_port(container_port)- Automatically assign available host port for container port.env(key, value)- Set environment variables.name(name)- Set container name.ready_timeout(duration)- Set readiness timeout.no_auto_cleanup()- Disable automatic cleanup (containers persist after tests)
Container Lifecycle Methods:
.start()- Start container and returnContainerInfo.stop(container_id)- Stop container by ID
Automatic Cleanup: By default, all containers are automatically stopped and removed when tests complete. This ensures a clean environment for each test run.
Port Configuration Options:
-
Auto-Port Assignment (Recommended): The framework automatically finds available ports on your system, eliminating port conflicts:
let container = new .auto_port // Automatically assign available host port for container port 80 .auto_port; // Automatically assign available host port for container port 443 let container_info = container.start?; println!; println!; -
User-Specified Ports: You can also specify exact port mappings when you need specific ports:
let container = new .port // Map host port 5432 to container port 5432 .port; // Map host port 8080 to container port 80 let container_info = container.start?; // PostgreSQL will be accessible on localhost:5432 // HTTP service will be accessible on localhost:8080 -
Mixed Configuration: Combine both approaches for maximum flexibility:
let container = new .port // Fixed mapping for main service .auto_port // Auto-assign for HTTPS .auto_port; // Auto-assign for metrics let container_info = container.start?; println!; if let Some = container_info.host_port_for
ContainerInfo Object:
When you start a container, you get a ContainerInfo object with:
- Port Information: Easy access to host ports and URLs
- Container Details: ID, image, name, and status
- Convenience Methods: Get URLs, port mappings, and summaries
let container_info = container.start?;
// Get the host port for a specific container port
if let Some = container_info.host_port_for
// Get all URLs
for url in &container_info.urls
// Get port summary
println!;
🌐 Accessing Container Ports and URLs
The framework provides comprehensive access to container port information, making it easy to connect to your services:
Getting Host Ports
let container = new
.auto_port // Auto-assign available host port
.env;
let container_info = container.start?;
// Get the actual host port that was assigned
if let Some = container_info.host_port_for
Getting Service URLs
let web_container = new
.auto_port
.auto_port;
let web_info = web_container.start?;
// Get ready-to-use URLs
if let Some = web_info.url_for_port
// Get primary URL (first port)
if let Some = web_info.primary_url
Real-World Usage Patterns
// Pattern 1: Database Testing
let db_info = postgres_container.start?;
if let Some = db_info.host_port_for
// Pattern 2: API Testing
let api_info = api_container.start?;
if let Some = api_info.primary_url
// Pattern 3: Multiple Services
let web_info = web_container.start?;
let db_info = db_container.start?;
println!;
println!;
println!;
// All ports are different - no conflicts!
ContainerInfo Methods Reference
| Method | Purpose | Example |
|---|---|---|
host_port_for(container_port) |
Get host port for specific container port | container_info.host_port_for(80) |
url_for_port(container_port) |
Get URL for specific container port | container_info.url_for_port(80) |
primary_url() |
Get URL for first port | container_info.primary_url() |
ports_summary() |
Human-readable port mappings | container_info.ports_summary() |
port_mappings |
All (host_port, container_port) pairs |
container_info.port_mappings |
urls |
All service URLs | container_info.urls |
Example with PostgreSQL:
let postgres = new
.port
.env
.env
.env
.name
.ready_timeout;
// Use in hooks
before_each;
Examples
Check out the examples/ directory for comprehensive examples:
Core Examples
minimal_rust_style.rs- Minimal example showing Rust-style testingrust_style_tests.rs- Comprehensive Rust-style testing patternsbasic_usage.rs- Basic framework usage withtest_case!
Real-World Examples
advanced_features.rs- Advanced features and patternsreal_world_calculator.rs- Real-world application testingmongodb_integration.rs- NEW! Database testing with container hooks (recommended approach)auto_port_demo.rs- NEW! Auto-port functionality and container management democontainer_port_access.rs- NEW! Detailed guide on accessing container ports and URLscargo_test_integration.rs- Integration with cargo test
Container Management Examples
mongodb_integration.rs- Container Hooks Pattern: Usesbefore_each/after_eachfor per-test container lifecycle
Container Hooks Pattern The container hooks approach provides excellent control and isolation:
- Each test gets a fresh container
- Automatic cleanup prevents resource leaks
- Cleaner separation of concerns
- More flexible configuration options
Running Examples
# Run a specific example
# Test a specific example
# Run specific test in an example
# HTML reports are automatically generated in target/test-reports/
# when using examples with HTML reporting enabled
Port Access Examples:
# See auto-port functionality in action
# Learn how to access container ports and URLs
# Container port and URL access
# User-specified port mappings
Container Management Patterns
Container Lifecycle with Hooks (NEW!)
Use before_each and after_each for per-test container management:
use ;
// Define container configuration
let mongo_container = new
.port
.env
.env
.name
.ready_timeout;
// before_each starts a fresh container for each test
before_each;
// after_each cleans up the container after each test
let mongo_container_clone = mongo_container.clone;
after_each;
// Tests use the container
test;
Benefits of Container Hooks:
- ✅ Fresh Containers: Each test gets a completely isolated container
- ✅ Automatic Cleanup: No risk of resource leaks
- ✅ Easy Configuration: Builder pattern for container setup
- ✅ Clean Separation: Test logic separate from container management
- ✅ Real-world Ready: Can easily be extended to use actual Docker API
For Docker Containers
Use Container Hooks (Recommended approach):
Refer to the Container Integration section above for the full example using before_each/after_each hooks.
Benefits of Container Hooks:
- Fine-grained control: Full control over container lifecycle
- Better isolation: Fresh container per test
- Automatic cleanup: Prevents resource leaks
- Flexible configuration: Custom setup/teardown logic
For Other Resources
Hooks work great for:
- Database connections
- File system operations
- Configuration management
- Test data setup/cleanup
Configuration
Set environment variables to configure test execution:
# Filter tests by name
# Skip tests with specific tags
# Set maximum concurrency
# Generate HTML report
# Skip hooks (for debugging)
IDE Support
RustRover and Similar IDEs
test_case! macros:
- ❌ No play buttons (macros aren't expanded during compilation)
- ✅ Tests are discoverable by
cargo test - ✅ Tests run correctly
Standard #[test] functions:
- ✅ Play buttons work normally
- ✅ Full IDE integration
Recommended Approach:
Framework Reliability:
The framework is fully functional. All features work correctly in test environments, and HTML reports are automatically organized in the target/test-reports/ directory for clean project structure.
Why This Approach?
- Familiar: Works exactly like Rust's built-in testing
- Discoverable: Tests are found by
cargo testautomatically - Compatible: Existing Rust tests work unchanged
- Enhanced: Adds powerful features without breaking existing patterns
- Flexible: Use framework features when needed, standard patterns when not
- Automatic: Hooks work automatically without manual setup
- Container-Ready: NEW! Built-in container lifecycle management with hooks
- Isolated: Each test gets fresh containers for true isolation
- Clean: Builder pattern for container configuration
- Docker Integration Ready: Can easily integrate with real Docker APIs
- Organized: HTML reports automatically stored in
target/test-reports/for clean project structure - Reliable: Fully functional framework with comprehensive test coverage
Contributing
Contributions are welcome! This framework aims to enhance Rust's testing capabilities while maintaining full compatibility with existing testing patterns.