16

Of the many, many assert methods in Python's standard unittest package, .assertHasAttr() is curiously absent. While writing some unit tests I've run into a case in which I'd like to test for the presence of an attribute in an object instance.

What's a safe/correct alternative for the missing .assertHasAttr() method?

tel
  • 13,005
  • 2
  • 44
  • 62

3 Answers3

12

Came up with an answer as I was writing the question. Given a class/test case that inherits from unittest.TestCase, you can just add a method based on .assertTrue():

def assertHasAttr(self, obj, intendedAttr):
    testBool = hasattr(obj, intendedAttr)

    # python >=3.8 only, see below for older pythons
    self.assertTrue(testBool, msg=f'obj lacking an attribute. {obj=}, {intendedAttr=}')

Duh.

I didn't find anything on google when I was searching before, so I'll leave this here in case anyone else runs into a similar issue.

update

I've updated my answer to use the neat new "self-documenting" feature for f-strings that was added in python 3.8. If you want a assertHasAttr func that will be compatible with any python (including <=3.7), change the last line to instead be:

# last line of original answer, will work with any python
self.assertTrue(testBool, msg='obj lacking an attribute. obj: %s, intendedAttr: %s' % (obj, intendedAttr))
tel
  • 13,005
  • 2
  • 44
  • 62
7

You can write your own:

HAS_ATTR_MESSAGE = '{} should have an attribute {}'

class BaseTestCase(TestCase):

    def assertHasAttr(self, obj, attrname, message=None):
        if not hasattr(obj, attrname):
            if message is not None:
                self.fail(message)
            else:
                self.fail(HAS_ATTR_MESSAGE.format(obj, attrname))

Then you can subclass BaseTestCase insteadof TestCase with tests. For example:

class TestDict(BaseTestCase):

    def test_dictionary_attributes(self):
        self.assertHasAttr({}, 'pop')  # will succeed
        self.assertHasAttr({}, 'blablablablabla')  # will fail
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
3

Going for the most succint answer so far:

self.assertTrue(hasattr(myInstance, "myAttribute"))

altough Dan's hint in a comment to the OP is also a valid answer:

assert hasattr(myInstance, "myAttribute"))

just not quite as syntactically aligned with the typical assertions from the unittest package.

manu3d
  • 991
  • 1
  • 8
  • 23