Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,48 @@ dmypy.json
**/model/

/data/milvus/db
/data/mysql/db
/data/mysql/db

# Testing
.pytest_cache/
.coverage
.coverage.*
htmlcov/
coverage.xml
*.py,cover
.hypothesis/
pytest_cache/
test-results/
.tox/
.nox/

# Claude
.claude/*

# Poetry
dist/

# Virtual environments
.venv/
venv/
ENV/
env/
.env

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Temporary files
*.tmp
*.bak
*.orig
tmp/
temp/
7,703 changes: 7,703 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
[tool.poetry]
name = "modelcache"
version = "0.1.0"
description = "A caching framework for machine learning models"
authors = ["ModelCache Team"]
readme = "README.md"
packages = [
{ include = "modelcache" },
{ include = "modelcache_mm" }
]

[tool.poetry.dependencies]
python = "^3.8"
cachetools = "5.3.1"
DBUtils = "1.4"
Flask = "3.0.0"
numpy = "1.24.4"
onnxruntime = "1.16.1"
openai = "0.28.1"
pymilvus = "2.3.1"
PyMySQL = "1.1.0"
Requests = "2.31.0"
torch = "2.1.1"
transformers = "4.38.2"
faiss-cpu = "1.7.4"
redis = "5.0.1"
modelscope = "1.14.0"
fastapi = "0.115.5"
uvicorn = "0.32.0"
chromadb = "0.5.23"
elasticsearch = "7.10.0"
snowflake-id = "1.0.2"

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
pytest-cov = "^5.0.0"
pytest-mock = "^3.14.0"

[tool.poetry.scripts]
test = "pytest:main"
tests = "pytest:main"

[tool.pytest.ini_options]
minversion = "8.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--cov=modelcache",
"--cov=modelcache_mm",
"--cov-branch",
"--cov-report=term-missing:skip-covered",
"--cov-report=html",
"--cov-report=xml",
"--cov-fail-under=80",
"-v"
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow running tests"
]

[tool.coverage.run]
source = ["modelcache", "modelcache_mm"]
omit = [
"*/tests/*",
"*/test_*",
"*/__pycache__/*",
"*/site-packages/*",
"*/distutils/*",
"*/venv/*",
"*/.venv/*"
]

[tool.coverage.report]
precision = 2
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if __name__ == .__main__.:",
"raise AssertionError",
"raise NotImplementedError",
"if TYPE_CHECKING:",
"if typing.TYPE_CHECKING:"
]

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Empty file added tests/__init__.py
Empty file.
218 changes: 218 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
"""
Shared pytest fixtures and configuration for modelcache tests.
"""
import os
import tempfile
import shutil
from pathlib import Path
from typing import Iterator, Dict, Any
import pytest
from unittest.mock import MagicMock


@pytest.fixture
def temp_dir() -> Iterator[Path]:
"""
Create a temporary directory for test files.

Yields:
Path: Path to the temporary directory
"""
temp_path = Path(tempfile.mkdtemp())
yield temp_path
# Cleanup after test
if temp_path.exists():
shutil.rmtree(temp_path)


@pytest.fixture
def mock_config() -> Dict[str, Any]:
"""
Provide a mock configuration dictionary for testing.

Returns:
Dict[str, Any]: Mock configuration
"""
return {
"cache_dir": "/tmp/test_cache",
"max_cache_size": 1000,
"ttl": 3600,
"embedding_model": "test-model",
"similarity_threshold": 0.8,
"vector_dimension": 768,
"batch_size": 32,
"database": {
"type": "memory",
"host": "localhost",
"port": 6379,
"password": None
}
}


@pytest.fixture
def mock_embedding():
"""
Mock embedding object for testing.

Returns:
MagicMock: Mock embedding with common methods
"""
mock = MagicMock()
mock.embed.return_value = [0.1] * 768 # Default 768-dim embedding
mock.embed_batch.return_value = [[0.1] * 768] * 10
mock.dimension = 768
mock.model_name = "test-embedding-model"
return mock


@pytest.fixture
def mock_cache_manager():
"""
Mock cache manager for testing.

Returns:
MagicMock: Mock cache manager with common methods
"""
mock = MagicMock()
mock.get.return_value = None
mock.set.return_value = True
mock.delete.return_value = True
mock.clear.return_value = True
mock.size.return_value = 0
return mock


@pytest.fixture
def sample_vector_data():
"""
Sample vector data for testing vector operations.

Returns:
Dict[str, Any]: Sample vector data
"""
return {
"id": "test_vector_001",
"vector": [0.1, 0.2, 0.3, 0.4, 0.5] * 153 + [0.6, 0.7, 0.8], # 768 dimensions
"metadata": {
"source": "test",
"timestamp": 1234567890,
"model": "test-model"
}
}


@pytest.fixture
def mock_redis_client():
"""
Mock Redis client for testing Redis-based operations.

Returns:
MagicMock: Mock Redis client
"""
mock = MagicMock()
mock.get.return_value = None
mock.set.return_value = True
mock.delete.return_value = 1
mock.exists.return_value = 0
mock.expire.return_value = True
mock.ttl.return_value = -2
return mock


@pytest.fixture
def mock_milvus_client():
"""
Mock Milvus client for testing vector database operations.

Returns:
MagicMock: Mock Milvus client
"""
mock = MagicMock()
mock.create_collection.return_value = True
mock.insert.return_value = MagicMock(primary_keys=[1, 2, 3])
mock.search.return_value = [[]]
mock.query.return_value = []
mock.delete.return_value = MagicMock(delete_count=1)
return mock


@pytest.fixture(autouse=True)
def reset_environment():
"""
Reset environment variables before each test.
"""
# Store original env vars
original_env = os.environ.copy()

# Set test environment variables
os.environ["MODELCACHE_ENV"] = "test"
os.environ["MODELCACHE_LOG_LEVEL"] = "DEBUG"

yield

# Restore original env vars
os.environ.clear()
os.environ.update(original_env)


@pytest.fixture
def sample_text_data():
"""
Sample text data for testing text processing.

Returns:
List[str]: List of sample texts
"""
return [
"This is a test sentence for modelcache.",
"Machine learning models need efficient caching.",
"Vector embeddings help with semantic search.",
"Testing is important for code quality.",
"PyTest makes testing in Python easier."
]


@pytest.fixture
def mock_http_response():
"""
Mock HTTP response for testing API calls.

Returns:
MagicMock: Mock response object
"""
mock = MagicMock()
mock.status_code = 200
mock.json.return_value = {"status": "success", "data": {}}
mock.text = '{"status": "success", "data": {}}'
mock.headers = {"Content-Type": "application/json"}
return mock


# Pytest configuration hooks
def pytest_configure(config):
"""
Configure pytest with custom settings.
"""
# Add custom markers description
config.addinivalue_line(
"markers", "unit: mark test as a unit test"
)
config.addinivalue_line(
"markers", "integration: mark test as an integration test"
)
config.addinivalue_line(
"markers", "slow: mark test as slow running"
)


def pytest_collection_modifyitems(config, items):
"""
Modify test collection to add markers based on test location.
"""
for item in items:
# Auto-mark tests based on their location
if "unit" in str(item.fspath):
item.add_marker(pytest.mark.unit)
elif "integration" in str(item.fspath):
item.add_marker(pytest.mark.integration)
Empty file added tests/integration/__init__.py
Empty file.
Loading