Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

assertIsInstance() against multiple class names

I have a function which should set an object attribute to a PIL Image instance:

from PIL import Image

class SimpleExample:
    def __init__(self):
        self.img = self.load_image()

    def load_image():
        self.img = Image.open(image)

To test the proper execution of load_image() I thought to use unittest.TestCase.assertIsInstance(), but introspection of the resultant instance gives a different class.name depending on the file type of the image that was loaded. I can't find anything along the lines of assertIsInstanceFromModule() in unittest, so this seems to be the assertion helper that best reflects what I am really trying to test.

I have come up with a couple solutions but am not satisfied with either of them:

Use a loop Produce a list of all possible class names, iterate though list, test each member for equality, then assertIsInstance for the appropriate list member. This is awkward, unpythonic, and I'm certainly not very proud of it. It does however work, and it uses what I think is the most meaningful assertion.

simplified_names = ['JpegImageFile', 'PngImageFile']
for i, name in enumerate(simplified_names):
    if SimpleExample.img.__class__.__name__ == name:
        TestCase.assertIsInstance(SimpleExample.img, simplified_names[i])

Use a different assertion helper Produce a list of all possible class names and assert that the class name of the generated object is in that list. It works, it's simple, but I don't like what it is that I'm actually asserting here.

simplified_names = ['JpegImageFile', 'PngImageFile']
TestCase.assertIn(SimpleExample.img.__class__.__name__, simplified_names)

Does anyone have any other idea about how to assert against multiple possible class names? Should I be approaching the test from a different direction and use a different assertion? This is my first foray into unittest. Should I go back to just testing my code with print?

~~~~~ And the obvious answer is...

Test against parent class. Alternatively, I could have noticed that a better option was presented to me every time I saw the following error:

TypeError: isinstance() arg 2 must be a type or tuple of types

Emphasis on the "or tuple."

Thanks for all the help Martijn Pieters.

like image 584
Jeffrey Swan Avatar asked Jun 01 '26 21:06

Jeffrey Swan


1 Answers

Use the parent class; you don't care which one of the many subclasses this is, just if it is an image file.

The second argument of assertIsInstace() must be the class itself, not a class name:

from PIL import ImageFile

self.assertIsInstance(SimpleExample.img, ImageFile.ImageFile)

or you could go one step further up and assert that it is a PIL.Image.Image instance, and not care if it came from a specific file or was produced otherwise:

from PIL import Image

self.assertIsInstance(SimpleExample.img, Image.Image)

If you do ever need to test against multiple classes, isinstance() (and by extension, assertIsInstance()) also accepts a tuple of classes as the second argument:

>>> foo = 'bar'
>>> isinstance(foo, (str, int, float))
True
like image 88
Martijn Pieters Avatar answered Jun 04 '26 10:06

Martijn Pieters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!