diff --git a/coverage.xml b/coverage.xml index 8602f1e2..7e9bb22b 100644 --- a/coverage.xml +++ b/coverage.xml @@ -1,5 +1,5 @@ - + @@ -1985,7 +1985,7 @@ - + @@ -2052,7 +2052,7 @@ - + @@ -2093,72 +2093,72 @@ - + - - + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - + + + + - - - - - + + + + + - - - + + + - - - - - - - - - + + + + + + + + - - - + + + + - - - - - - + + + @@ -2228,7 +2228,7 @@ - + @@ -2261,8 +2261,8 @@ - - + + @@ -3230,7 +3230,7 @@ - + @@ -3254,7 +3254,7 @@ - + @@ -3377,17 +3377,17 @@ - + - + - + - + @@ -3411,7 +3411,7 @@ - + @@ -3433,82 +3433,104 @@ - - - - + + + - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + - - - + + + + + - + - + - - - - - + + + - - - - - - - + - - - - - - - + + + + + + + + + - - - + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -3566,38 +3588,37 @@ - + - + - - + + - - + + - + - + - - - + + + - - - - - - + + + + + @@ -3610,29 +3631,29 @@ + - - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - + + + + + + @@ -3652,9 +3673,9 @@ - - - + + + @@ -3677,393 +3698,443 @@ - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + - - - - - - + + + + + - - - - + + + + + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + - + - - + + - - + + - - - - - - - + + + + + + + + + + + + - + + - - - + - - - - + - - - + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + - - + + + - - - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - + + - - + + + - - - - - - + + + + + + - - + - - - - + + - - - - - + + + - - - - + + + - + + + + + + + - - - - - + + + + - - + + + + + - + + - - - - - - - - - + + + + + + - + - - - - + + + + + + - - - - + + + + + + + + + + - - - - - + + + - - - - - + + - - - + + + + - - - - - - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + + + - - + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4324,7 +4395,7 @@ - + @@ -4447,9 +4518,9 @@ - + - + @@ -4538,7 +4609,7 @@ - + @@ -4563,7 +4634,7 @@ - + @@ -5979,7 +6050,7 @@ - + @@ -5998,7 +6069,7 @@ - + @@ -6030,12 +6101,12 @@ - + - + @@ -6047,13 +6118,13 @@ - - - + + + - + @@ -6070,406 +6141,446 @@ - - - - - + + + - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - + - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + - - - - - - - - + + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -6490,12 +6601,12 @@ - + - - - + + + @@ -6504,7 +6615,7 @@ - + @@ -6512,7 +6623,7 @@ - + @@ -6614,7 +6725,7 @@ - + @@ -6623,29 +6734,29 @@ - - - - - - - + + + + + + + - - + + - + - - + + - + - - - + + + @@ -6821,7 +6932,7 @@ - + @@ -6832,51 +6943,53 @@ - - - - - - + + + + + + - + - - + + + - - - - - + + + + + + + - + - - - - + + + + - - + + - - - + + - + @@ -6911,188 +7024,205 @@ - + - - + + + - + - - - + - + + - - - - - + + + - + - - - + + + - + - - - - - - - - - - - - - - + + + + + + + - + - + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - + - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -7193,7 +7323,7 @@ - + @@ -7218,25 +7348,25 @@ - - - + + + - - + + - + - - + + - - - + + + @@ -7273,7 +7403,7 @@ - + @@ -7319,38 +7449,38 @@ - + - + - + - + - + - + - + - + - - - - - + + + + + - + - + @@ -7385,10 +7515,10 @@ - - - - + + + + @@ -10625,7 +10755,7 @@ - + @@ -10651,74 +10781,78 @@ - + - + - + - - - - + + + + - - + + - - - - - - + + + + + - + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/pyproject.toml b/pyproject.toml index 3ab974db..c99a7e5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -566,6 +566,7 @@ addopts = [ "--cov-report=html", "--cov-report=xml", "--cov-fail-under=80", + "--import-mode=importlib", ] testpaths = ["tests"] python_files = ["test_*.py", "*_test.py"] diff --git a/src/codeweaver/_version.py b/src/codeweaver/_version.py index 95ee65f2..049b3823 100644 --- a/src/codeweaver/_version.py +++ b/src/codeweaver/_version.py @@ -4,6 +4,6 @@ from typing import Final -__version__: Final[str] = "0.0.1rc295+gfc4f90a" +__version__: Final[str] = "0.0.1rc3+g76d9888" __all__ = ("__version__",) diff --git a/tests/benchmark/chunker/test_performance.py b/tests/benchmark/chunker/test_performance.py index 103a33bb..0b6dd0c8 100644 --- a/tests/benchmark/chunker/test_performance.py +++ b/tests/benchmark/chunker/test_performance.py @@ -23,6 +23,9 @@ from codeweaver.engine.chunker.selector import ChunkerSelector from codeweaver.providers.embedding.capabilities.base import EmbeddingModelCapabilities +pytestmark = [pytest.mark.benchmark, pytest.mark.performance, pytest.mark.slow] + + # Test data generators def generate_python_file(num_lines: int) -> str: diff --git a/tests/contract/test_memory_provider.py b/tests/contract/test_memory_provider.py index 0afeb199..3371ddd3 100644 --- a/tests/contract/test_memory_provider.py +++ b/tests/contract/test_memory_provider.py @@ -20,10 +20,10 @@ from codeweaver.core.spans import Span from codeweaver.providers.vector_stores.inmemory import MemoryVectorStore - pytestmark = pytest.mark.unit + @pytest.fixture def temp_persist_path(): """Provide temporary persistence path for testing.""" diff --git a/tests/contract/test_qdrant_provider.py b/tests/contract/test_qdrant_provider.py index f3b8980a..3eb3ac26 100644 --- a/tests/contract/test_qdrant_provider.py +++ b/tests/contract/test_qdrant_provider.py @@ -21,11 +21,12 @@ from codeweaver.core.spans import Span from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - -# Mark all tests in this module as requiring Qdrant pytestmark = [pytest.mark.integration, pytest.mark.external_api] + +# Mark all tests in this module as requiring Qdrant + @pytest.fixture async def qdrant_config(): """Provide test Qdrant configuration.""" diff --git a/tests/contract/test_vector_store_provider.py b/tests/contract/test_vector_store_provider.py index b5d71963..e9e889a1 100644 --- a/tests/contract/test_vector_store_provider.py +++ b/tests/contract/test_vector_store_provider.py @@ -16,6 +16,7 @@ from codeweaver.providers.vector_stores.base import VectorStoreProvider +pytestmark = [pytest.mark.unit, pytest.mark.validation] class TestVectorStoreProviderContract: """Test VectorStoreProvider abstract interface contract compliance.""" diff --git a/tests/integration/chunker/test_e2e.py b/tests/integration/chunker/test_e2e.py index 37ab638b..286f3680 100644 --- a/tests/integration/chunker/test_e2e.py +++ b/tests/integration/chunker/test_e2e.py @@ -14,6 +14,9 @@ from codeweaver.engine.chunker.selector import ChunkerSelector +pytestmark = [pytest.mark.integration] + + @pytest.fixture def mock_governor(): @@ -263,6 +266,9 @@ def test_e2e_parallel_dict_convenience(): from codeweaver.engine.chunker.parallel import chunk_files_parallel_dict from codeweaver.providers.embedding.capabilities.base import EmbeddingModelCapabilities + + + # Get sample files fixture_dir = Path("tests/fixtures") files = [] diff --git a/tests/integration/test_custom_config.py b/tests/integration/test_custom_config.py index c2460bcc..d1e75016 100644 --- a/tests/integration/test_custom_config.py +++ b/tests/integration/test_custom_config.py @@ -13,10 +13,13 @@ from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] + + + + async def test_custom_configuration(): """ User Story: Customize provider settings like collection names. diff --git a/tests/integration/test_hybrid_ranking.py b/tests/integration/test_hybrid_ranking.py index f9600ffc..3bb16cdc 100644 --- a/tests/integration/test_hybrid_ranking.py +++ b/tests/integration/test_hybrid_ranking.py @@ -17,10 +17,13 @@ from codeweaver.core.language import SemanticSearchLanguage as Language from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] + + + + async def test_hybrid_search_ranking(): """ User Story: Hybrid search combines sparse and dense for better relevance. diff --git a/tests/integration/test_hybrid_storage.py b/tests/integration/test_hybrid_storage.py index 42185c6a..f58a2aff 100644 --- a/tests/integration/test_hybrid_storage.py +++ b/tests/integration/test_hybrid_storage.py @@ -17,10 +17,13 @@ from codeweaver.core.language import SemanticSearchLanguage as Language from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] + + + + @pytest.fixture async def qdrant_provider(): """Create Qdrant provider for testing.""" diff --git a/tests/integration/test_incremental_updates.py b/tests/integration/test_incremental_updates.py index 16d278fd..5831933c 100644 --- a/tests/integration/test_incremental_updates.py +++ b/tests/integration/test_incremental_updates.py @@ -17,10 +17,13 @@ from codeweaver.core.language import SemanticSearchLanguage as Language from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] + + + + async def test_incremental_updates(): """ User Story: File updates only re-index changed chunks. diff --git a/tests/integration/test_memory_persistence.py b/tests/integration/test_memory_persistence.py index ea8a0827..074d8524 100644 --- a/tests/integration/test_memory_persistence.py +++ b/tests/integration/test_memory_persistence.py @@ -19,10 +19,13 @@ from codeweaver.core.language import SemanticSearchLanguage as Language from codeweaver.providers.vector_stores.inmemory import MemoryVectorStore - pytestmark = pytest.mark.integration + + + + async def test_inmemory_persistence(): """ User Story: Use in-memory storage with automatic persistence. diff --git a/tests/integration/test_partial_embeddings.py b/tests/integration/test_partial_embeddings.py index 30076f5f..698622c6 100644 --- a/tests/integration/test_partial_embeddings.py +++ b/tests/integration/test_partial_embeddings.py @@ -17,10 +17,13 @@ from codeweaver.core.language import SemanticSearchLanguage as Language from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] + + + + async def test_partial_embeddings(): """ User Story: Handle cases where dense embedding generation fails. diff --git a/tests/integration/test_persistence.py b/tests/integration/test_persistence.py index 76c16216..4774155a 100644 --- a/tests/integration/test_persistence.py +++ b/tests/integration/test_persistence.py @@ -17,10 +17,13 @@ from codeweaver.core.language import SemanticSearchLanguage as Language from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] + + + + async def test_persistence_across_restarts(): """ User Story: Previously indexed data persists across restarts. diff --git a/tests/integration/test_provider_switch.py b/tests/integration/test_provider_switch.py index afa333ee..62714b33 100644 --- a/tests/integration/test_provider_switch.py +++ b/tests/integration/test_provider_switch.py @@ -19,10 +19,8 @@ from codeweaver.providers.vector_stores.inmemory import MemoryVectorStore from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore - pytestmark = [pytest.mark.integration, pytest.mark.external_api] - async def test_provider_switch_detection(): """ User Story: Warn when switching providers to prevent data loss. diff --git a/tests/performance/test_vector_store_performance.py b/tests/performance/test_vector_store_performance.py index b4c2fe58..c009967a 100644 --- a/tests/performance/test_vector_store_performance.py +++ b/tests/performance/test_vector_store_performance.py @@ -34,6 +34,12 @@ from codeweaver.providers.vector_stores.inmemory import MemoryVectorStore from codeweaver.providers.vector_stores.qdrant import QdrantVectorStore +pytestmark = [pytest.mark.async_test, pytest.mark.performance, pytest.mark.slow] + + + + + # Test data generation helpers def create_test_chunk( diff --git a/tests/test_delimiters.py b/tests/test_delimiters.py index f98659d2..6bb23f2f 100644 --- a/tests/test_delimiters.py +++ b/tests/test_delimiters.py @@ -36,6 +36,8 @@ matches_pattern, ) +pytestmark = [pytest.mark.unit] + class TestDelimiterPattern: """Test DelimiterPattern DSL and expansion.""" diff --git a/tests/test_lazy_importer.py b/tests/test_lazy_importer.py index 42f1b005..4928302d 100644 --- a/tests/test_lazy_importer.py +++ b/tests/test_lazy_importer.py @@ -13,6 +13,8 @@ from codeweaver.common.utils.lazy_importer import LazyImport, lazy_import +pytestmark = [pytest.mark.unit] + class TestLazyImportBasics: """Test basic LazyImport functionality.""" diff --git a/tests/unit/engine/chunker/test_delimiter_basic.py b/tests/unit/engine/chunker/test_delimiter_basic.py index 13942351..2271d057 100644 --- a/tests/unit/engine/chunker/test_delimiter_basic.py +++ b/tests/unit/engine/chunker/test_delimiter_basic.py @@ -25,6 +25,9 @@ from codeweaver.engine.chunker.delimiter import DelimiterChunker from codeweaver.engine.chunker.delimiters.kind import DelimiterKind +pytestmark = [pytest.mark.unit] + + @pytest.fixture def governor() -> ChunkGovernor: diff --git a/tests/unit/engine/chunker/test_delimiter_edge_cases.py b/tests/unit/engine/chunker/test_delimiter_edge_cases.py index 3f661a7c..4f426e35 100644 --- a/tests/unit/engine/chunker/test_delimiter_edge_cases.py +++ b/tests/unit/engine/chunker/test_delimiter_edge_cases.py @@ -19,6 +19,9 @@ from codeweaver.engine.chunker.base import ChunkGovernor from codeweaver.engine.chunker.delimiter import DelimiterChunker +pytestmark = [pytest.mark.unit] + + @pytest.fixture def delimiter_chunker(chunk_governor: ChunkGovernor) -> DelimiterChunker: @@ -337,7 +340,6 @@ def test_unmatched_delimiters( # Create DiscoveredFile - should not crash, should produce some chunks from codeweaver.core.discovery import DiscoveredFile - discovered_file = DiscoveredFile.from_path(file_path) chunks = delimiter_chunker.chunk(content, file=discovered_file) diff --git a/tests/unit/engine/chunker/test_governance.py b/tests/unit/engine/chunker/test_governance.py index 4bafafec..ef3c469c 100644 --- a/tests/unit/engine/chunker/test_governance.py +++ b/tests/unit/engine/chunker/test_governance.py @@ -16,6 +16,8 @@ from codeweaver.engine.chunker.exceptions import ChunkingTimeoutError, ChunkLimitExceededError from codeweaver.engine.chunker.governance import ResourceGovernor +pytestmark = [pytest.mark.unit] + class PerformanceSettings(Protocol): """Minimal protocol for testing.""" diff --git a/tests/unit/engine/chunker/test_selector.py b/tests/unit/engine/chunker/test_selector.py index 92e0a7fa..076571f6 100644 --- a/tests/unit/engine/chunker/test_selector.py +++ b/tests/unit/engine/chunker/test_selector.py @@ -7,11 +7,15 @@ from pathlib import Path from unittest.mock import Mock +import pytest + from codeweaver.engine.chunker.base import ChunkGovernor from codeweaver.engine.chunker.delimiter import DelimiterChunker from codeweaver.engine.chunker.selector import ChunkerSelector from codeweaver.engine.chunker.semantic import SemanticChunker +pytestmark = [pytest.mark.unit] + def test_selector_chooses_semantic_for_python(chunk_governor: ChunkGovernor) -> None: """Verify selector picks semantic for supported language.""" diff --git a/tests/unit/engine/chunker/test_semantic_basic.py b/tests/unit/engine/chunker/test_semantic_basic.py index f6b49d11..8b4e4e34 100644 --- a/tests/unit/engine/chunker/test_semantic_basic.py +++ b/tests/unit/engine/chunker/test_semantic_basic.py @@ -11,12 +11,14 @@ Python, JavaScript, and Rust. """ - +import pytest from codeweaver.core.language import SemanticSearchLanguage from codeweaver.engine.chunker import SemanticChunker from codeweaver.engine.chunker.base import ChunkGovernor +pytestmark = [pytest.mark.unit] + def test_semantic_chunks_python_file( chunk_governor: ChunkGovernor, discovered_sample_python_file diff --git a/tests/unit/engine/chunker/test_semantic_dedup.py b/tests/unit/engine/chunker/test_semantic_dedup.py index 6bccfce3..51710b31 100644 --- a/tests/unit/engine/chunker/test_semantic_dedup.py +++ b/tests/unit/engine/chunker/test_semantic_dedup.py @@ -20,6 +20,9 @@ from codeweaver.engine.chunker.base import ChunkGovernor from codeweaver.engine.chunker.semantic import SemanticChunker +pytestmark = [pytest.mark.unit] + + @pytest.fixture def chunk_governor() -> ChunkGovernor: @@ -257,6 +260,7 @@ def test_batch_id_tracking( # Create DiscoveredFile and chunk the file from codeweaver.core.discovery import DiscoveredFile + discovered_file = DiscoveredFile.from_path(python_file_with_unique_functions) chunks = semantic_chunker.chunk(content, file=discovered_file) diff --git a/tests/unit/engine/chunker/test_semantic_edge_cases.py b/tests/unit/engine/chunker/test_semantic_edge_cases.py index 7610a3c7..c22194a8 100644 --- a/tests/unit/engine/chunker/test_semantic_edge_cases.py +++ b/tests/unit/engine/chunker/test_semantic_edge_cases.py @@ -12,6 +12,8 @@ from codeweaver.engine.chunker.base import ChunkGovernor from codeweaver.engine.chunker.exceptions import BinaryFileError +pytestmark = [pytest.mark.unit] + def test_empty_file(chunk_governor: ChunkGovernor, discovered_empty_file) -> None: """Verify empty file returns empty list.""" diff --git a/tests/unit/engine/chunker/test_semantic_errors.py b/tests/unit/engine/chunker/test_semantic_errors.py index 168ee358..206b50d1 100644 --- a/tests/unit/engine/chunker/test_semantic_errors.py +++ b/tests/unit/engine/chunker/test_semantic_errors.py @@ -33,6 +33,9 @@ if TYPE_CHECKING: from pytest import MonkeyPatch +pytestmark = [pytest.mark.unit] + + # Path to test fixtures directory FIXTURES_DIR = Path(__file__).parent.parent.parent.parent / "fixtures" diff --git a/tests/unit/engine/chunker/test_semantic_oversized.py b/tests/unit/engine/chunker/test_semantic_oversized.py index da446899..3b87c78d 100644 --- a/tests/unit/engine/chunker/test_semantic_oversized.py +++ b/tests/unit/engine/chunker/test_semantic_oversized.py @@ -22,6 +22,8 @@ from codeweaver.engine.chunker.base import ChunkGovernor from codeweaver.engine.chunker.semantic import SemanticChunker +pytestmark = [pytest.mark.unit] + @pytest.fixture def python_chunker(chunk_governor: ChunkGovernor) -> SemanticChunker: