How to assert that an iterable is not empty on Unittest?

After submitting queries to a service, I get a dictionary or a list back and I want to make sure it's not empty. I using Python 2.7.

I am surprised of not having any assertEmpty method for the unittest.TestCase class instance.

The existing alternatives just don't look right:

self.assertTrue(bool(d))
self.assertNotEqual(d,{})
self.assertGreater(len(d),0)

Is this kind of a missing method in the Python unittest framework? If yes, what would be the most pythonic way to assert that an iterable is not empty?


Solution 1:

Empty lists/dicts evaluate to False, so self.assertTrue(d) gets the job done.

Solution 2:

Depends exactly what you are looking for.

If you want to make sure the object is an iterable and it is not empty:

# TypeError: object of type 'NoneType' has no len()
# if my_iterable is None
self.assertTrue(len(my_iterable))

If it is OK for the object being tested to be None:

self.assertTrue(my_maybe_iterable)

Solution 3:

"Falsy" values in Python

A falsy (sometimes written falsey) value is a value that is considered false when encountered in a Boolean context.

According to the official doc, the following built-in types evaluate to false:

  • constants defined to be false: None and False.
  • zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • empty sequences and collections: '', (), [], {}, set(), range(0)

Therefore, it's possible to check for

  • non-emptiness with assertTrue() and for
  • emptiness with assertFalse().

(The official doc has a full list of all available assert methods.)

Clean Code

All those assertTrue() and assertFalse() calls are kind of misleading as we wanted to check for emptiness and one needs to know which types evaluate to false to properly understand what's happening in the test.

So, for the sake of clean code and for better readability, we can simply define our own assertEmpty() and assertNotEmpty() methods like so:

def assertEmpty(self, obj):
    self.assertFalse(obj)

def assertNotEmpty(self, obj):
    self.assertTrue(obj)

Solution 4:

Maybe:

self.assertRaises(StopIteration, next(iterable_object))