In the following unit test, I get a typing error (using mypy or PyLance), because the type checker believes that ret might be an int, even though it has been asserted in the line before that it actually isn’t:
class TypeTest(unittest.TestCase):
def fut(self) -> list | int:
return [42]
def test_type(self):
ret = self.fut()
self.assertIsInstance(ret, list)
self.assertEqual(ret[0], 42) # typing error: not indexable
If I change the line self.assertIsInstance(value, list) to assert isinstance(value, list) then there is no typing error and everything works as expected.
The explanation is probably that the assert statement acts as a type guard, while the method self.assertIsInstance provided by the unittest module doesn’t.
A similar issue is this:
class TypeTest(unittest.TestCase):
def fut(self) -> list | None:
return [42]
def test_type(self):
ret = self.fut()
self.assertIsNotNone(ret , 42)
self.assertEqual(ret[0], 42) # typing error: not indexable
Again, if I change the line self.assertIsNotNone(value, 42) to assert ret is not None then everything is fine.
My suggestion is to make these assertions in the unittest module act as type guards, similar to the assert statement.
Thanks for your feedback @mdrissi and @davidfstr. Your’re right, the existing TypeGuard canot be used to implement this, we would need a TypeAssert or maybe a StrictTypeAssert. Maybe this is a good use case for extending PEP 647.