fix: resolve CI/CD issues - remove unused imports and fix type mismatches
This commit is contained in:
421
tests/test_chunking.py
Normal file
421
tests/test_chunking.py
Normal file
@@ -0,0 +1,421 @@
|
||||
from pathlib import Path
|
||||
|
||||
from codechunk.config import ChunkingConfig
|
||||
from codechunk.core.chunking import ChunkMetadata, ChunkPriority, CodeChunker, ParsedChunk
|
||||
|
||||
|
||||
class TestCodeChunker:
|
||||
"""Tests for CodeChunker."""
|
||||
|
||||
def test_calculate_priority_high_for_main_function(self):
|
||||
"""Test that 'main' function gets high priority."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
chunk = ParsedChunk(
|
||||
name="main",
|
||||
chunk_type="function",
|
||||
content="def main():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
result = chunker._calculate_priority(chunk)
|
||||
|
||||
assert result.priority >= 50
|
||||
|
||||
def test_calculate_priority_high_for_run_function(self):
|
||||
"""Test that 'run' function gets high priority."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
chunk = ParsedChunk(
|
||||
name="run_app",
|
||||
chunk_type="function",
|
||||
content="def run_app():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
result = chunker._calculate_priority(chunk)
|
||||
|
||||
assert result.priority >= 50
|
||||
|
||||
def test_calculate_priority_class_higher_than_function(self):
|
||||
"""Test that classes get higher priority than functions."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
func_chunk = ParsedChunk(
|
||||
name="helper",
|
||||
chunk_type="function",
|
||||
content="def helper():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
class_chunk = ParsedChunk(
|
||||
name="MyClass",
|
||||
chunk_type="class",
|
||||
content="class MyClass:\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
func_priority = chunker._calculate_priority(func_chunk)
|
||||
class_priority = chunker._calculate_priority(class_chunk)
|
||||
|
||||
assert class_priority.priority > func_priority.priority
|
||||
|
||||
def test_calculate_priority_line_count_factor(self):
|
||||
"""Test that larger chunks get higher priority."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
small_chunk = ParsedChunk(
|
||||
name="small",
|
||||
chunk_type="function",
|
||||
content="def small():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
large_chunk = ParsedChunk(
|
||||
name="large",
|
||||
chunk_type="function",
|
||||
content="def large():\n " + "\n ".join(["x = 1"] * 50),
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=52,
|
||||
line_count=52
|
||||
)
|
||||
)
|
||||
|
||||
small_priority = chunker._calculate_priority(small_chunk)
|
||||
large_priority = chunker._calculate_priority(large_chunk)
|
||||
|
||||
assert large_priority.priority > small_priority.priority
|
||||
|
||||
def test_calculate_priority_complexity_factor(self):
|
||||
"""Test that complexity affects priority."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
simple_chunk = ParsedChunk(
|
||||
name="simple",
|
||||
chunk_type="function",
|
||||
content="def simple():\n return 1",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2,
|
||||
complexity_score=1
|
||||
)
|
||||
)
|
||||
|
||||
complex_chunk = ParsedChunk(
|
||||
name="complex",
|
||||
chunk_type="function",
|
||||
content="def complex():\n if True:\n for i in range(10):\n if i > 5:\n return i\n return 0",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=6,
|
||||
line_count=6,
|
||||
complexity_score=10
|
||||
)
|
||||
)
|
||||
|
||||
simple_priority = chunker._calculate_priority(simple_chunk)
|
||||
complex_priority = chunker._calculate_priority(complex_chunk)
|
||||
|
||||
assert complex_priority.priority > simple_priority.priority
|
||||
|
||||
def test_calculate_priority_decorators_factor(self):
|
||||
"""Test that decorators increase priority."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
no_decorator_chunk = ParsedChunk(
|
||||
name="no_decorator",
|
||||
chunk_type="function",
|
||||
content="def no_decorator():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2,
|
||||
decorators=[]
|
||||
)
|
||||
)
|
||||
|
||||
with_decorator_chunk = ParsedChunk(
|
||||
name="with_decorator",
|
||||
chunk_type="function",
|
||||
content="@property\ndef with_decorator():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=3,
|
||||
line_count=3,
|
||||
decorators=["@property"]
|
||||
)
|
||||
)
|
||||
|
||||
no_dec_priority = chunker._calculate_priority(no_decorator_chunk)
|
||||
with_dec_priority = chunker._calculate_priority(with_decorator_chunk)
|
||||
|
||||
assert with_dec_priority.priority >= no_dec_priority.priority
|
||||
|
||||
def test_remove_boilerplate_property(self):
|
||||
"""Test that boilerplate detection works for functions."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
chunk = ParsedChunk(
|
||||
name="MyClass.value",
|
||||
chunk_type="function",
|
||||
content="def value(self):\n return self._value",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
result = chunker._remove_boilerplate(chunk)
|
||||
assert result.is_boilerplate is False
|
||||
|
||||
def test_remove_boilerplate_dunder_methods(self):
|
||||
"""Test that dunder methods are detected."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
chunk = ParsedChunk(
|
||||
name="MyClass.__str__",
|
||||
chunk_type="function",
|
||||
content="def __str__(self):\n return 'MyClass'",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
result = chunker._remove_boilerplate(chunk)
|
||||
assert result.is_boilerplate is True
|
||||
|
||||
def test_remove_boilerplate_regular_function(self):
|
||||
"""Test that regular functions are not marked as boilerplate."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
chunk = ParsedChunk(
|
||||
name="process_data",
|
||||
chunk_type="function",
|
||||
content="def process_data(data):\n return [x for x in data if x > 0]",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
result = chunker._remove_boilerplate(chunk)
|
||||
|
||||
assert result.is_boilerplate is False
|
||||
|
||||
def test_sort_by_priority(self):
|
||||
"""Test that chunks are sorted by priority."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
low_chunk = ParsedChunk(
|
||||
name="helper",
|
||||
chunk_type="function",
|
||||
content="def helper():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
),
|
||||
priority=10
|
||||
)
|
||||
|
||||
high_chunk = ParsedChunk(
|
||||
name="main",
|
||||
chunk_type="function",
|
||||
content="def main():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
),
|
||||
priority=100
|
||||
)
|
||||
|
||||
chunks = [low_chunk, high_chunk]
|
||||
sorted_chunks = chunker._sort_by_priority(chunks)
|
||||
|
||||
assert sorted_chunks[0].name == "main"
|
||||
assert sorted_chunks[1].name == "helper"
|
||||
|
||||
def test_chunk_all_processes_all_chunks(self):
|
||||
"""Test that chunk_all processes all chunks correctly."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
chunks = [
|
||||
ParsedChunk(
|
||||
name="helper",
|
||||
chunk_type="function",
|
||||
content="def helper():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
),
|
||||
ParsedChunk(
|
||||
name="main",
|
||||
chunk_type="function",
|
||||
content="def main():\n pass",
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=4,
|
||||
end_line=5,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
result = chunker.chunk_all(chunks)
|
||||
|
||||
assert len(result) == 2
|
||||
assert result[0].priority > result[1].priority
|
||||
|
||||
def test_split_large_chunk(self, tmp_path):
|
||||
"""Test splitting a large chunk into smaller pieces."""
|
||||
config = ChunkingConfig()
|
||||
config.max_chunk_size = 10
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
large_content = "\n".join([f"line {i}" for i in range(30)])
|
||||
chunk = ParsedChunk(
|
||||
name="large_function",
|
||||
chunk_type="function",
|
||||
content=large_content,
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=30,
|
||||
line_count=30
|
||||
)
|
||||
)
|
||||
|
||||
parts = chunker.split_large_chunk(chunk)
|
||||
|
||||
assert len(parts) > 1
|
||||
for part in parts:
|
||||
assert part.metadata.line_count <= config.max_chunk_size
|
||||
|
||||
def test_split_small_chunk(self, tmp_path):
|
||||
"""Test that small chunks are not split."""
|
||||
config = ChunkingConfig()
|
||||
chunker = CodeChunker(config)
|
||||
|
||||
small_content = "def small():\n pass"
|
||||
chunk = ParsedChunk(
|
||||
name="small",
|
||||
chunk_type="function",
|
||||
content=small_content,
|
||||
metadata=ChunkMetadata(
|
||||
file_path=Path("test.py"),
|
||||
file_name="test.py",
|
||||
language="python",
|
||||
start_line=1,
|
||||
end_line=2,
|
||||
line_count=2
|
||||
)
|
||||
)
|
||||
|
||||
parts = chunker.split_large_chunk(chunk)
|
||||
|
||||
assert len(parts) == 1
|
||||
assert parts[0].content == small_content
|
||||
|
||||
|
||||
class TestChunkPriority:
|
||||
"""Tests for ChunkPriority constants."""
|
||||
|
||||
def test_priority_values(self):
|
||||
"""Test that priority constants have expected values."""
|
||||
assert ChunkPriority.CRITICAL == 100
|
||||
assert ChunkPriority.HIGH == 75
|
||||
assert ChunkPriority.MEDIUM == 50
|
||||
assert ChunkPriority.LOW == 25
|
||||
assert ChunkPriority.MINIMAL == 10
|
||||
Reference in New Issue
Block a user