跨多系统与Python版本,如何匹配含无序集合对象的字符串?
解决集合无序导致的pytest异常消息匹配失败问题
你的问题根源在于Python集合的字符串表示是无序的,受哈希表实现、系统环境影响,导致测试中生成的正则匹配模式和实际抛出的异常消息里的元素顺序不一致。下面是三种可行的解决方法:
方法1:统一使用排序后的元素列表生成消息
不管是函数里的异常消息,还是测试中的匹配模式,都把集合转换成排序后的列表,强制固定元素顺序。
修改原函数:
def check_items(item): my_set = {True, False, "item1", "item2", "item3"} # 按字符串内容排序,避免布尔值与字符串的排序类型冲突 sorted_items = sorted(my_set, key=str) if item not in my_set: raise ValueError( f"Parameter reorder needs to be one of {sorted_items}." ) return item
修改测试代码:
import pytest my_set = {True, False, "item1", "item2", "item3"} sorted_items = sorted(my_set, key=str) def test_check_items_error(): with pytest.raises( ValueError, match=f"Parameter reorder needs to be one of {sorted_items}" ): check_items("new")
方法2:构造匹配任意元素顺序的正则表达式
如果不想修改原函数的异常消息,可以在测试中用正则的正向预查特性,验证所有元素都存在于消息中,忽略顺序。
测试代码修改如下:
import pytest import re my_set = {True, False, "item1", "item2", "item3"} # 转义元素字符串,避免特殊字符干扰正则匹配 escaped_items = [re.escape(str(item)) for item in my_set] # 构造正则:确保每个元素都出现在消息里,顺序不限 pattern = ( r"Parameter reorder needs to be one of \{" + r", ".join([f"(?=.*{item})" for item in escaped_items]) + r".*\}" ) def test_check_items_error(): with pytest.raises(ValueError, match=pattern): check_items("new")
方法3:捕获异常后手动验证消息内容
完全不依赖元素顺序,捕获异常后拆分验证消息的关键部分:
import pytest my_set = {True, False, "item1", "item2", "item3"} def test_check_items_error(): with pytest.raises(ValueError) as exc_info: check_items("new") error_msg = str(exc_info.value) # 验证消息前缀和后缀格式正确 assert error_msg.startswith("Parameter reorder needs to be one of {") assert error_msg.endswith("}.") # 验证所有集合元素都在消息中 for item in my_set: assert str(item) in error_msg
内容的提问来源于stack exchange,提问作者user5654627
相关产品推荐
相关产品推荐

