How to match a string that contains a Python unordered set object when testing across multiple systems and Python versions?

huangapple go评论58阅读模式
英文:

How to match a string that contains a Python unordered set object when testing across multiple systems and Python versions?

问题

我有一个运行在Python版本>= 3.7,以及在Ubuntu和macOS系统上运行测试的CI设置。我有一个测试似乎会随机失败,我想知道是否与不同系统上如何存储无序集有关。错误是一个失败,其中正确引发了一个警告,但它与预期的警告消息不匹配,因为它显示了以不同顺序打印的正则表达式模式与集合对象。我想知道在将它们作为对象插入到f-string正则表达式时,是否有更好的比较无序集的方法。

为了明确起见,我有以下要测试的函数:

def check_items(item):
    my_set = {True, False, "item1", "item2", "item3"}
    if item not in my_set:
        raise ValueError(
            f"Parameter reorder needs to be one of {my_set}."
        )
    return item

在一个单独的测试文件中,我有以下测试:

import pytest

my_set = {True, False, "item1", "item2", "item3"}

def test_check_items_error():
    with pytest.raises(
            ValueError,
            match=f"Parameter reorder needs to be one of {my_set}"
    ):
        check_items("new")

测试的失败是:

AssertionError: 正则表达式模式不匹配。
 正则表达式: "Parameter reorder needs to be one of {False, True, 'item1', 'item2', 'item3'}"
 输入: "Parameter reorder needs to be one of {False, True, 'item2', 'item1', 'item3'}."

在这种情况下,确保相同的无序集在f-strings中正确匹配的最安全方法是什么?

英文:

I have a CI setup that is running tests across Python versions >= 3.7 and on Ubuntu and macOS systems. I have a test that seems to randomly fail and I'm wondering if it has to do with how unordered sets are stored in memory on different systems. The error is a failure where a warning is raised correctly but it does not match the expected warning message because it is showing the regex pattern printed with a different order of the set object. I wonder if there is a better way to compare unordered sets when they are inserted as an object into an f-string regex.

For clarity I have the following function I am testing:

def check_items(item):
    my_set = {True, False, "item1", "item2", "item3"}
    if item not in my_set:
        raise ValueError(
            f"Parameter reorder needs to be one of {my_set}."
        )
    return item

And in a separate test file I have the following test

import pytest

my_set = {True, False, "item1", "item2", "item3"}

def test_check_items_error():
    with pytest.raises(
            ValueError,
            match=f"Parameter reorder needs to be one of {my_set}"
    ):
        check_items("new")

The failure of the test is

AssertionError: Regex pattern did not match.
 Regex: "Parameter reorder needs to be one of {False, True, 'item1', 'item2', 'item3'}"
 Input: "Parameter reorder needs to be one of {False, True, 'item2', 'item1', 'item3'}."

What is the safest way to make sure that identical unordered sets are matched correctly in this setting where they are inserted into an f-strings?

答案1

得分: 0

我们可以通过对每个集合元素的表示进行排序来"规范化"集合。这样,结果将会按顺序排列:

#!/usr/bin/env python3
import pytest

def check_items(item):
    my_set = {True, False, "item1", "item2", "item3"}
    if item not in my_set:
        normalized = ", ".join(sorted(repr(e) for e in my_set))
        raise ValueError(f"参数 reorder 需要是 {normalized} 其中之一。")
    return item

def test_check_items_error():
    my_set = {"item1", "item2", "item3", False, True}
    normalized = ", ".join(sorted(repr(e) for e in my_set))
    with pytest.raises(
        ValueError, match=f"参数 reorder 需要是 {normalized} 其中之一。"
    ):
        check_items("new")

在这种情况下,无论如何排列集合,消息都将显示为

参数 reorder 需要是 'item1', 'item2', 'item3', False, True 其中之一
英文:

We can "normalize" the set by sorting the repr of each set element. That way, the result will be in order:

#!/usr/bin/env python3
import pytest


def check_items(item):
    my_set = {True, False, "item1", "item2", "item3"}
    if item not in my_set:
        normalized = ", ".join(sorted(repr(e) for e in my_set))
        raise ValueError(f"Parameter reorder needs to be one of {normalized}.")
    return item




def test_check_items_error():
    my_set = {"item1", "item2", "item3", False, True}
    normalized = ", ".join(sorted(repr(e) for e in my_set))
    with pytest.raises(
        ValueError, match=f"Parameter reorder needs to be one of {normalized}"
    ):
        check_items("new")

In this case, no matter how your order your set, the message will come out to be

Parameter reorder needs to be one of 'item1', 'item2', 'item3', False, True.

huangapple
  • 本文由 发表于 2023年6月8日 23:33:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76433507.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定