Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expected mypy errors #105

Open
dcbaker opened this issue Oct 3, 2020 · 4 comments
Open

Expected mypy errors #105

dcbaker opened this issue Oct 3, 2020 · 4 comments
Assignees

Comments

@dcbaker
Copy link

dcbaker commented Oct 3, 2020

I'm working on a module specifically for use with typing, so I have tests that I expect to raise mypy warnings. It doesn't look like there's a way to mark tests as having expected errors.

@dmtucker
Copy link
Collaborator

dmtucker commented Oct 6, 2020

I'm not sure I understand the issue 🤔 Could you elaborate or provide an example?
My initial reaction is that controlling/suppressing mypy errors seems like a mypy configuration issue.

@dcbaker
Copy link
Author

dcbaker commented Oct 7, 2020

What I want is basically the equivalent of:

def test_func():
    with pytest.raises(Exception):
       func('Invalid input')

but for mypy errors. I want to verify that an error is happening. My use case is that I'm writing "const" protocols (think list with out any methods or operators that modify), and I want to ensure that if I have:

class MyProto(Protocol[T]):

    def __add__(self, other: T) -> MyProto[T]: ...

class MyClass(Generic[T])
    def __add__(self, other: T) -> MyClass[T]:
    def __iadd__(self, other: T) -> None:


def test_func() -> None:
    c: MyProto[str] = MyClass(['foo'])
    with mypyerror:
        c += 'bar'  # this is an error, getting it is a test pass, not getting it is a test fail

@dmtucker
Copy link
Collaborator

Interesting... I'm not aware of a way to do that, as written, but perhaps doing the same kind of thing the pytest-mypy tests do would work. For example,

def test_func(testdir):
    testdir.makepyfile('''
        class MyProto(Protocol[T]):
            def __add__(self, other: T) -> MyProto[T]: ...

        class MyClass(Generic[T]):
            def __add__(self, other: T) -> MyClass[T]: ...
            def __iadd__(self, other: T) -> None: ...

        c: MyProto[str] = MyClass(['foo'])
        c += 'bar'
    ''') 
    result = testdir.runpytest('--mypy') 
    result.assert_outcomes(failed=2)  # mypy exit status check fails too
    result.stdout.fnmatch_lines([ 
        '9: error: bad type error message etc*', 
    ])

In fact, you don't even really need pytest to be involved:

def test_func(testdir):
    testdir.makepyfile('''
        c: MyProto[str] = MyClass(['foo'])
        c += 'bar'
    ''') 
    result = testdir.run('mypy', 'test_func.py') 
    result.stdout.fnmatch_lines([ 
        'test_func.py:9: error: bad type error message etc*', 
    ])

@Avasam
Copy link

Avasam commented Aug 29, 2024

Can't you just add a type: ignore[error-code] on that line ?
Make sure that the following codes are enabled:

Then if the suppression comment is unused or incorrect, test will fail with a mypy error.

That's how typeshed does its static-type-checking tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants