fix: 改进
This commit is contained in:
0
tests/kernel/puzzles/__init__.py
Normal file
0
tests/kernel/puzzles/__init__.py
Normal file
23
tests/kernel/puzzles/test_base.py
Normal file
23
tests/kernel/puzzles/test_base.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
|
||||
from heurams.kernel.puzzles.base import BasePuzzle
|
||||
|
||||
|
||||
class TestBasePuzzle(unittest.TestCase):
|
||||
"""测试 BasePuzzle 基类"""
|
||||
|
||||
def test_refresh_not_implemented(self):
|
||||
"""测试 refresh 方法未实现时抛出异常"""
|
||||
puzzle = BasePuzzle()
|
||||
with self.assertRaises(NotImplementedError):
|
||||
puzzle.refresh()
|
||||
|
||||
def test_str(self):
|
||||
"""测试 __str__ 方法"""
|
||||
puzzle = BasePuzzle()
|
||||
self.assertEqual(str(puzzle), "谜题: BasePuzzle")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
51
tests/kernel/puzzles/test_cloze.py
Normal file
51
tests/kernel/puzzles/test_cloze.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from heurams.kernel.puzzles.cloze import ClozePuzzle
|
||||
|
||||
|
||||
class TestClozePuzzle(unittest.TestCase):
|
||||
"""测试 ClozePuzzle 类"""
|
||||
|
||||
def test_init(self):
|
||||
"""测试初始化"""
|
||||
puzzle = ClozePuzzle("hello/world/test", min_denominator=3, delimiter="/")
|
||||
self.assertEqual(puzzle.text, "hello/world/test")
|
||||
self.assertEqual(puzzle.min_denominator, 3)
|
||||
self.assertEqual(puzzle.delimiter, "/")
|
||||
self.assertEqual(puzzle.wording, "填空题 - 尚未刷新谜题")
|
||||
self.assertEqual(puzzle.answer, ["填空题 - 尚未刷新谜题"])
|
||||
|
||||
@patch('random.sample')
|
||||
def test_refresh(self, mock_sample):
|
||||
"""测试 refresh 方法"""
|
||||
mock_sample.return_value = [0, 2] # 选择索引 0 和 2
|
||||
puzzle = ClozePuzzle("hello/world/test", min_denominator=2, delimiter="/")
|
||||
puzzle.refresh()
|
||||
|
||||
# 检查 wording 和 answer
|
||||
self.assertNotEqual(puzzle.wording, "填空题 - 尚未刷新谜题")
|
||||
self.assertNotEqual(puzzle.answer, ["填空题 - 尚未刷新谜题"])
|
||||
# 根据模拟,应该有两个填空
|
||||
self.assertEqual(len(puzzle.answer), 2)
|
||||
self.assertEqual(puzzle.answer, ["hello", "test"])
|
||||
# wording 应包含下划线
|
||||
self.assertIn("__", puzzle.wording)
|
||||
|
||||
def test_refresh_empty_text(self):
|
||||
"""测试空文本的 refresh"""
|
||||
puzzle = ClozePuzzle("", min_denominator=3, delimiter="/")
|
||||
puzzle.refresh() # 不应引发异常
|
||||
# 空文本导致 wording 和 answer 为空
|
||||
self.assertEqual(puzzle.wording, "")
|
||||
self.assertEqual(puzzle.answer, [])
|
||||
|
||||
def test_str(self):
|
||||
"""测试 __str__ 方法"""
|
||||
puzzle = ClozePuzzle("hello/world", min_denominator=2, delimiter="/")
|
||||
str_repr = str(puzzle)
|
||||
self.assertIn("填空题 - 尚未刷新谜题", str_repr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
122
tests/kernel/puzzles/test_mcq.py
Normal file
122
tests/kernel/puzzles/test_mcq.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock, call
|
||||
|
||||
from heurams.kernel.puzzles.mcq import MCQPuzzle
|
||||
|
||||
|
||||
class TestMCQPuzzle(unittest.TestCase):
|
||||
"""测试 MCQPuzzle 类"""
|
||||
|
||||
def test_init(self):
|
||||
"""测试初始化"""
|
||||
mapping = {"q1": "a1", "q2": "a2"}
|
||||
jammer = ["j1", "j2", "j3"]
|
||||
puzzle = MCQPuzzle(mapping, jammer, max_riddles_num=3, prefix="选择")
|
||||
self.assertEqual(puzzle.prefix, "选择")
|
||||
self.assertEqual(puzzle.mapping, mapping)
|
||||
self.assertEqual(puzzle.max_riddles_num, 3)
|
||||
# jammer 应合并正确答案并去重
|
||||
self.assertIn("a1", puzzle.jammer)
|
||||
self.assertIn("a2", puzzle.jammer)
|
||||
self.assertIn("j1", puzzle.jammer)
|
||||
# 初始状态
|
||||
self.assertEqual(puzzle.wording, "选择题 - 尚未刷新谜题")
|
||||
self.assertEqual(puzzle.answer, ["选择题 - 尚未刷新谜题"])
|
||||
self.assertEqual(puzzle.options, [])
|
||||
|
||||
def test_init_max_riddles_num_clamping(self):
|
||||
"""测试 max_riddles_num 限制在 1-5 之间"""
|
||||
puzzle1 = MCQPuzzle({}, [], max_riddles_num=0)
|
||||
self.assertEqual(puzzle1.max_riddles_num, 1)
|
||||
puzzle2 = MCQPuzzle({}, [], max_riddles_num=10)
|
||||
self.assertEqual(puzzle2.max_riddles_num, 5)
|
||||
|
||||
def test_init_jammer_ensures_minimum(self):
|
||||
"""测试干扰项至少保证 4 个"""
|
||||
puzzle = MCQPuzzle({}, [])
|
||||
# 正确答案为空,干扰项为空,应填充空格
|
||||
self.assertEqual(len(puzzle.jammer), 4)
|
||||
self.assertEqual(set(puzzle.jammer), {" "}) # 三个空格?实际上循环填充空格
|
||||
|
||||
@patch('random.sample')
|
||||
@patch('random.shuffle')
|
||||
def test_refresh(self, mock_shuffle, mock_sample):
|
||||
"""测试 refresh 方法生成题目"""
|
||||
mapping = {"q1": "a1", "q2": "a2", "q3": "a3"}
|
||||
jammer = ["j1", "j2", "j3", "j4"]
|
||||
puzzle = MCQPuzzle(mapping, jammer, max_riddles_num=2)
|
||||
# 模拟 random.sample 返回前两个映射项
|
||||
mock_sample.side_effect = [
|
||||
[("q1", "a1"), ("q2", "a2")], # 选择问题
|
||||
["j1", "j2", "j3"], # 为每个问题选择干扰项(实际调用两次)
|
||||
]
|
||||
puzzle.refresh()
|
||||
|
||||
# 检查 wording 是列表
|
||||
self.assertIsInstance(puzzle.wording, list)
|
||||
self.assertEqual(len(puzzle.wording), 2)
|
||||
# 检查 answer 列表
|
||||
self.assertEqual(puzzle.answer, ["a1", "a2"])
|
||||
# 检查 options 列表
|
||||
self.assertEqual(len(puzzle.options), 2)
|
||||
# 每个选项列表应包含 4 个选项(正确答案 + 3 个干扰项)
|
||||
self.assertEqual(len(puzzle.options[0]), 4)
|
||||
self.assertEqual(len(puzzle.options[1]), 4)
|
||||
# random.shuffle 应被调用
|
||||
self.assertEqual(mock_shuffle.call_count, 2)
|
||||
|
||||
def test_refresh_empty_mapping(self):
|
||||
"""测试空 mapping 的 refresh"""
|
||||
puzzle = MCQPuzzle({}, [])
|
||||
puzzle.refresh()
|
||||
self.assertEqual(puzzle.wording, "无可用题目")
|
||||
self.assertEqual(puzzle.answer, ["无答案"])
|
||||
self.assertEqual(puzzle.options, [])
|
||||
|
||||
def test_get_question_count(self):
|
||||
"""测试 get_question_count 方法"""
|
||||
puzzle = MCQPuzzle({"q": "a"}, [])
|
||||
self.assertEqual(puzzle.get_question_count(), 0) # 未刷新
|
||||
puzzle.refresh = MagicMock()
|
||||
puzzle.wording = ["Q1", "Q2"]
|
||||
self.assertEqual(puzzle.get_question_count(), 2)
|
||||
puzzle.wording = "无可用题目"
|
||||
self.assertEqual(puzzle.get_question_count(), 0)
|
||||
puzzle.wording = "单个问题"
|
||||
self.assertEqual(puzzle.get_question_count(), 1)
|
||||
|
||||
def test_get_correct_answer_for_question(self):
|
||||
"""测试 get_correct_answer_for_question 方法"""
|
||||
puzzle = MCQPuzzle({}, [])
|
||||
puzzle.answer = ["ans1", "ans2"]
|
||||
self.assertEqual(puzzle.get_correct_answer_for_question(0), "ans1")
|
||||
self.assertEqual(puzzle.get_correct_answer_for_question(1), "ans2")
|
||||
self.assertIsNone(puzzle.get_correct_answer_for_question(2))
|
||||
puzzle.answer = "not a list"
|
||||
self.assertIsNone(puzzle.get_correct_answer_for_question(0))
|
||||
|
||||
def test_get_options_for_question(self):
|
||||
"""测试 get_options_for_question 方法"""
|
||||
puzzle = MCQPuzzle({}, [])
|
||||
puzzle.options = [["a", "b", "c", "d"], ["e", "f", "g", "h"]]
|
||||
self.assertEqual(puzzle.get_options_for_question(0), ["a", "b", "c", "d"])
|
||||
self.assertEqual(puzzle.get_options_for_question(1), ["e", "f", "g", "h"])
|
||||
self.assertIsNone(puzzle.get_options_for_question(2))
|
||||
|
||||
def test_str(self):
|
||||
"""测试 __str__ 方法"""
|
||||
puzzle = MCQPuzzle({}, [])
|
||||
puzzle.wording = "选择题 - 尚未刷新谜题"
|
||||
puzzle.answer = ["选择题 - 尚未刷新谜题"]
|
||||
self.assertIn("选择题 - 尚未刷新谜题", str(puzzle))
|
||||
self.assertIn("正确答案", str(puzzle))
|
||||
|
||||
puzzle.wording = ["Q1", "Q2"]
|
||||
puzzle.answer = ["A1", "A2"]
|
||||
str_repr = str(puzzle)
|
||||
self.assertIn("Q1", str_repr)
|
||||
self.assertIn("A1, A2", str_repr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user