mirror of
https://github.com/KohakuBlueleaf/KohakuHub.git
synced 2026-05-02 10:27:48 -05:00
412 lines
9.3 KiB
Markdown
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/`
|