Skip to main content
Glama

MCP Sheet Parser

by yuqie6
MIT License
3
  • Apple
test_table_model.py21.3 kB
import pytest from src.models.table_model import ( RichTextFragmentStyle, RichTextFragment, Cell, Style, Row, Sheet, ChartPosition, Chart, LazySheet, LazyRowProvider, StreamingCapable ) class TestRichTextFragmentStyle: """测试RichTextFragmentStyle类。""" def test_rich_text_fragment_style_default_values(self): """ TDD测试:RichTextFragmentStyle应该有正确的默认值 """ style = RichTextFragmentStyle() assert style.bold is False assert style.italic is False assert style.underline is False assert style.font_color is None assert style.font_size is None assert style.font_name is None def test_rich_text_fragment_style_with_values(self): """ TDD测试:RichTextFragmentStyle应该正确设置属性值 """ style = RichTextFragmentStyle( bold=True, italic=True, underline=True, font_color="#FF0000", font_size=14.0, font_name="Arial" ) assert style.bold is True assert style.italic is True assert style.underline is True assert style.font_color == "#FF0000" assert style.font_size == 14.0 assert style.font_name == "Arial" class TestRichTextFragment: """测试RichTextFragment类。""" def test_rich_text_fragment_creation(self): """ TDD测试:RichTextFragment应该正确创建 """ style = RichTextFragmentStyle(bold=True, font_color="#FF0000") fragment = RichTextFragment(text="Hello World", style=style) assert fragment.text == "Hello World" assert fragment.style == style assert fragment.style.bold is True assert fragment.style.font_color == "#FF0000" class TestCell: """测试Cell类。""" def test_cell_default_values(self): """ TDD测试:Cell应该有正确的默认值 """ cell = Cell(value="Test") assert cell.value == "Test" assert cell.style is None assert cell.row_span == 1 assert cell.col_span == 1 assert cell.formula is None def test_cell_with_all_properties(self): """ TDD测试:Cell应该正确设置所有属性 """ style = Style(bold=True) cell = Cell( value="Test Value", style=style, row_span=2, col_span=3, formula="=A1+B1" ) assert cell.value == "Test Value" assert cell.style == style assert cell.row_span == 2 assert cell.col_span == 3 assert cell.formula == "=A1+B1" def test_cell_with_rich_text_value(self): """ TDD测试:Cell应该支持富文本值 """ style1 = RichTextFragmentStyle(bold=True) style2 = RichTextFragmentStyle(italic=True) fragments = [ RichTextFragment("Bold text", style1), RichTextFragment("Italic text", style2) ] cell = Cell(value=fragments) assert cell.value == fragments assert len(cell.value) == 2 assert cell.value[0].text == "Bold text" assert cell.value[1].text == "Italic text" class TestStyle: """测试Style类。""" def test_style_default_values(self): """ TDD测试:Style应该有正确的默认值 """ style = Style() assert style.font_name is None assert style.font_size is None assert style.font_color is None assert style.background_color is None assert style.bold is False assert style.italic is False assert style.underline is False assert style.text_align is None assert style.vertical_align is None assert style.border_top is None assert style.border_bottom is None assert style.border_left is None assert style.border_right is None assert style.border_color is None assert style.wrap_text is False assert style.number_format is None assert style.formula is None assert style.hyperlink is None assert style.comment is None def test_style_with_all_properties(self): """ TDD测试:Style应该正确设置所有属性 """ style = Style( font_name="Arial", font_size=12, font_color="#000000", background_color="#FFFFFF", bold=True, italic=False, underline=True, text_align="center", vertical_align="middle", border_top="1px solid black", border_bottom="1px solid black", border_left="1px solid black", border_right="1px solid black", border_color="#000000", wrap_text=True, number_format="0.00", formula="=A1+B1", hyperlink="http://example.com", comment="Test comment" ) assert style.font_name == "Arial" assert style.font_size == 12 assert style.font_color == "#000000" assert style.background_color == "#FFFFFF" assert style.bold is True assert style.italic is False assert style.underline is True assert style.text_align == "center" assert style.vertical_align == "middle" assert style.border_top == "1px solid black" assert style.border_bottom == "1px solid black" assert style.border_left == "1px solid black" assert style.border_right == "1px solid black" assert style.border_color == "#000000" assert style.wrap_text is True assert style.number_format == "0.00" assert style.formula == "=A1+B1" assert style.hyperlink == "http://example.com" assert style.comment == "Test comment" class TestRow: """测试Row类。""" def test_row_creation(self): """ TDD测试:Row应该正确创建 """ cells = [Cell(value="A1"), Cell(value="B1"), Cell(value="C1")] row = Row(cells=cells) assert row.cells == cells assert len(row.cells) == 3 assert row.cells[0].value == "A1" assert row.cells[1].value == "B1" assert row.cells[2].value == "C1" def test_row_with_empty_cells(self): """ TDD测试:Row应该支持空单元格列表 """ row = Row(cells=[]) assert row.cells == [] assert len(row.cells) == 0 class TestChartPosition: """测试ChartPosition类。""" def test_chart_position_creation(self): """ TDD测试:ChartPosition应该正确创建 """ position = ChartPosition( from_col=0, from_row=0, to_col=5, to_row=10, from_col_offset=0, from_row_offset=0, to_col_offset=0, to_row_offset=0 ) assert position.from_col == 0 assert position.from_row == 0 assert position.to_col == 5 assert position.to_row == 10 assert position.from_col_offset == 0 assert position.from_row_offset == 0 assert position.to_col_offset == 0 assert position.to_row_offset == 0 class TestChart: """测试Chart类。""" def test_chart_default_values(self): """ TDD测试:Chart应该有正确的默认值 """ chart = Chart(name="TestChart", type="line", anchor="A1") assert chart.name == "TestChart" assert chart.type == "line" assert chart.anchor == "A1" assert chart.position is None assert chart.chart_data is None def test_chart_with_all_properties(self): """ TDD测试:Chart应该正确设置所有属性 """ position = ChartPosition(0, 0, 5, 10, 0, 0, 0, 0) chart_data = {"type": "line", "data": [1, 2, 3]} chart = Chart( name="TestChart", type="line", anchor="A1", position=position, chart_data=chart_data ) assert chart.name == "TestChart" assert chart.type == "line" assert chart.anchor == "A1" assert chart.position == position assert chart.chart_data == chart_data class TestSheet: """测试Sheet类。""" def test_sheet_default_values(self): """ TDD测试:Sheet应该有正确的默认值 """ rows = [Row(cells=[Cell(value="A1")])] sheet = Sheet(name="TestSheet", rows=rows) assert sheet.name == "TestSheet" assert sheet.rows == rows assert sheet.merged_cells == [] assert sheet.charts == [] assert sheet.column_widths == {} assert sheet.row_heights == {} assert sheet.default_column_width == 8.43 assert sheet.default_row_height == 18.0 def test_sheet_with_all_properties(self): """ TDD测试:Sheet应该正确设置所有属性 """ rows = [Row(cells=[Cell(value="A1")])] merged_cells = ["A1:B2"] charts = [Chart(name="Chart1", type="line", anchor="A1")] column_widths = {0: 20, 1: 30} row_heights = {0: 25, 1: 35} sheet = Sheet( name="TestSheet", rows=rows, merged_cells=merged_cells, charts=charts, column_widths=column_widths, row_heights=row_heights, default_column_width=10.0, default_row_height=20.0 ) assert sheet.name == "TestSheet" assert sheet.rows == rows assert sheet.merged_cells == merged_cells assert sheet.charts == charts assert sheet.column_widths == column_widths assert sheet.row_heights == row_heights assert sheet.default_column_width == 10.0 assert sheet.default_row_height == 20.0 class MockRowProvider: """模拟的行提供者,用于测试LazySheet。""" def __init__(self, total_rows=10): self.total_rows = total_rows def iter_rows(self, start_row=0, max_rows=None): """生成模拟行。""" end_row = min(start_row + (max_rows or self.total_rows), self.total_rows) for i in range(start_row, end_row): yield Row(cells=[Cell(value=f"Row{i}Col{j}") for j in range(3)]) def get_row(self, row_index): """获取指定行。""" if row_index >= self.total_rows: raise IndexError(f"Row index {row_index} out of range") return Row(cells=[Cell(value=f"Row{row_index}Col{j}") for j in range(3)]) def get_total_rows(self): """获取总行数。""" return self.total_rows class TestLazySheet: """测试LazySheet类。""" def test_lazy_sheet_creation(self): """ TDD测试:LazySheet应该正确创建 """ provider = MockRowProvider(total_rows=5) lazy_sheet = LazySheet(name="LazyTestSheet", provider=provider) assert lazy_sheet.name == "LazyTestSheet" assert lazy_sheet._provider == provider def test_lazy_sheet_iter_rows(self): """ TDD测试:LazySheet应该支持行迭代 """ provider = MockRowProvider(total_rows=5) lazy_sheet = LazySheet(name="LazyTestSheet", provider=provider) rows = list(lazy_sheet.iter_rows(start_row=1, max_rows=3)) assert len(rows) == 3 assert rows[0].cells[0].value == "Row1Col0" assert rows[1].cells[0].value == "Row2Col0" assert rows[2].cells[0].value == "Row3Col0" def test_lazy_sheet_get_row(self): """ TDD测试:LazySheet应该支持按索引获取行 """ provider = MockRowProvider(total_rows=5) lazy_sheet = LazySheet(name="LazyTestSheet", provider=provider) row = lazy_sheet.get_row(2) assert row.cells[0].value == "Row2Col0" assert row.cells[1].value == "Row2Col1" assert row.cells[2].value == "Row2Col2" def test_lazy_sheet_get_total_rows(self): """ TDD测试:LazySheet应该支持获取总行数 """ provider = MockRowProvider(total_rows=10) lazy_sheet = LazySheet(name="LazyTestSheet", provider=provider) total_rows = lazy_sheet.get_total_rows() assert total_rows == 10 class MockStreamingParser(StreamingCapable): """模拟的流式解析器,用于测试StreamingCapable。""" def __init__(self, supports_streaming=True): self._supports_streaming = supports_streaming def supports_streaming(self): """检查是否支持流式处理。""" return self._supports_streaming def create_lazy_sheet(self, file_path): """创建惰性sheet。""" provider = MockRowProvider(total_rows=5) return LazySheet(name="StreamingSheet", provider=provider) class TestStreamingCapable: """测试StreamingCapable抽象类。""" def test_streaming_capable_supports_streaming_true(self): """ TDD测试:StreamingCapable应该正确报告流式支持状态 """ parser = MockStreamingParser(supports_streaming=True) assert parser.supports_streaming() is True def test_streaming_capable_supports_streaming_false(self): """ TDD测试:StreamingCapable应该正确报告不支持流式 """ parser = MockStreamingParser(supports_streaming=False) assert parser.supports_streaming() is False def test_streaming_capable_create_lazy_sheet(self): """ TDD测试:StreamingCapable应该能创建LazySheet """ parser = MockStreamingParser() lazy_sheet = parser.create_lazy_sheet("test.xlsx") assert isinstance(lazy_sheet, LazySheet) assert lazy_sheet.name == "StreamingSheet" assert lazy_sheet.get_total_rows() == 5 class TestTableModelEdgeCases: """测试表格模型的边界情况。""" def test_cell_with_none_values(self): """ TDD测试:Cell应该处理None值 """ cell = Cell(value=None) assert cell.value is None assert cell.style is None def test_style_equality(self): """ TDD测试:Style对象应该支持相等性比较 """ style1 = Style(bold=True, font_size=12) style2 = Style(bold=True, font_size=12) style3 = Style(bold=False, font_size=12) assert style1 == style2 assert style1 != style3 def test_rich_text_fragment_style_equality(self): """ TDD测试:RichTextFragmentStyle对象应该支持相等性比较 """ style1 = RichTextFragmentStyle(bold=True, font_color="#FF0000") style2 = RichTextFragmentStyle(bold=True, font_color="#FF0000") style3 = RichTextFragmentStyle(bold=False, font_color="#FF0000") assert style1 == style2 assert style1 != style3 def test_chart_position_equality(self): """ TDD测试:ChartPosition对象应该支持相等性比较 """ pos1 = ChartPosition(0, 0, 5, 10, 0, 0, 0, 0) pos2 = ChartPosition(0, 0, 5, 10, 0, 0, 0, 0) pos3 = ChartPosition(1, 0, 5, 10, 0, 0, 0, 0) assert pos1 == pos2 assert pos1 != pos3 # === 边界情况和未覆盖代码测试 === class TestSheetIterRows: """测试Sheet.iter_rows方法的边界情况。""" def test_iter_rows_with_max_rows_exceeding_total(self): """ TDD测试:iter_rows应该处理max_rows超过总行数的情况 这个测试覆盖第186行的min函数调用 """ rows = [ Row(cells=[Cell(value=f"Row {i}")]) for i in range(3) ] sheet = Sheet(name="测试表", rows=rows, merged_cells=[]) # 请求超过总行数的行数 result_rows = list(sheet.iter_rows(start_row=0, max_rows=10)) # 应该只返回实际存在的行数 assert len(result_rows) == 3 assert result_rows[0].cells[0].value == "Row 0" assert result_rows[2].cells[0].value == "Row 2" def test_iter_rows_with_start_row_beyond_range(self): """ TDD测试:iter_rows应该处理start_row超出范围的情况 这个测试覆盖第189行的边界检查 """ rows = [Row(cells=[Cell(value="Row 0")])] sheet = Sheet(name="测试表", rows=rows, merged_cells=[]) # 从超出范围的行开始 result_rows = list(sheet.iter_rows(start_row=5, max_rows=10)) # 应该返回空列表 assert len(result_rows) == 0 class TestLazySheetSlicing: """测试LazySheet的切片功能。""" def test_lazy_sheet_slice_with_step_not_one(self): """ TDD测试:LazySheet切片应该拒绝步长不为1的切片 这个测试覆盖第226-227行的步长检查 """ # 创建模拟的LazyRowProvider class MockProvider: def iter_rows(self, start_row=0, max_rows=None): for i in range(start_row, min(start_row + (max_rows or 5), 5)): yield Row(cells=[Cell(value=f"Row {i}")]) def get_row(self, row_index): return Row(cells=[Cell(value=f"Row {row_index}")]) def get_total_rows(self): return 5 lazy_sheet = LazySheet("测试表", MockProvider()) # 尝试使用步长不为1的切片 with pytest.raises(ValueError, match="暂不支持步长切片"): _ = lazy_sheet[0:3:2] def test_lazy_sheet_invalid_index_type(self): """ TDD测试:LazySheet应该拒绝无效的索引类型 这个测试覆盖第229-230行的类型检查 """ class MockProvider: def get_total_rows(self): return 5 lazy_sheet = LazySheet("测试表", MockProvider()) # 尝试使用无效的索引类型 with pytest.raises(TypeError, match="无效的下标类型"): _ = lazy_sheet["invalid"] def test_lazy_sheet_slice_access(self): """ TDD测试:LazySheet应该支持切片访问 这个测试覆盖第224-228行的切片处理 """ class MockProvider: def iter_rows(self, start_row=0, max_rows=None): for i in range(start_row, min(start_row + (max_rows or 5), 5)): yield Row(cells=[Cell(value=f"Row {i}")]) def get_total_rows(self): return 5 lazy_sheet = LazySheet("测试表", MockProvider()) # 使用切片访问 result = lazy_sheet[1:3] assert len(result) == 2 assert result[0].cells[0].value == "Row 1" assert result[1].cells[0].value == "Row 2" def test_lazy_sheet_to_sheet_conversion(self): """ TDD测试:LazySheet应该能转换为常规Sheet 这个测试覆盖第232-239行的转换逻辑 """ class MockProvider: def iter_rows(self, start_row=0, max_rows=None): for i in range(3): yield Row(cells=[Cell(value=f"Row {i}")]) lazy_sheet = LazySheet("测试表", MockProvider(), merged_cells=["A1:B1"]) # 转换为常规Sheet regular_sheet = lazy_sheet.to_sheet() assert isinstance(regular_sheet, Sheet) assert regular_sheet.name == "测试表" assert len(regular_sheet.rows) == 3 assert regular_sheet.merged_cells == ["A1:B1"] assert regular_sheet.rows[0].cells[0].value == "Row 0" class TestProtocolAndAbstractMethods: """测试Protocol和抽象方法的覆盖。""" def test_lazy_row_provider_protocol_methods(self): """ TDD测试:LazyRowProvider协议方法应该可以被调用 这个测试覆盖第32, 36, 40行的协议方法 """ # 创建实现协议的类 class TestProvider: def iter_rows(self, start_row=0, max_rows=None): return iter([]) # 覆盖第32行 def get_row(self, row_index): return Row(cells=[]) # 覆盖第36行 def get_total_rows(self): return 0 # 覆盖第40行 provider = TestProvider() # 验证方法可以被调用 assert list(provider.iter_rows()) == [] assert isinstance(provider.get_row(0), Row) assert provider.get_total_rows() == 0 def test_streaming_capable_abstract_methods(self): """ TDD测试:StreamingCapable抽象方法应该可以被实现 这个测试覆盖第48, 53行的抽象方法 """ # 创建实现抽象类的类 class TestStreamingParser(StreamingCapable): def supports_streaming(self): return True # 覆盖第48行 def create_lazy_sheet(self, file_path, sheet_name=None): return None # 覆盖第53行 parser = TestStreamingParser() # 验证方法可以被调用 assert parser.supports_streaming() is True assert parser.create_lazy_sheet("test.xlsx") is None

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yuqie6/MCP-Sheet-Parser-cot'

If you have feedback or need assistance with the MCP directory API, please join our Discord server