Adding vendor api tests

This commit is contained in:
2025-11-21 23:16:21 +01:00
parent 6ad308e250
commit 2532a977c1
13 changed files with 1908 additions and 0 deletions

View File

@@ -0,0 +1,426 @@
# Test Structure
## Overview
The integration test suite is organized to mirror the API code structure, providing clear mapping between code and tests for better maintainability, discoverability, and team collaboration.
## Directory Structure
```
tests/integration/api/v1/
├── admin/ # Admin API tests
│ ├── __init__.py
│ └── README.md
├── vendor/ # Vendor API tests
│ ├── __init__.py
│ ├── README.md
│ ├── test_authentication.py # Authentication tests
│ └── test_dashboard.py # Dashboard tests
├── public/ # Public API tests
│ ├── __init__.py
│ └── README.md
└── shared/ # Shared/common tests
├── __init__.py
└── README.md
```
## Structure Mapping
The test structure directly mirrors the API code structure:
```
app/api/v1/admin/ → tests/integration/api/v1/admin/
app/api/v1/vendor/ → tests/integration/api/v1/vendor/
app/api/v1/public/ → tests/integration/api/v1/public/
app/api/v1/shared/ → tests/integration/api/v1/shared/
```
### Benefits
#### 1. Easy Discoverability
Finding tests is straightforward:
```bash
# Looking for vendor product tests?
ls tests/integration/api/v1/vendor/test_products.py
# Looking for admin user tests?
ls tests/integration/api/v1/admin/test_users.py
```
#### 2. Clear Code-to-Test Mapping
```
Code change: app/api/v1/vendor/products.py
Test location: tests/integration/api/v1/vendor/test_products.py
↑ 1:1 mapping!
```
#### 3. Faster Testing
Run tests for specific areas without complex filters:
```bash
# Test only vendor endpoints
pytest tests/integration/api/v1/vendor/ -v
# Test only admin endpoints
pytest tests/integration/api/v1/admin/ -v
```
#### 4. Better Code Reviews
Changes are grouped logically:
```
Pull Request:
Changed files:
app/api/v1/vendor/products.py # Code
tests/integration/api/v1/vendor/test_products.py # Test
↑ Easy to verify
```
#### 5. Team Collaboration
Different teams can work in parallel with fewer conflicts:
```
Admin Team: works in tests/integration/api/v1/admin/
Vendor Team: works in tests/integration/api/v1/vendor/
Public Team: works in tests/integration/api/v1/public/
```
## Running Tests
### By Area
```bash
# All vendor tests
pytest tests/integration/api/v1/vendor/ -v
# All admin tests
pytest tests/integration/api/v1/admin/ -v
# All public tests
pytest tests/integration/api/v1/public/ -v
# All shared tests
pytest tests/integration/api/v1/shared/ -v
```
### Specific Test Files
```bash
# Run specific test file
pytest tests/integration/api/v1/vendor/test_authentication.py -v
# Run specific test class
pytest tests/integration/api/v1/vendor/test_authentication.py::TestVendorAPIAuthentication -v
# Run specific test
pytest tests/integration/api/v1/vendor/test_authentication.py::TestVendorAPIAuthentication::test_vendor_auth_me_success -v
```
### With Coverage
```bash
# Vendor API coverage
pytest tests/integration/api/v1/vendor/ \
--cov=app/api/v1/vendor \
--cov-report=html
# View coverage report
open htmlcov/index.html
```
### Using Markers
All tests use pytest markers for flexible filtering:
```bash
# All vendor tests
pytest -m vendor -v
# Vendor API tests only
pytest -m "vendor and api" -v
# Vendor authentication tests
pytest -m "vendor and auth" -v
```
## Naming Conventions
### Test Files
- **Pattern**: `test_<endpoint_name>.py`
- **Examples**:
- `test_products.py` - Tests for products endpoints
- `test_authentication.py` - Tests for authentication
- `test_dashboard.py` - Tests for dashboard endpoints
### Test Classes
- **Pattern**: `Test<Area><Feature>API`
- **Examples**:
```python
class TestVendorProductAPI: # Vendor product endpoints
class TestAdminUserAPI: # Admin user endpoints
class TestPublicCatalogAPI: # Public catalog endpoints
```
### Test Functions
- **Pattern**: `test_<action>_<scenario>`
- **Examples**:
```python
def test_list_products_success(self):
def test_create_product_without_auth(self):
def test_update_product_invalid_data(self):
def test_delete_product_not_found(self):
```
## Best Practices
### 1. Mirror API Structure
Always create test files that mirror the API code structure:
```python
# API Code
app/api/v1/vendor/products.py
# Test File
tests/integration/api/v1/vendor/test_products.py
```
### 2. One Test File Per API Module
Keep tests focused:
- Each API module gets its own test file
- Easy to find and maintain
- Clear responsibility
### 3. Descriptive Test Names
Use clear, descriptive names:
```python
# Good ✅
class TestVendorProductAPI:
def test_list_products_success(self):
def test_create_product_without_auth(self):
def test_update_product_with_invalid_data(self):
# Avoid ❌
class TestProducts:
def test_api(self):
def test_endpoint(self):
```
### 4. Appropriate Markers
Mark tests appropriately:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorProductAPI:
pass
```
### 5. Test Both Success and Failure
Cover all scenarios:
```python
class TestVendorProductAPI:
# Success cases
def test_list_products_success(self):
def test_create_product_success(self):
# Failure cases
def test_list_products_without_auth(self):
def test_create_product_invalid_data(self):
def test_create_product_as_admin_user(self):
```
## Test Areas
### Admin Tests (`admin/`)
Tests for admin-only endpoints at `/api/v1/admin/*`:
- User management
- System configuration
- Analytics and reporting
- Vendor approval workflows
**Requirements:**
- Admin user authentication
- Admin-specific permissions
- Cross-vendor data access
### Vendor Tests (`vendor/`)
Tests for vendor endpoints at `/api/v1/vendor/*`:
- Product management
- Order processing
- Customer management
- Analytics and stats
- Team management
**Requirements:**
- Vendor user authentication
- Vendor context isolation
- VendorUser associations
See [Vendor API Testing Guide](vendor-api-testing.md) for details.
### Public Tests (`public/`)
Tests for public endpoints at `/api/v1/public/*`:
- Product catalog browsing
- Public vendor profiles
- Search functionality
**Requirements:**
- No authentication required
- Rate limiting tests
- Public data only
### Shared Tests (`shared/`)
Tests for shared/common functionality:
- Authentication endpoints
- Pagination utilities
- Filtering utilities
- Common error handling
**Requirements:**
- Work across all user types
- Consistent behavior
- Proper error handling
## Migration Status
### Completed ✅
| Area | Files | Tests | Status |
|------|-------|-------|--------|
| Vendor Authentication | `vendor/test_authentication.py` | 30+ | ✅ Complete |
| Vendor Dashboard | `vendor/test_dashboard.py` | 12 | ✅ Complete |
### Pending ⚠️
| Legacy File | New Location | Priority |
|-------------|--------------|----------|
| `test_vendor_endpoints.py` | Split into `vendor/test_*.py` | High |
| `test_admin_endpoints.py` | Split into `admin/test_*.py` | High |
| `test_auth_endpoints.py` | `shared/test_auth.py` | Medium |
| `test_marketplace_*.py` | `vendor/test_marketplace_*.py` | Medium |
| `test_inventory_endpoints.py` | `vendor/test_inventory.py` | Medium |
## Adding New Tests
When adding new integration tests:
1. **Identify the API area** (admin/vendor/public/shared)
2. **Create test file in appropriate folder**
3. **Follow naming conventions**
4. **Add appropriate markers**
5. **Test both success and failure cases**
6. **Update coverage reports**
### Example: Adding Vendor Products Tests
```bash
# 1. Create test file
touch tests/integration/api/v1/vendor/test_products.py
```
```python
# 2. Write tests following conventions
import pytest
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorProductAPI:
"""Tests for vendor product management endpoints"""
def test_list_products_success(self, client, vendor_user_headers):
"""Test listing products with authentication"""
response = client.get(
"/api/v1/vendor/products",
headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
assert "products" in data
assert "total" in data
def test_list_products_without_auth(self, client):
"""Test listing products requires authentication"""
response = client.get("/api/v1/vendor/products")
assert response.status_code == 401
def test_create_product_success(self, client, vendor_user_headers):
"""Test creating product with valid data"""
response = client.post(
"/api/v1/vendor/products",
headers=vendor_user_headers,
json={
"name": "Test Product",
"price": 29.99,
"description": "Test description"
}
)
assert response.status_code == 201
```
```bash
# 3. Run tests
pytest tests/integration/api/v1/vendor/test_products.py -v
# 4. Check coverage
pytest tests/integration/api/v1/vendor/test_products.py \
--cov=app/api/v1/vendor/products \
--cov-report=html
```
## Troubleshooting
### Tests Not Discovered
**Problem**: `pytest` doesn't find tests
**Solutions**:
- Ensure `__init__.py` exists in test directory
- Check file naming: `test_*.py` or `*_test.py`
- Verify test functions start with `test_`
- Check pytest collection with: `pytest --collect-only`
### Import Errors
**Problem**: Fixtures not found
**Solutions**:
- Check `pytest_plugins` in `tests/conftest.py`
- Use absolute imports: `from tests.fixtures.auth_fixtures import ...`
- Verify fixture files are in correct location
### Coverage Not Working
**Problem**: Coverage report shows 0%
**Solutions**:
- Specify correct source path: `--cov=app/api/v1/vendor`
- Check test actually exercises the code
- Verify coverage config in `pyproject.toml` or `.coveragerc`
## See Also
- [Vendor API Testing Guide](vendor-api-testing.md) - Comprehensive vendor testing documentation
- [Testing Guide](testing-guide.md) - Overall testing strategy
- [Test Maintenance](test-maintenance.md) - Maintaining test quality

View File

@@ -0,0 +1,670 @@
# Vendor API Testing Guide
## Overview
Comprehensive integration test suite for vendor API endpoints that use `get_current_vendor_api` for authentication.
## Test Coverage
### Current Coverage
| Endpoint | Auth Tests | Functionality Tests | Coverage |
|----------|-----------|-------------------|----------|
| `/api/v1/vendor/auth/me` | ✅ Complete | ✅ Complete | 100% |
| `/api/v1/vendor/dashboard/stats` | ✅ Complete | ✅ Complete | 100% |
| `/api/v1/vendor/profile` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/settings` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/products` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/orders` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/customers` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/inventory` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/marketplace` | ✅ Auth only | ⚠️ Pending | 50% |
| `/api/v1/vendor/analytics` | ✅ Auth only | ⚠️ Pending | 50% |
**Total Tests Created**: 58+ tests
**Tests in Structure**: 28 tests (authentication + dashboard)
## Test Files
### Location
```
tests/integration/api/v1/vendor/
├── __init__.py
├── test_authentication.py # 30+ authentication tests
└── test_dashboard.py # 12 dashboard tests
```
### 1. Authentication Tests
**File**: `tests/integration/api/v1/vendor/test_authentication.py`
**Purpose**: Verify authentication and authorization for vendor API endpoints
#### Test Classes
##### `TestVendorAPIAuthentication`
Core authentication tests for `get_current_vendor_api`:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
@pytest.mark.auth
class TestVendorAPIAuthentication:
"""Test authentication for vendor API endpoints"""
```
**Tests**:
-`test_vendor_auth_me_success` - Valid vendor token accepted
-`test_vendor_auth_me_no_token` - Missing token rejected (401)
-`test_vendor_auth_me_invalid_token` - Invalid token rejected (401)
-`test_vendor_auth_me_expired_token` - Expired token rejected (401)
-`test_vendor_auth_me_malformed_header` - Malformed header rejected (401)
-`test_admin_user_blocked` - Admin users blocked (403)
-`test_regular_user_blocked` - Regular users blocked (403)
-`test_inactive_vendor_user_rejected` - Inactive users rejected (401)
-`test_csrf_protection_header_required` - Requires Authorization header
-`test_csrf_protection_cookie_only_rejected` - Cookie-only auth rejected
-`test_concurrent_requests` - Concurrent requests with same token
-`test_token_with_missing_claims` - Token with missing claims rejected
-`test_empty_authorization_header` - Empty header rejected
##### `TestVendorAPIConsistency`
Consistency checks across all vendor endpoints:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorAPIConsistency:
"""Test that all vendor API endpoints have consistent auth behavior"""
```
**Tests**:
- ✅ Verifies all vendor endpoints require authentication
- ✅ Ensures consistent error responses
- ✅ Checks CSRF protection across all endpoints
#### What's Tested
**Authentication (`get_current_vendor_api`)**:
- [x] Requires Authorization header (not cookies)
- [x] Validates JWT token format
- [x] Checks token expiration
- [x] Verifies token signature
- [x] Extracts user from token
- [x] Verifies user exists and is active
**Authorization**:
- [x] Blocks admin users (403)
- [x] Blocks regular users (403)
- [x] Accepts vendor users (200/404)
- [x] Checks vendor-role requirement
**CSRF Protection**:
- [x] API endpoints require header auth
- [x] Cookie-only auth rejected
- [x] Consistent across all endpoints
**Vendor Context**:
- [x] Vendor association required
- [x] Inactive vendors rejected
- [x] Vendor data isolation
- [x] VendorUser relationship working
### 2. Dashboard Tests
**File**: `tests/integration/api/v1/vendor/test_dashboard.py`
**Purpose**: Test vendor dashboard statistics endpoint
#### Test Class
##### `TestVendorDashboardAPI`
Dashboard functionality tests:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorDashboardAPI:
"""Test vendor dashboard stats endpoint"""
```
**Tests**:
-`test_dashboard_stats_structure` - Correct response structure
-`test_dashboard_stats_vendor_isolation` - Only shows vendor's data
-`test_dashboard_stats_empty_vendor` - Empty vendor returns zeros
-`test_dashboard_stats_product_counts` - Accurate product counts
-`test_dashboard_stats_order_counts` - Accurate order counts
-`test_dashboard_stats_customer_counts` - Accurate customer counts
-`test_dashboard_stats_revenue` - Accurate revenue calculations
-`test_dashboard_stats_no_vendor_association` - User not associated (403)
-`test_dashboard_stats_inactive_vendor` - Inactive vendor (404)
-`test_dashboard_stats_performance` - Response time < 2 seconds
-`test_dashboard_stats_multiple_requests` - Consistency across requests
-`test_dashboard_stats_data_types` - Correct data types
#### What's Tested
**Data Structure**:
- [x] Correct response structure
- [x] All required fields present
- [x] Correct data types
**Business Logic**:
- [x] Vendor isolation (only shows own data)
- [x] Empty vendor returns zeros
- [x] Accurate product counts (total, active)
- [x] Orders, customers, revenue stats
**Error Cases**:
- [x] User not associated with vendor (403)
- [x] Inactive vendor (404)
- [x] Missing vendor association
**Performance**:
- [x] Response time < 2 seconds
- [x] Multiple requests consistency
- [x] Caching behavior
## Test Fixtures
### Authentication Fixtures
Located in `tests/fixtures/auth_fixtures.py`:
#### `test_vendor_user`
Creates a user with `role="vendor"`:
```python
@pytest.fixture
def test_vendor_user(db, auth_manager):
"""Create a test vendor user with unique username"""
unique_id = str(uuid.uuid4())[:8]
hashed_password = auth_manager.hash_password("vendorpass123")
user = User(
email=f"vendor_{unique_id}@example.com",
username=f"vendoruser_{unique_id}",
hashed_password=hashed_password,
role="vendor",
is_active=True,
)
db.add(user)
db.commit()
db.refresh(user)
return user
```
**Usage**: Base fixture for vendor-role users
#### `vendor_user_headers`
Returns Authorization headers for vendor user:
```python
@pytest.fixture
def vendor_user_headers(client, test_vendor_user):
"""Get authentication headers for vendor user"""
response = client.post(
"/api/v1/auth/login",
json={
"username": test_vendor_user.username,
"password": "vendorpass123"
},
)
token = response.json()["access_token"]
return {"Authorization": f"Bearer {token}"}
```
**Usage**: Use for authenticated vendor API requests
**Format**: `{"Authorization": "Bearer <token>"}`
### Vendor Fixtures
Located in `tests/fixtures/vendor_fixtures.py`:
#### `test_vendor_with_vendor_user`
Creates a vendor owned by vendor user:
```python
@pytest.fixture
def test_vendor_with_vendor_user(db, test_vendor_user):
"""Create a vendor owned by a vendor user"""
vendor = Vendor(
vendor_code=f"VENDORAPI_{unique_id}",
subdomain=f"vendorapi{unique_id.lower()}",
name=f"Vendor API Test {unique_id}",
owner_user_id=test_vendor_user.id,
is_active=True,
is_verified=True,
)
db.add(vendor)
db.commit()
# Create VendorUser association
vendor_user = VendorUser(
vendor_id=vendor.id,
user_id=test_vendor_user.id,
is_owner=True,
is_active=True,
)
db.add(vendor_user)
db.commit()
return vendor
```
**Usage**: Fully configured vendor for API testing with VendorUser association
## Running Tests
### All Vendor Tests
```bash
# Run all vendor integration tests
pytest tests/integration/api/v1/vendor/ -v
# With output
pytest tests/integration/api/v1/vendor/ -v -s
```
### Specific Test Files
```bash
# Authentication tests only
pytest tests/integration/api/v1/vendor/test_authentication.py -v
# Dashboard tests only
pytest tests/integration/api/v1/vendor/test_dashboard.py -v
```
### Specific Test Classes
```bash
# Authentication tests class
pytest tests/integration/api/v1/vendor/test_authentication.py::TestVendorAPIAuthentication -v
# Dashboard tests class
pytest tests/integration/api/v1/vendor/test_dashboard.py::TestVendorDashboardAPI -v
```
### Specific Tests
```bash
# Single authentication test
pytest tests/integration/api/v1/vendor/test_authentication.py::TestVendorAPIAuthentication::test_vendor_auth_me_success -v
# Single dashboard test
pytest tests/integration/api/v1/vendor/test_dashboard.py::TestVendorDashboardAPI::test_dashboard_stats_structure -v
```
### With Coverage
```bash
# Coverage for all vendor tests
pytest tests/integration/api/v1/vendor/ \
--cov=app/api/v1/vendor \
--cov-report=html
# View coverage report
open htmlcov/index.html
# Coverage for specific endpoint
pytest tests/integration/api/v1/vendor/test_dashboard.py \
--cov=app/api/v1/vendor/dashboard \
--cov-report=term-missing
```
### Using Markers
```bash
# All vendor tests
pytest -m vendor -v
# Vendor API tests only
pytest -m "vendor and api" -v
# Vendor authentication tests
pytest -m "vendor and auth" -v
```
## Test Examples
### Basic Authenticated Request
```python
def test_vendor_endpoint(client, vendor_user_headers):
"""Test vendor endpoint with authentication"""
response = client.get(
"/api/v1/vendor/some-endpoint",
headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
assert "expected_field" in data
```
### Test with Vendor Context
```python
def test_with_vendor_data(
client,
vendor_user_headers,
test_vendor_with_vendor_user,
db
):
"""Test with specific vendor data"""
vendor = test_vendor_with_vendor_user
# Create test data for this vendor
product = Product(
vendor_id=vendor.id,
name="Test Product",
price=29.99
)
db.add(product)
db.commit()
response = client.get(
"/api/v1/vendor/products",
headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
assert len(data["products"]) == 1
```
### Test Negative Cases
```python
def test_rejects_non_vendor(client, auth_headers):
"""Test endpoint rejects non-vendor users"""
response = client.get(
"/api/v1/vendor/endpoint",
headers=auth_headers # Regular user token
)
assert response.status_code == 403
data = response.json()
assert data["detail"] == "This endpoint is only for vendor users"
```
### Test Authentication Failure
```python
def test_requires_authentication(client):
"""Test endpoint requires authentication"""
response = client.get("/api/v1/vendor/endpoint")
assert response.status_code == 401
data = response.json()
assert data["detail"] == "Not authenticated"
```
## Expanding Test Coverage
### Recommended Next Tests
#### 1. Vendor Products API
Create `tests/integration/api/v1/vendor/test_products.py`:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorProductsAPI:
"""Test vendor product management endpoints"""
def test_list_products(self, client, vendor_user_headers):
"""Test listing products with pagination"""
def test_create_product_from_marketplace(self, client, vendor_user_headers):
"""Test creating product from marketplace"""
def test_update_product(self, client, vendor_user_headers):
"""Test updating product details"""
def test_delete_product(self, client, vendor_user_headers):
"""Test deleting product"""
def test_toggle_product_active(self, client, vendor_user_headers):
"""Test toggling product active status"""
```
#### 2. Vendor Orders API
Create `tests/integration/api/v1/vendor/test_orders.py`:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorOrdersAPI:
"""Test vendor order management endpoints"""
def test_list_orders(self, client, vendor_user_headers):
"""Test listing orders with filters"""
def test_get_order_details(self, client, vendor_user_headers):
"""Test getting order details"""
def test_update_order_status(self, client, vendor_user_headers):
"""Test updating order status"""
def test_order_data_isolation(self, client, vendor_user_headers):
"""Test vendor can only see their orders"""
```
#### 3. Vendor Profile API
Create `tests/integration/api/v1/vendor/test_profile.py`:
```python
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorProfileAPI:
"""Test vendor profile endpoints"""
def test_get_profile(self, client, vendor_user_headers):
"""Test getting vendor profile"""
def test_update_profile(self, client, vendor_user_headers):
"""Test updating vendor profile"""
def test_profile_permissions(self, client, vendor_user_headers):
"""Test profile permission checks"""
```
## Troubleshooting
### Test Fails with 401 (Unauthorized)
**Problem**: Tests fail even with valid token
**Common Causes**:
- User doesn't have `role="vendor"`
- Token is expired
- Authorization header format incorrect
**Solutions**:
```python
# Verify user role
assert test_vendor_user.role == "vendor"
# Check token format
assert vendor_user_headers["Authorization"].startswith("Bearer ")
# Generate fresh token
response = client.post("/api/v1/auth/login", json={...})
```
### Test Fails with 403 (Forbidden)
**Problem**: "Not associated with vendor" error
**Common Causes**:
- `VendorUser` record doesn't exist
- Vendor is inactive
- User not linked to vendor
**Solutions**:
```python
# Use fixture that creates VendorUser
def test_example(
client,
vendor_user_headers,
test_vendor_with_vendor_user # ← Use this fixture
):
pass
# Or manually create VendorUser
vendor_user = VendorUser(
vendor_id=vendor.id,
user_id=test_vendor_user.id,
is_active=True
)
db.add(vendor_user)
db.commit()
```
### Test Fails with 404 (Not Found)
**Problem**: "Vendor not found" error
**Common Causes**:
- Vendor is inactive (`is_active=False`)
- Vendor doesn't exist
- Database not set up correctly
**Solutions**:
```python
# Verify vendor is active
assert vendor.is_active is True
# Verify vendor exists
vendor_in_db = db.query(Vendor).filter_by(id=vendor.id).first()
assert vendor_in_db is not None
```
### Import Errors for Fixtures
**Problem**: `fixture not found` errors
**Solutions**:
- Fixtures are auto-loaded via `conftest.py`
- Check `pytest_plugins` list in `tests/conftest.py`:
```python
pytest_plugins = [
"tests.fixtures.auth_fixtures",
"tests.fixtures.vendor_fixtures",
]
```
- Use absolute imports in test files
## Best Practices
### 1. Use Appropriate Fixtures
```python
# ✅ Good - Use specific fixtures
def test_vendor_endpoint(client, vendor_user_headers, test_vendor_with_vendor_user):
pass
# ❌ Avoid - Manual setup
def test_vendor_endpoint(client):
user = User(role="vendor", ...) # Don't do this
db.add(user)
```
### 2. Test Isolation
Each test should be independent:
```python
# ✅ Good - Test creates its own data
def test_product_list(client, vendor_user_headers, db):
product = Product(...)
db.add(product)
db.commit()
response = client.get("/api/v1/vendor/products", headers=vendor_user_headers)
# Test assertions
# ❌ Avoid - Depending on other tests
def test_product_list(client, vendor_user_headers):
# Assumes data from previous test
response = client.get("/api/v1/vendor/products", headers=vendor_user_headers)
```
### 3. Comprehensive Assertions
Check multiple aspects:
```python
def test_dashboard_stats(client, vendor_user_headers):
response = client.get(
"/api/v1/vendor/dashboard/stats",
headers=vendor_user_headers
)
# Check status
assert response.status_code == 200
# Check structure
data = response.json()
assert "products" in data
assert "orders" in data
# Check data types
assert isinstance(data["products"]["total"], int)
# Check business logic
assert data["products"]["total"] >= 0
```
### 4. Use Markers Consistently
```python
@pytest.mark.integration # Always for integration tests
@pytest.mark.api # For API endpoint tests
@pytest.mark.vendor # For vendor-specific tests
class TestVendorAPI:
pass
```
### 5. Clear Test Names
```python
# ✅ Good - Descriptive names
def test_list_products_returns_paginated_results(self):
def test_create_product_requires_authentication(self):
def test_update_product_rejects_invalid_price(self):
# ❌ Avoid - Vague names
def test_products(self):
def test_api_1(self):
def test_endpoint(self):
```
## See Also
- [Test Structure](test-structure.md) - Overall test organization
- [Testing Guide](testing-guide.md) - Testing strategy and best practices
- [Test Maintenance](test-maintenance.md) - Maintaining test quality
- [API Authentication](../api/authentication.md) - Authentication documentation
- [RBAC](../api/RBAC.md) - Role-based access control