Home » Python » python – How to test field value for an object that should be in a list mixed with other objects of different classes?-Exceptionshub

python – How to test field value for an object that should be in a list mixed with other objects of different classes?-Exceptionshub

Posted by: admin February 24, 2020 Leave a comment

Questions:

I am using pytest and trying to check if an object has the right content in one of its fields. The issue I face is that the object comes in a list where it could be in any position and mixed with objects from different classes where that field won’t even exist.

Below you have an example that tests what I need. The example works as it should but I think this is not a great solution because it is testing 2 conditions in a test (instance in list and correct content if it finds the instance) and also because having to break the test function does not seem very clean.

Does anyone have advice on a more elegant and correct way to test this?

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")

The expected outputs of running the test for the three conditions are:

Results of running with l = [Bar(), Foo(‘foo’), Bar()]

test_is_instance.py .                                                           [100%]

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

Results of running with 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 ==================================

Results of running with 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 ==================================

Thanks for your advice and help to find a better way of getting the same results 🙂 !!

How to&Answers:

This could one of the other approaches if you don’t want to check availability of instance in the same test.

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"

The test will return xfail if the instance is not found in the list, else assert condition will check the object content