testing · git:20260915.d1860cb · 2026-09-15 · sha256 70e9d5b7a1ce8488
testing git:20260915.d1860cbA
Immutable. This exact content never changes and is served at /api/v1/blob/70e9d5b7a1ce8488.
---
description: Test writing rules
globs: tests/**/*.py
alwaysApply: true
---
# Test Writing Rules
## General Principles
1. **Coverage**: Aim for code coverage >90%
2. **One class at a time**: When creating new class, write tests for it immediately
3. **Isolation**: Each test must be independent
4. **Readability**: Test names should describe what is being tested
## Test Structure
### Naming
- Test file: `test_<module_name>.py`
- Test class: `Test<ClassName>`
- Test method: `test_<what_is_tested>`
### Test Class Structure
```python
class TestSearchController:
"""Test suite for SearchController."""
@pytest.fixture
def search_controller(self, realistic_data_path):
"""SearchController loaded with realistic test data."""
return SearchController(str(realistic_data_path))
def test_some_functionality(self, search_controller):
"""Test description."""
# Arrange
# Act
# Assert
```
## Test Types
### Unit Tests
- Test individual modules in isolation
- Use mocks for dependencies
- Fast and deterministic
### Integration Tests
- Test interaction between modules
- Use real data from `tests/test_data/`
- Test through HTTP API using `TestClient`
### Performance Tests
- Check hash index performance
- Ensure search works in O(1)
### Edge-case Tests
- Test edge cases
- Test error handling
- Test input validation
## Fixtures
### Using Fixtures
- Create fixtures for data preparation
- Use `@pytest.fixture` for reusable data
- Use `scope="function"` for test isolation
### Test Data
- Store test Excel files in `tests/test_data/`
- Use realistic data for integration tests
- Create minimal data for unit tests
## Test Examples
### Unit Test for Class
```python
def test_get_value_global(self, search_controller):
"""Test global value search."""
result = search_controller.get_value("custom_key")
assert isinstance(result, QueryResult)
assert result.success
assert result.value == 1.2
assert result.error is None
```
### Integration Test for API
```python
def test_simple_search_success(self, client):
"""Test successful simple search."""
request_data = {
"name": "Demo",
"key": "Key"
}
response = client.post("/search", json=request_data)
assert response.status_code == 200
data = response.json()
assert data["value"] == 1.2
```
### Error Handling Test
```python
def test_get_value_not_found(self, search_controller):
"""Test search value with non-existent data."""
result = search_controller.get_value("NonExistentKey")
assert isinstance(result, QueryResult)
assert not result.success
assert result.value is None
assert result.error is not None
assert "not found" in result.error.lower()
```
## Assertions
### What to Check
- Return value types
- Operation success (`success` flag)
- Result values
- Error messages
- HTTP status codes (for API tests)
### Using assert
- Use clear assert messages
- Check multiple aspects of result
- Use `isinstance()` for type checking
## Edge Case Testing
### Empty Data
- Empty responses
### Invalid Data
- Invalid types
- Invalid formats
## Running Tests
### All Tests
```bash
pytest tests/ -v
```
### With Coverage
```bash
pytest tests/ --cov=search_project --cov-report=term-missing
```
### Specific Test
```bash
pytest tests/test_search_controller.py::TestSearchController::test_get_value_global -v
```
## References
@pytest.ini
@code-style.mdc