精确地:适用于Python的Matcher库

2021-02-18 18:45:23

精确地允许您编写精确的断言,以便仅测试您真正感兴趣的行为。这使读者可以更清楚地了解预期的行为,并使测试不那么脆弱。这还可以生成更好的错误消息断言失败时受Hamcrest的启发。

例如,假设我们要确保一个唯一函数从列表中删除重复项,我们可以编写如下测试:

从精确导入assert_that,contains_exactly def test_unique_removes_duplicates():结果=唯一([" a&#34 ;、" a&#34 ;、" b&#34 ;、" a&#34 ;," b"])assert_that(结果,contains_exactly(" a&#34 ;," b"))

只要结果包含" a&#34 ;,声明就会通过。和" b"不同于断言结果== [" a&#34 ;," b"],我们的断言忽略元素的顺序。当以下情况时,此方法很有用:

如果唯一声明了特定的顺序,则我们将测试实现而不是合同。

订单是在唯一性合同中指定的,但订单是在单独的测试用例中进行测试的。

当断言失败时,错误消息将不仅仅是更详细地描述失败,而不仅仅是声明两个值不相等。例如,如果unique具有值[" a&#34 ;,&# 34; a"," b"],我们会收到失败消息:

预期:以任意顺序包含的可迭代:*' a' *&b'但是:有额外的元素:*' a'

许多匹配器由其他匹配器组成。如果给它们一个值而不是一个匹配器,则该值将被包装在equal_to()中,例如has_attrs(name =" bob")等同于has_attrs(名称= equal_to(&bob"))。

has_attr(attribute_name,matcher):如果具有指定的属性,则匹配一个值。当属性名称为常数时,通常认为has_attrs更惯用,例如,代替:

assert_that(结果,contains_exactly(" a&#34 ;," b"))#匹配[" a&#34 ;、" b"]和[&# 34; b"," a"],但不是[[## a"," a"," b"] " a"]或[" a&#34 ;、" b&#34 ;、" c"]

is_sequence(* args):如果一个元素具有相同的顺序,则匹配一个iterable,例如:

assert_that(result,is_sequence(" a&#34 ;," b"))#匹配[" a&#34 ;," b"]#但不匹配[ " a"]或[" a&#34 ;、" b&#34 ;、" c"]或[& #34; c"," a"," b"]

assert_that(结果,包括(" a&#34 ;、" b"))#匹配[" a&#34 ;、" b"],[&# 34; b"," a"]和[" a"," c"," b"]#而非[& #34; a"," c"]或[" a"] assert_that(结果,包括(" a&#34 ;、" a&#34 ;))#匹配[" a&#34 ;," a"]和[" a&#34 ;、" a&#34 ;、" a&# 34;]#,但不是[" a"]

is_mapping(matchers):如果映射具有相同的键和匹配的值,则匹配一个映射,例如dict。如果该映射缺少任何键或具有任何额外的键,则会引发错误,例如:

mapping_includes(matchers):如果映射具有相同的键和匹配的值,则匹配一个映射,例如dict。如果该映射缺少任何键,但允许额外的键,则会引发错误,例如:

assert_that(result,mapping_includes({" a&#34 ;: equal_to(1)," b&#34 ;: equal_to(4),}))#匹配{" a&#34 ;: 1," b&#34 ;: 4}和{" a&#34 ;: 1," b&#34 ;: 4,4," c&#34 ;: 5}#但不是{" a&#34 ;: 1}也不是{" a&#34 ;: 1," b&#34 ;: 5}

为了清楚起见,它通常有助于将has_feature的使用提取到其自己的函数中:

PyHamcrest是匹配器的另一个Python实现。我更喜欢该项目产生的错误消息,但可以自行判断:

#准确地从精确导入assert_that,is_sequence,has_attrs assert_that([User(" bob&#34 ;," [email protected]"),User(" jim",& #34; [email protected]"),],is_sequence(has_attrs(用户名=" bob&#34 ;、电子邮件地址=" [email protected]"),has_attrs(用户名= " jim&#34 ;, email_address =" [email protected]"),))#预期的:可迭代的包含顺序:#0:属性:#*用户名:' bob&# 39; #* email_address:' [email protected]' #1:属性:#*用户名:' jim' #* email_address:' [email protected]' #但是:索引0处的元素不匹配:#*属性email_address:是' [email protected]' #hamcrest从hamcrest导入assert_that,包含has_properties assert_that([User(" bob&#34 ;," [email protected]"),User(" jim&#34 ;,& #34; [email protected]"),],包含(has_properties(用户名=" bob&#34 ;、电子邮件地址=" [email protected]"),has_properties(用户名= " jim&#34 ;, email_address =" [email protected]"),))#Hamcrest错误:#预期值:包含[(具有属性' username&#的对象的对象的序列39;匹配' bob'和具有&' email_address'匹配' [email protected]'的对象)(具有'用户名'匹配' jim'和对象的属性' email_address'匹配' [email protected]')]#但:项目0:对象具有属性' email_address'匹配' [email protected]'财产'电子邮件地址'是' [email protected]'