Testing Guide¶
R Commerce includes comprehensive testing at multiple levels to ensure reliability and correctness.
Test Types¶
1. Unit Tests¶
Unit tests are located within each crate's source files, using Rust's built-in test framework:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_product_creation() {
let product = Product::new("Test Product", dec!(29.99));
assert_eq!(product.title, "Test Product");
assert_eq!(product.price, dec!(29.99));
}
}
Run unit tests:
2. Integration Tests¶
Integration tests are located in tests/ directories and test the full API:
# Run all integration tests
cargo test --test integration
# Run specific test
cargo test test_create_order
3. API Tests (MVP)¶
The MVP test suite validates core API functionality:
# Run MVP API tests
./scripts/test_api_mvp.sh
# Or run with curl directly
curl -s http://localhost:8080/health
curl -s http://localhost:8080/api/v1/products
4. End-to-End Tests¶
Full system tests including database operations:
# Run E2E test suite
./scripts/run_e2e_tests.sh
# Run complete system test
./scripts/test_complete_system.sh
Test Organization¶
crates/
├── rcommerce-core/
│ └── src/
│ └── services/
│ └── product_service.rs # Unit tests inline
├── rcommerce-api/
│ └── tests/
│ └── integration_tests.rs # Integration tests
└── rcommerce-cli/
└── tests/
└── cli_tests.rs # CLI tests
Writing Tests¶
Unit Test Example¶
// In your source file
pub fn calculate_tax(amount: Decimal, rate: Decimal) -> Decimal {
(amount * rate).round_dp(2)
}
#[cfg(test)]
mod tests {
use super::*;
use rust_decimal_macros::dec;
#[test]
fn test_calculate_tax() {
let amount = dec!(100.00);
let rate = dec!(0.10);
let tax = calculate_tax(amount, rate);
assert_eq!(tax, dec!(10.00));
}
#[test]
fn test_calculate_tax_rounding() {
let amount = dec!(99.99);
let rate = dec!(0.10);
let tax = calculate_tax(amount, rate);
assert_eq!(tax, dec!(10.00));
}
}
Integration Test Example¶
// tests/product_api_tests.rs
use reqwest::Client;
#[tokio::test]
async fn test_list_products() {
let client = Client::new();
let response = client
.get("http://localhost:8080/api/v1/products")
.send()
.await
.expect("Failed to send request");
assert!(response.status().is_success());
let products: Vec<Product> = response
.json()
.await
.expect("Failed to parse response");
assert!(!products.is_empty());
}
Async Test Example¶
#[tokio::test]
async fn test_async_operation() {
let result = async_operation().await;
assert!(result.is_ok());
}
Test Database¶
Tests use a separate database configuration:
# config.test.toml
[database]
db_type = "Postgres"
host = "localhost"
port = 5432
username = "rcommerce_test"
password = "testpass"
database = "rcommerce_test"
Run tests with test configuration:
Mocking¶
Use mockall for mocking dependencies:
use mockall::mock;
mock! {
PaymentGateway {}
#[async_trait]
impl PaymentGateway for PaymentGateway {
async fn process_payment(&self, amount: Decimal) -> Result<PaymentResult, Error>;
}
}
#[tokio::test]
async fn test_payment_processing() {
let mut mock = MockPaymentGateway::new();
mock.expect_process_payment()
.returning(|_| Ok(PaymentResult::Success));
let service = PaymentService::new(mock);
let result = service.process(dec!(100.00)).await;
assert!(result.is_ok());
}
Code Coverage¶
Generate test coverage reports:
# Install tarpaulin
cargo install cargo-tarpaulin
# Generate coverage report
cargo tarpaulin --out Html
# View report
open tarpaulin-report.html
Continuous Integration¶
Tests run automatically on: - Every pull request - Every push to main branch - Daily scheduled runs
See .github/workflows/ for CI configuration.
Test Best Practices¶
- Test behavior, not implementation - Tests should verify what code does, not how it does it
- One assertion per test - Keep tests focused and readable
- Use descriptive names - Test names should explain the scenario
- Arrange-Act-Assert - Structure tests clearly
- Clean up after tests - Don't leave test data in databases
Debugging Tests¶
# Run with output
cargo test -- --nocapture
# Run specific test with output
cargo test test_name -- --nocapture
# Run with debugger
rust-gdb --args cargo test test_name
Performance Testing¶
Load Testing¶
Use the included load testing script: