Files
KohakuHub/tests/README.md
2025-10-06 21:13:02 +08:00

412 lines
9.3 KiB
Markdown

# KohakuHub API Tests
Comprehensive test suite for KohakuHub API, validating HuggingFace Hub compatibility and custom endpoints.
## Test Strategy
This test suite uses a **dual-client approach** to ensure API correctness:
1. **HuggingFace Hub Client** (`huggingface_hub`): Tests HF API compatibility
2. **Custom HTTP Client** (`requests`): Tests custom endpoints and validates API schema
### Why Dual Testing?
- **HF Client tests**: Ensure compatibility with existing HF ecosystem
- **HTTP Client tests**: Validate custom endpoints and catch reverse-engineering errors
If HF client fails but HTTP client succeeds → Our reverse-engineering of HF API is wrong
If both fail → Our implementation is broken
If both succeed → ✅ Perfect compatibility
## Prerequisites
### 1. Deploy KohakuHub Server
Tests require a running KohakuHub instance (via docker-compose):
```bash
# From project root
cp docker-compose.example.yml docker-compose.yml
# Edit docker-compose.yml with your configuration
# Build and start
npm install --prefix ./src/kohaku-hub-ui
npm run build --prefix ./src/kohaku-hub-ui
docker-compose up -d --build
# Verify server is running
curl http://localhost:28080/api/version
```
**Important**: Tests connect to `http://localhost:28080` (nginx port) by default.
### 2. Install Test Dependencies
```bash
# Install test requirements
pip install pytest pytest-xdist requests huggingface_hub
# Or from project root
pip install -e ".[test]"
```
## Configuration
Tests are configured via environment variables or defaults in `config.py`:
| Variable | Default | Description |
|----------|---------|-------------|
| `TEST_ENDPOINT` | `http://localhost:28080` | KohakuHub API endpoint (use nginx port!) |
| `TEST_USERNAME` | `testuser` | Test user username |
| `TEST_EMAIL` | `test@example.com` | Test user email |
| `TEST_PASSWORD` | `testpass123` | Test user password |
| `TEST_ORG_NAME` | `testorg` | Test organization name |
| `TEST_REPO_PREFIX` | `test` | Prefix for test repositories |
| `TEST_TIMEOUT` | `30` | HTTP request timeout (seconds) |
| `TEST_CLEANUP` | `true` | Cleanup resources after tests |
### Example: Test Against Custom Endpoint
```bash
export TEST_ENDPOINT=http://my-server.com:28080
export TEST_USERNAME=myuser
export TEST_PASSWORD=mypass
pytest tests/
```
## Running Tests
### Run All Tests
```bash
# From project root
pytest tests/
# With verbose output
pytest tests/ -v
# With coverage
pytest tests/ --cov=kohakuhub --cov-report=html
```
### Run Specific Test Files
```bash
# Authentication tests only
pytest tests/test_auth.py -v
# Repository CRUD tests
pytest tests/test_repo_crud.py -v
# File operations
pytest tests/test_file_ops.py -v
# LFS operations
pytest tests/test_lfs.py -v
```
### Run Specific Tests
```bash
# Run single test
pytest tests/test_auth.py::TestAuthentication::test_version_check -v
# Run tests matching pattern
pytest tests/ -k "upload" -v
# Run tests with specific marker
pytest tests/ -m lfs -v
```
### Test Markers
Tests are marked for easier filtering:
```bash
# Run only LFS tests
pytest tests/ -m lfs
# Skip slow tests
pytest tests/ -m "not slow"
# Run tests for specific repo type
pytest tests/test_repo_crud.py::test_create_different_repo_types[model] -v
```
Available markers:
- `lfs` - Tests requiring LFS (large files >10MB)
- `slow` - Slow running tests (files >50MB)
- `repo_type(type)` - Tests for specific repository types
### Parallel Execution
```bash
# Run tests in parallel (4 workers)
pytest tests/ -n 4
# Auto-detect CPU cores
pytest tests/ -n auto
```
**Note**: Some tests may not be thread-safe. Use with caution.
## Test Structure
```
tests/
├── __init__.py # Package init
├── conftest.py # Pytest fixtures and configuration
├── config.py # Test configuration
├── base.py # Base test classes and utilities
├── test_auth.py # Authentication tests
├── test_repo_crud.py # Repository CRUD operations
├── test_file_ops.py # File upload/download/delete
├── test_lfs.py # Large file storage tests
└── README.md # This file
```
## Test Categories
### 1. Authentication Tests (`test_auth.py`)
- User registration
- Login/logout flow
- Session management
- API token creation/deletion
- Token-based authentication
- `whoami` endpoint
### 2. Repository CRUD Tests (`test_repo_crud.py`)
- Repository creation (model, dataset, space)
- Repository deletion
- Repository listing
- Repository info retrieval
- Repository move/rename
- Private repository handling
- Duplicate detection
### 3. File Operations Tests (`test_file_ops.py`)
- Small file upload/download (<10MB)
- Folder upload
- File deletion
- File listing (tree API)
- File metadata (HEAD request)
- Content integrity verification
- Commit messages
### 4. LFS Tests (`test_lfs.py`)
- Large file upload (>10MB)
- LFS batch API
- File size threshold (10MB boundary)
- LFS deduplication
- Mixed file sizes
- Content integrity for large files
- LFS metadata in tree API
## Fixtures
### Session-Scoped Fixtures
Created once per test session:
- `test_config`: Test configuration
- `http_client`: Unauthenticated HTTP client
- `api_token`: API token for test user
- `authenticated_http_client`: HTTP client with auth
- `hf_client`: HuggingFace Hub client wrapper
- `test_org`: Test organization
### Function-Scoped Fixtures
Created per test function:
- `temp_repo`: Temporary repository (auto-cleanup)
### Example Usage
```python
def test_something(hf_client, temp_repo):
"""Test with HF client and temporary repository."""
repo_id, repo_type = temp_repo
# Upload file
hf_client.upload_file(
path_or_fileobj="test.txt",
path_in_repo="test.txt",
repo_id=repo_id,
repo_type=repo_type,
)
# Repository will be cleaned up automatically
```
## Debugging
### Enable Verbose Logging
```bash
# Pytest verbose mode
pytest tests/ -vv
# Show print statements
pytest tests/ -s
# Show local variables on failure
pytest tests/ -l
```
### Run Failed Tests Only
```bash
# Run last failed tests
pytest tests/ --lf
# Run failed first, then others
pytest tests/ --ff
```
### Stop on First Failure
```bash
pytest tests/ -x
```
### Interactive Debugging
```bash
# Drop into debugger on failure
pytest tests/ --pdb
# Drop into debugger on first failure
pytest tests/ -x --pdb
```
## Common Issues
### 1. Connection Refused
**Problem**: `ConnectionRefusedError` or `Connection refused to localhost:28080`
**Solution**: Ensure KohakuHub is running:
```bash
docker-compose ps
curl http://localhost:28080/api/version
```
### 2. Wrong Port (48888)
**Problem**: Tests connecting to backend port instead of nginx
**Solution**: Use `TEST_ENDPOINT=http://localhost:28080` (nginx port)
### 3. Authentication Errors
**Problem**: `401 Unauthorized` errors
**Solution**: Check test user credentials or recreate test user:
```bash
# Delete old user from database if needed
docker-compose exec hub-api python -c "from kohakuhub.db import User; User.delete().where(User.username == 'testuser').execute()"
```
### 4. File Permission Errors
**Problem**: Cannot create temporary files
**Solution**: Check disk space and permissions for temp directory
### 5. LFS Upload Failures
**Problem**: Large file uploads timing out
**Solution**:
- Increase `TEST_TIMEOUT` environment variable
- Check MinIO is running: `docker-compose ps minio`
- Verify S3 credentials in `docker-compose.yml`
## Cleanup
Tests automatically cleanup resources if `TEST_CLEANUP=true` (default):
- Temporary repositories are deleted
- Temporary files are removed
- API tokens are revoked (optional)
### Manual Cleanup
If tests fail and leave resources:
```bash
# List test repositories
curl http://localhost:28080/api/models?author=testuser
# Delete manually via API
curl -X DELETE http://localhost:28080/api/repos/delete \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type": "model", "name": "test-repo-name"}'
# Or use kohub-cli
kohub-cli repo delete testuser/test-repo-name --type model
```
## Continuous Integration
### GitHub Actions Example
```yaml
name: API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install pytest requests huggingface_hub
- name: Start KohakuHub
run: |
cp docker-compose.example.yml docker-compose.yml
npm install --prefix ./src/kohaku-hub-ui
npm run build --prefix ./src/kohaku-hub-ui
docker-compose up -d --build
sleep 30 # Wait for services to start
- name: Run tests
run: pytest tests/ -v
- name: Stop services
run: docker-compose down
```
## Contributing
When adding new tests:
1. Follow existing patterns in test files
2. Use both HF client and HTTP client where applicable
3. Add appropriate markers (`@pytest.mark.lfs`, etc.)
4. Ensure cleanup in teardown or use fixtures
5. Document test purpose in docstring
6. Update this README if adding new test categories
## Support
- **Issues**: https://github.com/KohakuBlueleaf/KohakuHub/issues
- **Discord**: https://discord.gg/xWYrkyvJ2s
- **Documentation**: `../docs/`