首页 > 解决方案 > 如何测试应该在列表中与不同类的其他对象混合的对象的字段值?

问题描述

我正在使用 pytest 并尝试检查对象是否在其某个字段中具有正确的内容。我面临的问题是该对象出现在一个列表中,它可能位于任何位置,并且与来自不同类的对象混合在一起,而该字段甚至不存在。

下面你有一个测试我需要什么的例子。该示例按原样工作,但我认为这不是一个很好的解决方案,因为它正在测试中测试 2 个条件(列表中的实例和正确的内容,如果它找到实例)并且还因为不得不打破测试功能似乎不是很干净的。

有没有人有关于更优雅和正确的测试方法的建议?

import pytest

class Foo:
    def __init__(self,name):
        self.name = name

class Bar:
    pass

def test_instance_in_list():

    l = [Bar(), Foo('foo'), Bar()]                      # Will pass the test
#    l = [Bar(), Bar(), Bar()]                     # Will NOT pass the test - "No instance"
#    l = [Bar(), Foo('other name'), Bar()]     # Will NOT pass the test - "Assertion fail"

    for item in l:
        if isinstance(item,Foo):
            assert item.name == 'foo'
            return
    pytest.fail("There wasn't a Foo instance in the list")

针对这三个条件运行测试的预期输出是:

使用 l = [Bar(), Foo('foo'), Bar()] 运行的结果

test_is_instance.py .                                                           [100%]

================================== 1 passed in 0.01s ==================================

使用 l = [Bar(), Bar(), Bar()] 运行的结果

>       pytest.fail("There wasn't a Foo instance in the list")
E       Failed: There wasn't a Foo instance in the list

test_is_instance.py:21: Failed
================================== 1 failed in 0.03s ==================================

使用 l = [Bar(), Foo('other name'), Bar()] 运行的结果

>               assert item.name == 'foo'
E               AssertionError: assert 'something else' == 'foo'
E                 - something else
E                 + foo

test_is_instance.py:18: AssertionError
================================== 1 failed in 0.03s ==================================

感谢您的建议和帮助,以找到获得相同结果的更好方法:-) !!

标签: pythonpytest

解决方案


如果您不想在同一测试中检查实例的可用性,这可能是其他方法之一。

def get_params():
    l = [Foo('hello'), Bar(), Bar()]        
    obj_count =0
    for item in l:
        if isinstance(item,Foo):
            yield item.name
            obj_count +=1

    if obj_count ==0:
        yield None

@pytest.mark.parametrize('obj_val', [val if val !=None else pytest.param(val, marks=pytest.mark.xfail(reason="There was not a Foo instance in the list")) for val in get_params() ])
def test_instance_in_list(obj_val):
    assert obj_val == 'foo', "Object content not matched"

如果在列表中找不到实例,测试将返回 xfail,否则断言条件将检查对象内容


推荐阅读