Unit testing type alias declarations

When I declare a non-trivial type alias, I want to add “tests” to confirm that the type alias does what I think it does. For example, suppose I have the following declaration:

type AllowedVariable = (
    str | int | Decimal | bool | dict[str, AllowedVariable] | list[AllowedVariable]
)

Then I can effectively use my static type checker (in my case, mypy) to test that this does include cases I intend to include by adding something like:

# Test AllowedVariable is compatible with intended types
_valid_str: AllowedVariable = "a string"
_valid_list: AllowedVariable = [1, 2, 3, 4]
_valid_nested_dict: AllowedVariable = {
            "a": {"c": [Decimal("2.0")]},
            "b": {"d": [Decimal("2.0"), Decimal("3.0")]},
        }

If the type alias declaration isn’t compatible with one of my intended valid values, the type checker will complain.

However, I don’t see a way to check that the declaration is excluding things that I don’t want/expect. Ideally, I’m looking for something like:

from typing import assert_compatible, assert_incompatible

assert_compatible("a string", AllowedVariable)
valid_nested_dict = {
            "a": {"c": [Decimal("2.0")]},
            "b": {"d": [Decimal("2.0"), Decimal("3.0")]},
        }
assert_compatible(valid_nested_dict, AllowedVariable)
invalid_nested_dict = {
            "a": {6: [Decimal("2.0")]},
            "b": {7: [Decimal("2.0"), Decimal("3.0")]},
        }
assert_incompatible(invalid_nested_dict, AllowedVariable)

Is there a way to achieve this that I’m missing?

The best way to do negative tests is to enable warn-unused-ignores and then add a type:ignore for the assignments that are supposed to fail, optionally with the specific error you’re expecting to occur. That’s how the tests in typeshed are written.

5 Likes

See also Testing and Ensuring Type Annotation Quality — typing documentation

2 Likes

Thank you! This makes sense.