使用py.test在Python中测试正则表达式

时间:2014-04-02 17:39:09

标签: python unit-testing python-3.x pytest

对我来说,正则表达式仍然是一种黑暗艺术,但我认为这只是需要练习的事情之一。因此,我更关心能够生成py.test函数,告诉我我的正则表达式失败的地方。我目前的代码是这样的:

my_regex = re.compile("<this is where the magic (doesn't)? happen(s)?>")

def test_my_regex():
    tests = ["an easy test that I'm sure will pass",
             "a few things that may trip me up",
             "a really pathological, contrived example",
             "something from the real world?"]

    test_matches = [my_regex.match(test) for test in tests]

    for i in range(len(tests)):
        print("{}: {!r}".format(i, tests[i]))
        assert test_matches[i] is not None

我运行py.test myfile.py时的输出类似于

0: "an easy..."
1: "a few things..."
2: "a really pathological..."

其中最后一个是第一个(仅?)未通过测试的那个。

我想我可以做一些像

这样的事情
assertSequenceEqual(test_matches, [not None]*len(test_matches))

但这似乎很严重,而且我认为<object> is not None是检查对象不是None而不是<object> != None的首选方式。

2 个答案:

答案 0 :(得分:15)

另一种方法是使用parametrize

my_regex = re.compile("<this is where the magic (doesn't)? happen(s)?>")

@pytest.mark.parametrize('test_str', [
    "an easy test that I'm sure will pass",
    "a few things that may trip me up",
    "a really pathological, contrived example",
    "something from the real world?",
])
def test_my_regex(test_str):
     assert my_regex.match(test_str) is not None

这将为每个测试字符串生成一个独立的测试用例。此IMO更清晰,更容易添加新案例,并且还具有允许每个test_str单独失败而不影响其他IMO的优势。

答案 1 :(得分:3)

您可以使用all

assert all([my_regex.match(test) for test in goodinputs])

您可能还想测试不匹配的输入,并测试带有否定的any的输入。

assert not any([my_regex.match(test) for test in badinputs])

如果您想查看哪些匹配失败,您可以稍微重新组织现有代码,例如:

for test in tests:
    assert my_regex.match(test), test
如果断言失败,

应该打印出test的值。

但是,这只会打印出第一次失败的细节。

如果您想查看所有失败,可以执行以下操作:

failures = [test for test in tests if not my_regex.match(test)]
assert len(failures) == 0, failures