When are things normally converted to true/false?
The question you are really asking is "what happens when you convert a list or dictionary to bool?". That's because if x: and assert x behave identically to if you wrote if bool(x): or assert bool(x). (By the way, putting that explicit call to bool() in those places is bad form, precisely because it's redundant.)
The answer is that lists and dictionaries (and strings and other containers) are True when converted to bool if they are not empty. Conversely, they're False when converted to bool if they are empty.
The terminology often used for this is that non-empty containers are "truthy" and empty containers are "falsey".
This has the interesting consequence that bool("False") evaluates to True - because "False" is a non-empty string!
Aside from containers, there are some other usual cases: numbers are truethy if they're non-zero (i.e. 27 and 0.5 are truthey while 0 and 0.0 are falsey), and the value None is falsey.
How to find out for other classes
how could I have checked the internals of this behavior ?
As said above, anything that is sufficiently like a collection is truethy when it's non-empty; the usual test for whether it's "like a container" is whether you can call len(x) successfully on it, in which case it is truethy whenever len(x) is non-zero.
Even if a class is not a container (or a number), it is still possible that it has some meaningful conversion to bool(). In fact you can even define this on your own classes by defining a __bool__() method. The only way to determine that, short of looking at the source code, is to look at the documentation for the library you're using.
If there is no such conversion defined by the library then bool(x) will just always return True (that's the default for classes with no __bool__() or __len__() methods defined). See Truth value testing in the official Python docs for a bit more information.
ElementTree specifically
xml.etree.ElementTree in particular, things are unfortunately a bit confusing. A looks a little bit like a container of elements: e[0] returns the first child element, and for child in e returns all the children, and len(e) returns the count of child elements (these are all documented in the official docs). It therefore makes perfect sense that bool(e) is true exactly when there is at least one child element - that fits with how all the rest of Python works. However, as Tomerikoo's answer shows in the source code, while this currently works, it's deprecated and may not work in future. The docs also mention this but it is extremely buried:
Caution: Elements with no subelements will test as False. This behavior will change in future versions. Use specific len(elem) or elem is None test instead.
The confusing logic behind this is explained in the code snippet below. The background is, maybe_child = e.find("child") finds a subelement of e with name "child", or None if no such element is found. But None is falsey, so it's tempting to check if this search succeeded by writing if maybe_child: - but that will actually count as False if a child was found but had no child elements itself. Here's the snippet from the docs:
element = root.find('foo')
if not element: # careful!
print("element not found, or element has no subelements")
if element is None:
print("element not found")