简体   繁体   English

如何在 pytest.raises() 中使用正则表达式来检查两个短语是否在错误消息字符串中

[英]How to use regex inside pytest.raises() to check if two phrases are in error message string

I would like to be able to check if text:我希望能够检查文本是否:

1 validation error for Person\nname\n  `name` is invalid, must be 3 characters long (type=value_error)

contains two phrases:包含两个短语:

validation error for Person and name is invalid, must be 3 characters long validation error for Person name is invalid, must be 3 characters long

It is important that it is done using only re.search() and regex pattern, because I want to use it inside pytest.raises(match=regex_pattern) (more info about pytest.raises in documentation )仅使用re.search()和正则表达式模式完成它很重要,因为我想在pytest.raises(match=regex_pattern)中使用它(有关pytest.raises的更多信息 在文档中

What is correct way to do this?这样做的正确方法是什么? (If possible I would prefer solution which doesn't care about order of phrases in text.) (如果可能的话,我更喜欢不关心文本中短语顺序的解决方案。)

I tried to do this in pattern3 and pattern4 below, however I can't figure out proper regex pattern.我尝试在下面的pattern3pattern4中执行此操作,但是我无法找出正确的正则表达式模式。

(Solution I tried is from Regular Expression to match two separate phrases ) (我尝试的解决方案是从正则表达式匹配两个单独的短语

import re

text = '1 validation error for Person\nname\n  `name` is invalid, must be 3 characters long (type=value_error)'


pattern1="`name` is invalid, must be 3 characters long"
result1 = re.search(pattern1, text)  # found

pattern2=re.escape('1 validation error for Person\nname\n  `name` is invalid, must be 3 characters long (type=value_error)')
result2 = re.search(pattern2, text)  # found

pattern3="(" +re.escape('validation error for Person')+ ").*(" + re.escape('`name` is invalid, must be 3 characters long') +")"
result3 = re.search(pattern3, text)  # not found

pattern4=re.escape('(validation error for Person).*(`name` is invalid, must be 3 characters long)')
result4 = re.search(pattern4, text)  # not found

In pytest tests below it is visible how I try to use this in test_person_invalid3 and test_person_invalid4 :在下面的pytest测试中,可以看到我如何尝试在test_person_invalid3test_person_invalid4中使用它:

import pytest
from pydantic import ValidationError, BaseModel, validator
import re

class Person(BaseModel):
    name: str

    @validator("name")
    def check_name(cls, v):
        if len(v) != 3:
            raise ValueError("`name` is invalid, must be 3 characters long")
        return v


def test_person_invalid1(): # works ok
    """`environment` invalid"""
    with pytest.raises(
        ValidationError,
        match='`name` is invalid, must be 3 characters long',
    ):
        person = Person(name="Olivia")

def test_person_invalid2(): # works ok
    """`environment` invalid"""
    with pytest.raises(
        ValidationError,
        match=re.escape('1 validation error for Person\nname\n  `name` is invalid, must be 3 characters long (type=value_error)'),
    ):
        person = Person(name="Olivia")

def test_person_invalid3(): # doesn't work
    """`environment` invalid"""
    with pytest.raises(
        ValidationError,
        match="(" +re.escape('validation error for Person')+ ").*(" + re.escape('`name` is invalid, must be 3 characters long') +")",   
    ):
        person = Person(name="Olivia")

def test_person_invalid4(): # doesn't work
    """`environment` invalid"""
    with pytest.raises(
        ValidationError,
        match=re.escape('(validation error for Person).*(`name` is invalid, must be 3 characters long)'),
    ):
        person = Person(name="Olivia")

Why don't you just check for substring?为什么不检查 substring?

For example:例如:

s = "1 validation error for Person\nname\n  `name` is invalid, must be 3 characters long (type=value_error)"
print("validation error for Person" in s and "`name` is invalid, must be 3 characters long" in s)

Output: Output:

True

If you want to use this with pytest.raises() check this:如果您想将此与pytest.raises()一起使用,请检查:

There's an alternate form of the pytest.raises() function where you pass a function that will be executed with the given *args and **kwargs and assert that the given exception is raised: pytest.raises() function 有另一种形式,您可以在其中传递 function ** 将使用给定的 *args 执行并断言给定的异常和引发:

pytest.raises(ExpectedException, func, *args, **kwargs) pytest.raises(ExpectedException, func, *args, **kwargs)

Source .来源

So, for example, you might want to write something like this:因此,例如,您可能想要编写如下内容:

def check_substring(string_to_check: str):
    sub_str_one = "validation error for Person"
    sub_str_two = "`name` is invalid, must be 3 characters long"
    if not (sub_str_one in string_to_check and sub_str_two in string_to_check):
        raise ValueError

And pass it to pytest.raises(ExpectedException, func, *args, **kwargs)并将其传递给pytest.raises(ExpectedException, func, *args, **kwargs)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM