【问题标题】:How can I assert lists equality with pytest如何断言列表与 pytest 相等
【发布时间】:2018-04-05 11:15:40
【问题描述】:

我正在尝试使用 pytest 进行一些单元测试。

我正在考虑做这样的事情:

actual = b_manager.get_b(complete_set)
assert actual is not None
assert actual.columns == ['bl', 'direction', 'day']

第一个断言正常,但第二个断言出现值错误。

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

我认为用 pytest 断言两个不同列表的相等性不是正确的方法。

如何断言数据框列(列表)等于预期列?

谢谢

【问题讨论】:

  • 回溯包含一个提示...使用a.any()a.all()。 BTW assert 不是进行单元测试的“正常”方式
  • @Chris_Rands assert 是在pytest 下测试值的THE 方法。 pytest内部重写asserts的字节码,调用自己的比较函数。
  • actual.columns 是一个列表吗?回溯表明它是一个布尔值。
  • actual.columns 确实是一个列表。经过一些调查后,我意识到比较返回另一个带有布尔值的列表,以检查内容是否不同。 [True, False, True, True ..]. 这就是为什么我必须使用 .All().. 为了能够给 Assert 一个唯一的布尔值而不是布尔值列表
  • @Chris_Rands 我使用的是 pytest,而不是内置的 unittest 框架。那么进行单元测试的正常方法应该是什么?

标签: python unit-testing pytest


【解决方案1】:

在 Python 3.9 中,这现在应该可以工作了:

def test_arrays_equal():
    a = [1, 2, 3]
    b = [1, 2, 4]
    assert a == b

或者,您可以将列表解析为numpy 数组并使用函数array_equal

import numpy as np

def test_arrays_equal():
    a = [1, 2, 3]
    b = [1, 2, 4]
    ar = np.array(a)
    br = np.array(b)
    assert np.array_equal(ar, br)

【讨论】:

    【解决方案2】:

    在编写断言之前,请回答以下问题:

    1. 订单重要吗?
    2. 可以重复吗?
    3. 可以有不可散列的元素吗?

    不,不,不:集合中的对称差异

    a = [1, 2, 3]
    b = [3, 2, 1]
    diff = set(a) ^ set(b)
    assert not diff
    

    在大型列表上使用此方法很方便,因为diff 将只包含它们之间的差异,因此AssertionError 将是紧凑的并且 可读。

    注意set() 将删除重复项。最好也检查一下:

    assert len(a) == len(set(a))
    

    是,是,是:比较列表

    a = [1, 2, 3, {'a': 1}]
    b = [1, 2, 3, {'a': 1}]
    assert a == b
    

    【讨论】:

    • 这不适用于a = [1,1,2] and b = [1, 2, 2]等情况
    • 我已经更新了我的答案。由您决定要比较哪些列表参数。
    • sorted([1, {'a': 1}, 2, 3]) → "TypeError: 'sorted([{'a': 2}, {'a': 1}]) → "TypeError: '
    • 很好的答案。非常感谢。
    • @l0b0: 对于排序你可以使用sorted(..., key=id)
    【解决方案3】:

    你可以做一个列表推导来检查所有值的相等性。如果您在列表推导结果中调用all,如果所有参数都相等,它将返回True

    actual = ['bl', 'direction', 'day']
    expected = ['bl', 'direction', 'day']
    
    assert len(actual) == len(expected)
    assert all([a == b for a, b in zip(actual, expected)])
    
    print(all([a == b for a, b in zip(actual, expected)]))
    
    >>> True
    

    【讨论】:

    • @smerlung all() 采用可迭代对象,列表比较将返回布尔值。
    • 您忘记了列表长度检查。 zip() 函数以最小尺寸的列表切割输出。重写实际并将其设置为 ['bl', 'direction', 'day', 'MYAHAHA'] 甚至 [] 并获得 True :P 我将尝试重写您的示例。
    【解决方案4】:

    你也可以使用https://github.com/AdityaSavara/UnitTesterSG,可以通过pip UnitTesterSG获取

    【讨论】:

      【解决方案5】:

      将 numpy 数组转换为 python 列表,您将获得比简单地使用 allany 更好的响应。这样,如果测试失败,您将看到预期与实际有何不同

      【讨论】:

        【解决方案6】:

        this:

        注意:

        您可以简单地使用assert 语句来断言测试 期望。 pytest 的Advanced assertion introspection 将 智能地报告断言表达式的中间值 让您无需学习JUnit legacy methods 的众多名称。

        还有this:

        对一些案例进行了特殊比较:

        • 比较长字符串:显示上下文差异
        • 比较长序列:第一个失败的索引
        • 比较字典:不同的条目

        还有reporting demo

        failure_demo.py:59: AssertionError
        _______ TestSpecialisedExplanations.test_eq_list ________
        
        self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
        
            def test_eq_list(self):
        >       assert [0, 1, 2] == [0, 1, 3]
        E       assert [0, 1, 2] == [0, 1, 3]
        E         At index 2 diff: 2 != 3
        E         Use -v to get the full diff
        

        在那边看到与文字== 相等的列表的断言了吗? pytest 为您完成了艰苦的工作。

        【讨论】:

        • 好答案。应该被接受。请将实际代码示例带到答案中以使其更清晰。
        • 由于某种原因,即使我使用的是 pytest 4.3.0 版,我也会收到 ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 的错误消息
        • @AllenWang 您用于比较的一个或两个值很可能是 numpy 数组。在那种情况下,pytest 似乎会测试比较结果的 numpy 数组的真值,这是一个布尔值的 numpy 数组,并且 numpy 会产生上述警告。尝试用list() 包装这两个值。
        【解决方案7】:

        如果您使用的是内置的unittest.TestCase,那么已经有一种方法可以为您做到这一点:unittest.TestCase.assertListEqual 如果您关心列表排序,unittest.TestCase.assertCountEqual 如果您不关心。

        https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual

        【讨论】:

        • 我使用的是 pytest,而不是内置的 unittest 包。这就是为什么我不使用 assertListEqual..
        • 在 pytest 测试用例中调用 unittest.TestCase().assertCountEqual(first, second) 效果很好。如果断言失败,您将收到更糟糕的错误消息(在 assertCountEqual 方法中进行回溯),否则没有问题。
        猜你喜欢
        • 1970-01-01
        • 2012-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        相关资源
        最近更新 更多