如何通过单元测试覆盖Python重载的__setitem__方法?
覆盖__setitem__重载分支的测试方案
Python里的@overload装饰器仅用于静态类型检查工具(比如mypy),运行时不会生成多个独立的__setitem__方法,实际执行的只有你写的那个合并实现的方法。你要做的不是“覆盖重载方法”,而是覆盖实现方法里对应两种重载场景的所有代码分支,包括正常流程和异常分支。
完整测试用例
1. 测试int索引的正常赋值
def test_setitem_int_valid(self): cup_list = Cup_List() original_cup = Cup("red 10") new_cup = Cup("blue 20") cup_list.append(original_cup) # 用标准下标赋值语法,替代直接调用__setitem__ cup_list[0] = new_cup self.assertEqual(cup_list.cups[0], new_cup)
2. 测试int索引传入非Cup类型的异常
def test_setitem_int_invalid_type(self): cup_list = Cup_List() cup_list.append(Cup("red 10")) with self.assertRaises(TypeError) as error_ctx: cup_list[0] = "not a Cup instance" self.assertEqual(str(error_ctx.exception), "Expected item of type Cupgot str")
3. 测试slice索引的正常批量赋值
def test_setitem_slice_valid(self): cup_list = Cup_List() cup_list.extend([Cup("cup1"), Cup("cup2"), Cup("cup3")]) new_cups = [Cup("new1"), Cup("new2")] # 用slice语法替换指定范围的元素 cup_list[1:3] = new_cups self.assertEqual(cup_list.cups, [Cup("cup1"), Cup("new1"), Cup("new2")])
4. 测试slice索引的异常场景
def test_setitem_slice_invalid(self): cup_list = Cup_List() cup_list.extend([Cup("cup1"), Cup("cup2")]) # 测试传入非Iterable类型 with self.assertRaises(TypeError) as error_ctx: cup_list[0:1] = Cup("single cup") self.assertEqual(str(error_ctx.exception), "Expected Iterable of Cups") # 测试Iterable中包含非Cup元素 with self.assertRaises(TypeError) as error_ctx: cup_list[0:1] = [Cup("valid"), "invalid item"] self.assertEqual(str(error_ctx.exception), "Expected Iterable of Cups")
关键注意点
- 不要直接调用
__setitem__方法,而是使用Python标准的下标赋值语法cup_list[index] = value,这是该方法的实际调用方式,也更符合代码使用场景。 - 必须覆盖所有代码分支:int索引的正常/异常、slice索引的正常/异常,这样才能让实现方法里的每一行代码都被测试覆盖到。
- 验证异常信息的准确性,确保错误处理逻辑符合预期。
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

