mirror of https://github.com/buster-so/buster.git
122 lines
3.6 KiB
Plaintext
122 lines
3.6 KiB
Plaintext
|
---
|
||
|
description: This is designed to help understand how to do testing in this project.
|
||
|
globs: src/*
|
||
|
---
|
||
|
# Testing Rules and Best Practices
|
||
|
|
||
|
## General Testing Guidelines
|
||
|
- All tests must be async and use tokio test framework
|
||
|
- Tests should be well-documented with clear test case descriptions and expected outputs
|
||
|
- Each test should focus on testing a single piece of functionality
|
||
|
- Tests should be independent and not rely on the state of other tests
|
||
|
- Use meaningful test names that describe what is being tested
|
||
|
|
||
|
## Unit Tests
|
||
|
- Unit tests should be inline with the code they are testing using `#[cfg(test)]` modules
|
||
|
- Each public function should have corresponding unit tests
|
||
|
- Mock external dependencies using mockito for HTTP calls
|
||
|
- Use `mockito::Server::new_async()` instead of `mockito::Server::new()`
|
||
|
- Test both success and error cases
|
||
|
- Test edge cases and boundary conditions
|
||
|
|
||
|
## Integration Tests
|
||
|
- Integration tests should be placed in the `/tests` directory
|
||
|
- Organize integration tests to mirror the main codebase structure
|
||
|
- Each major feature/resource should have its own test file
|
||
|
- Test the interaction between multiple components
|
||
|
- Use real dependencies when possible, mock only what's necessary
|
||
|
- Include end-to-end workflow tests
|
||
|
|
||
|
## Test Structure
|
||
|
```rust
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
use mockito;
|
||
|
use tokio;
|
||
|
|
||
|
// Optional: Setup function for common test initialization
|
||
|
async fn setup() -> TestContext {
|
||
|
// Setup code here
|
||
|
}
|
||
|
|
||
|
#[tokio::test]
|
||
|
async fn test_name() {
|
||
|
// Test case description in comments
|
||
|
// Expected output in comments
|
||
|
|
||
|
// Arrange
|
||
|
// Setup test data and dependencies
|
||
|
|
||
|
// Act
|
||
|
// Execute the function being tested
|
||
|
|
||
|
// Assert
|
||
|
// Verify the results
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Mocking Guidelines
|
||
|
- Use mockito for HTTP service mocks
|
||
|
- Create mock responses that match real API responses
|
||
|
- Include both successful and error responses in mocks
|
||
|
- Clean up mocks after tests complete
|
||
|
|
||
|
## Error Testing
|
||
|
- Test error conditions and error handling
|
||
|
- Verify error messages and error types
|
||
|
- Test timeout scenarios
|
||
|
- Test connection failures
|
||
|
- Test invalid input handling
|
||
|
|
||
|
## Database Testing
|
||
|
- Use a separate test database for integration tests
|
||
|
- Clean up test data after tests complete
|
||
|
- Test database transactions and rollbacks
|
||
|
- Test database connection error handling
|
||
|
|
||
|
## Test Output
|
||
|
- Tests should provide clear error messages
|
||
|
- Use descriptive assert messages
|
||
|
- Print relevant debug information in test failures
|
||
|
- Log test execution progress for long-running tests
|
||
|
|
||
|
## CI/CD Considerations
|
||
|
- All tests must pass in CI environment
|
||
|
- Tests should be reproducible
|
||
|
- Tests should not have external dependencies that could fail CI
|
||
|
- Test execution time should be reasonable
|
||
|
|
||
|
## Example Test
|
||
|
```rust
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
use mockito;
|
||
|
use tokio;
|
||
|
|
||
|
#[tokio::test]
|
||
|
async fn test_api_call_success() {
|
||
|
// Test case: Successful API call returns expected response
|
||
|
// Expected: Response contains user data with status 200
|
||
|
|
||
|
let mut server = mockito::Server::new_async().await;
|
||
|
|
||
|
let mock = server
|
||
|
.mock("GET", "/api/user")
|
||
|
.match_header("authorization", "Bearer test-token")
|
||
|
.with_status(200)
|
||
|
.with_body(r#"{"id": "123", "name": "Test User"}"#)
|
||
|
.create();
|
||
|
|
||
|
let client = ApiClient::new(server.url());
|
||
|
let response = client.get_user().await.unwrap();
|
||
|
|
||
|
assert_eq!(response.id, "123");
|
||
|
assert_eq!(response.name, "Test User");
|
||
|
|
||
|
mock.assert();
|
||
|
}
|
||
|
}
|
||
|
```
|