Mypy static type checker plugin for Pytest

Related tags

Testingpytest-mypy
Overview

pytest-mypy

Mypy static type checker plugin for pytest

See Latest Release on PyPI

Features

  • Runs the mypy static type checker on your source files as part of your pytest test runs.
  • Does for mypy what the pytest-flake8 plugin does for flake8.
  • This is a work in progress – pull requests appreciated.

Installation

You can install "pytest-mypy" via pip from PyPI:

$ pip install pytest-mypy

Usage

You can enable pytest-mypy with the --mypy flag:

$ py.test --mypy test_*.py

Mypy supports reading configuration settings from a mypy.ini file. Alternatively, the plugin can be configured in a conftest.py to invoke mypy with extra options:

def pytest_configure(config):
    plugin = config.pluginmanager.getplugin('mypy')
    plugin.mypy_argv.append('--check-untyped-defs')

You can restrict your test run to only perform mypy checks and not any other tests by using the -m option:

py.test --mypy -m mypy test_*.py

License

Distributed under the terms of the MIT license, "pytest-mypy" is free and open source software

Issues

If you encounter any problems, please file an issue along with a detailed description.

Meta

Daniel Bader – @dbader_orghttps://dbader.org[email protected]

https://github.com/dbader/pytest-mypy

Comments
  • Add support for 3.8

    Add support for 3.8

    Just a nice quick change hopefully. I've ran tox and the tests passed but really I'm just making sure when used with 3.8 it no longer pulls in the version of mypy which depends on typed_ast as that's been removed in 3.8.

    I'm not very familiar with tox so correct me if I've made an erroneous change to the tox.ini (I ran tox -e py38 inside a 3.8-dev interpreter)

    opened by naphta 10
  • 0.8.1: pytest is failing because cannot find module named `is_always_missing`

    0.8.1: pytest is failing because cannot find module named `is_always_missing`

    I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

    • python3 -sBm build -w --no-isolation
    • install .whl file in </install/prefix>
    • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

    May I ask where I can find that is_always_missing module? I canmot find it on pypi :/ Here is pytest output:

    + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mypy-0.8.1-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mypy-0.8.1-2.fc35.x86_64/usr/lib/python3.8/site-packages
    + /usr/bin/pytest -ra
    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1, configfile: tox.ini, testpaths: tests
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    collected 50 items
    
    tests/test_pytest_mypy.py ............FFF...................................                                                                                         [100%]
    
    ================================================================================= FAILURES =================================================================================
    _________________________________________________________________ test_mypy_ignore_missings_imports[True] __________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0')>, xdist_args = ['-n', 'auto']
    
        def test_mypy_ignore_missings_imports(testdir, xdist_args):
            """
            Verify that --mypy-ignore-missing-imports
            causes mypy to ignore missing imports.
            """
            module_name = "is_always_missing"
            testdir.makepyfile(
                """
                    try:
                        import {module_name}
                    except ImportError:
                        pass
                """.format(
                    module_name=module_name,
                ),
            )
            result = testdir.runpytest_subprocess("--mypy", *xdist_args)
            mypy_file_checks = 1
            mypy_status_check = 1
            mypy_checks = mypy_file_checks + mypy_status_check
            result.assert_outcomes(failed=mypy_checks)
    >       result.stdout.fnmatch_lines(
                [
                    "2: error: Cannot find *module named '{module_name}'".format(
                        module_name=module_name,
                    ),
                ],
            )
    E       Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0'
    E           and: 'plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7'
    E           and: 'gw0 I / gw1 I / gw2 I / gw3 I / gw4 I / gw5 I / gw6 I / gw7 I / gw8 I / gw9 I / gw10 I / gw11 I'
    E           and: 'gw0 [2] / gw1 [2] / gw2 [2] / gw3 [2] / gw4 [2] / gw5 [2] / gw6 [2] / gw7 [2] / gw8 [2] / gw9 [2] / gw10 [2] / gw11 [2]'
    E           and: ''
    E           and: 'FF                                                                       [100%]'
    E           and: '=================================== FAILURES ==================================='
    E           and: '_________________________________ test session _________________________________'
    E           and: '[gw1] linux -- Python 3.8.12 /usr/bin/python3'
    E           and: 'mypy exited with status 1.'
    E           and: '_____________________ test_mypy_ignore_missings_imports.py _____________________'
    E           and: '[gw0] linux -- Python 3.8.12 /usr/bin/python3'
    E           and: '2: error: Cannot find implementation or library stub for module named "is_always_missing"'
    E           and: '2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports'
    E           and: '===================================== mypy ====================================='
    E           and: 'Found 1 error in 1 file (checked 1 source file)'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy-status'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy'
    E           and: '============================== 2 failed in 13.08s =============================='
    E       remains unmatched: "2: error: Cannot find *module named 'is_always_missing'"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1/tests/test_pytest_mypy.py:119: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0/runpytest-0 --mypy -n auto
         in: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    gw0 I / gw1 I / gw2 I / gw3 I / gw4 I / gw5 I / gw6 I / gw7 I / gw8 I / gw9 I / gw10 I / gw11 I
    gw0 [2] / gw1 [2] / gw2 [2] / gw3 [2] / gw4 [2] / gw5 [2] / gw6 [2] / gw7 [2] / gw8 [2] / gw9 [2] / gw10 [2] / gw11 [2]
    
    FF                                                                       [100%]
    =================================== FAILURES ===================================
    _________________________________ test session _________________________________
    [gw1] linux -- Python 3.8.12 /usr/bin/python3
    mypy exited with status 1.
    _____________________ test_mypy_ignore_missings_imports.py _____________________
    [gw0] linux -- Python 3.8.12 /usr/bin/python3
    2: error: Cannot find implementation or library stub for module named "is_always_missing"
    2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
    ===================================== mypy =====================================
    Found 1 error in 1 file (checked 1 source file)
    =========================== short test summary info ============================
    FAILED test_mypy_ignore_missings_imports.py::mypy-status
    FAILED test_mypy_ignore_missings_imports.py::mypy
    ============================== 2 failed in 13.08s ==============================
    _________________________________________________________________ test_mypy_ignore_missings_imports[False] _________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1')>, xdist_args = []
    
        def test_mypy_ignore_missings_imports(testdir, xdist_args):
            """
            Verify that --mypy-ignore-missing-imports
            causes mypy to ignore missing imports.
            """
            module_name = "is_always_missing"
            testdir.makepyfile(
                """
                    try:
                        import {module_name}
                    except ImportError:
                        pass
                """.format(
                    module_name=module_name,
                ),
            )
            result = testdir.runpytest_subprocess("--mypy", *xdist_args)
            mypy_file_checks = 1
            mypy_status_check = 1
            mypy_checks = mypy_file_checks + mypy_status_check
            result.assert_outcomes(failed=mypy_checks)
    >       result.stdout.fnmatch_lines(
                [
                    "2: error: Cannot find *module named '{module_name}'".format(
                        module_name=module_name,
                    ),
                ],
            )
    E       Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1'
    E           and: 'plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7'
    E           and: 'collected 2 items'
    E           and: ''
    E           and: 'test_mypy_ignore_missings_imports.py FF                                  [100%]'
    E           and: ''
    E           and: '=================================== FAILURES ==================================='
    E           and: '_____________________ test_mypy_ignore_missings_imports.py _____________________'
    E           and: '2: error: Cannot find implementation or library stub for module named "is_always_missing"'
    E           and: '2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports'
    E           and: '_________________________________ test session _________________________________'
    E           and: 'mypy exited with status 1.'
    E           and: '===================================== mypy ====================================='
    E           and: 'Found 1 error in 1 file (checked 1 source file)'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy-status'
    E           and: '============================== 2 failed in 11.33s =============================='
    E       remains unmatched: "2: error: Cannot find *module named 'is_always_missing'"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1/tests/test_pytest_mypy.py:119: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1/runpytest-0 --mypy
         in: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    collected 2 items
    
    test_mypy_ignore_missings_imports.py FF                                  [100%]
    
    =================================== FAILURES ===================================
    _____________________ test_mypy_ignore_missings_imports.py _____________________
    2: error: Cannot find implementation or library stub for module named "is_always_missing"
    2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
    _________________________________ test session _________________________________
    mypy exited with status 1.
    ===================================== mypy =====================================
    Found 1 error in 1 file (checked 1 source file)
    =========================== short test summary info ============================
    FAILED test_mypy_ignore_missings_imports.py::mypy
    FAILED test_mypy_ignore_missings_imports.py::mypy-status
    ============================== 2 failed in 11.33s ==============================
    _________________________________________________________________ test_mypy_ignore_missings_imports[None] __________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2')>, xdist_args = ['-p', 'no:xdist']
    
        def test_mypy_ignore_missings_imports(testdir, xdist_args):
            """
            Verify that --mypy-ignore-missing-imports
            causes mypy to ignore missing imports.
            """
            module_name = "is_always_missing"
            testdir.makepyfile(
                """
                    try:
                        import {module_name}
                    except ImportError:
                        pass
                """.format(
                    module_name=module_name,
                ),
            )
            result = testdir.runpytest_subprocess("--mypy", *xdist_args)
            mypy_file_checks = 1
            mypy_status_check = 1
            mypy_checks = mypy_file_checks + mypy_status_check
            result.assert_outcomes(failed=mypy_checks)
    >       result.stdout.fnmatch_lines(
                [
                    "2: error: Cannot find *module named '{module_name}'".format(
                        module_name=module_name,
                    ),
                ],
            )
    E       Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2'
    E           and: 'plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7'
    E           and: 'collected 2 items'
    E           and: ''
    E           and: 'test_mypy_ignore_missings_imports.py FF                                  [100%]'
    E           and: ''
    E           and: '=================================== FAILURES ==================================='
    E           and: '_____________________ test_mypy_ignore_missings_imports.py _____________________'
    E           and: '2: error: Cannot find implementation or library stub for module named "is_always_missing"'
    E           and: '2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports'
    E           and: '_________________________________ test session _________________________________'
    E           and: 'mypy exited with status 1.'
    E           and: '===================================== mypy ====================================='
    E           and: 'Found 1 error in 1 file (checked 1 source file)'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy-status'
    E           and: '============================== 2 failed in 11.25s =============================='
    E       remains unmatched: "2: error: Cannot find *module named 'is_always_missing'"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1/tests/test_pytest_mypy.py:119: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2/runpytest-0 --mypy -p no:xdist
         in: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    collected 2 items
    
    test_mypy_ignore_missings_imports.py FF                                  [100%]
    
    =================================== FAILURES ===================================
    _____________________ test_mypy_ignore_missings_imports.py _____________________
    2: error: Cannot find implementation or library stub for module named "is_always_missing"
    2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
    _________________________________ test session _________________________________
    mypy exited with status 1.
    ===================================== mypy =====================================
    Found 1 error in 1 file (checked 1 source file)
    =========================== short test summary info ============================
    FAILED test_mypy_ignore_missings_imports.py::mypy
    FAILED test_mypy_ignore_missings_imports.py::mypy-status
    ============================== 2 failed in 11.25s ==============================
    ========================================================================= short test summary info ==========================================================================
    FAILED tests/test_pytest_mypy.py::test_mypy_ignore_missings_imports[True] - Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    FAILED tests/test_pytest_mypy.py::test_mypy_ignore_missings_imports[False] - Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    FAILED tests/test_pytest_mypy.py::test_mypy_ignore_missings_imports[None] - Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    ================================================================= 3 failed, 47 passed in 588.13s (0:09:48) =================================================================
    
    opened by kloczek 9
  • Build requirements are too strict

    Build requirements are too strict

    I'd like to package pytest-mypy for OpenIndiana, but it is very hard to do so because build requirements for pytest-mypy are these (from pyproject.toml):

    [build-system]
    requires = ['setuptools ~= 50.3.0', 'setuptools-scm[toml] ~= 5.0.0', 'wheel ~= 0.36.0']
    build-backend = 'setuptools.build_meta'
    

    The latest acceptable versions of required tools are about two years old now.

    Could you please update pytest-mypy to relax its build requirements?

    Thank you.

    opened by mtelka 8
  • The exclude option is being ignored

    The exclude option is being ignored

    I am using pytest-mypy 0.8.0 to check ts_salobj (see link below). It had a generated version.py file that makes mypy unhappy so I am trying to exclude that (on branch tickets/DM-31000, see link below). My configuration works if I run mypy from the command line:

    mypy python tests
    

    but if run mypy using pytest-mypy then version.py is processed and the test fails:

    pytest -v -m mypy
    

    My configuration includes verbosity=1 and the output shows that version\.py is marked as excluded in both cases, but somehow pytest is pulling it in anyway.

    I am not sure how pytest is running mypy. Even with verbosity 2 I can't tell pytest-mypy tells mypy which files to test. I suspect that pytest-mypy is explicitly ordering mypy to test each file and am hoping there is some way to tell it to exclude version.py.

    The packages is here https://github.com/lsst-ts/ts_salobj/tree/tickets/DM-31000 and that ticket branch is the one with my attempted changes (including committing the offending version.py file, which normally is not in git).

    I admit that I am specifying the mypy config in setup.cfg and the pytest-mypy docs say to use mypy.ini. However, pytest-mypy is clearly using the configuration, based on the verbosity and the resulting log. Also moving or copying the mypy configuration to a new mypy.ini file makes no difference. Here is an excerpt from the printed output from pytest -v -m mypy:

    LOG:  Mypy Version:           0.812
    LOG:  Config File:            setup.cfg
    LOG:  Configured Executable:  /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Current Executable:     /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Cache Dir:              .mypy_cache
    LOG:  Compiled:               True
    LOG:  Exclude:                version\.py
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/setup.py', module='setup', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj')
    ...
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/validator.py', module='salobj.validator', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/version.py', module='salobj.version', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/topics/__init__.py', module='salobj.topics', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    

    and a log from the command line:

    LOG:  Mypy Version:           0.812
    LOG:  Config File:            setup.cfg
    LOG:  Configured Executable:  /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Current Executable:     /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Cache Dir:              .mypy_cache
    LOG:  Compiled:               True
    LOG:  Exclude:                version\.py
    LOG:  Found source:           BuildSource(path='python/lsst/ts/salobj/__init__.py', module='salobj', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    ...
    LOG:  Found source:           BuildSource(path='python/lsst/ts/salobj/validator.py', module='salobj.validator', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    LOG:  Found source:           BuildSource(path='tests/data/minimal_salobj_controller.py', module='minimal_salobj_controller', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/tests/data')
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/topics/__init__.py', module='salobj.topics', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    

    notice that version.py is not listed as a "Found source" in the second case.

    opened by r-owen 8
  • Update dependency from mypy-lang to mypy

    Update dependency from mypy-lang to mypy

    When trying to use a development snapshot of mypy (through pip install git+https://github.com/python/mypy.git\#egg\=mypy), the current setup.py is ignoring the existing mypy installation because it doesn't match mypy-lang, making such use impossible.

    Apparently mypy's maintainers managed to get access to mypy in PyPI, and their setup.py now builds using this very name.

    This fix consists of dropping the dependency on mypy-lang and adding a new one on mypy requiring version 0.470 or newer, which is the earliest version available on PyPI for this newly named package.

    opened by lastmikoi 8
  • Fix automatic release deployment

    Fix automatic release deployment

    Resolve #104

    This will not work until the project has repository secrets for PYPI_USERNAME and PYPI_PASSWORD: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository

    I don't have permission to do that, so @dbader will have to do it.

    opened by dmtucker 7
  • Why not just use `mypy`and

    Why not just use `mypy`and "pytest`? What are the advantages of the "pytest-mypy" package?

    Sorry for my noob question, but what is the purpose of the package? I can run in a terminal locally or at a cloud's CI/CD the following two commands:

    >  mypy src/ && mypy tests/
    >  pytest tests/ 
    

    So why waste time on a new package development instead of just running two simple commands?

    opened by AIGeneratedUsername 7
  • AttributeError: 'MypyStatusItem' object has no attribute '_obj'

    AttributeError: 'MypyStatusItem' object has no attribute '_obj'

    Hey,

    I'm using both pytest-mypy and allure-pytest together and when I generate the report, I'm getting weird errors I don't know how to solve.

    Can you help me please?

    Test Code

    import allure
    
    
    def test_mypy1():
    
        def foo(arg: str) -> int:
            return arg
    
    
    @allure.severity(allure.severity_level.MINOR)
    def test_mypy2():
    
        def boo() -> int:
            return 10
    
    
    def test_mypy3():
    
        def boo() -> int:
            return 'I should have been an int'
    

    Error: AttributeError: 'MypyStatusItem' object has no attribute '_obj'

    cls = <class '_pytest.runner.CallInfo'>
    func = <function call_runtest_hook.<locals>.<lambda> at 0x7f855c16a3b0>
    when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    .venv/lib/python3.7/site-packages/_pytest/runner.py:311: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    >       lambda: ihook(item=item, **kwds), when=when, reraise=reraise
        )
    
    .venv/lib/python3.7/site-packages/_pytest/runner.py:255: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <_HookCaller 'pytest_runtest_setup'>, args = ()
    kwargs = {'item': <MypyStatusItem mypy>}, notincall = set()
    
        def __call__(self, *args, **kwargs):
            if args:
                raise TypeError("hook calling supports only keyword arguments")
            assert not self.is_historic()
            if self.spec and self.spec.argnames:
                notincall = (
                    set(self.spec.argnames) - set(["__multicall__"]) - set(kwargs.keys())
                )
                if notincall:
                    warnings.warn(
                        "Argument(s) {} which are declared in the hookspec "
                        "can not be found in this hook call".format(tuple(notincall)),
                        stacklevel=2,
                    )
    >       return self._hookexec(self, self.get_hookimpls(), kwargs)
    
    .venv/lib/python3.7/site-packages/pluggy/hooks.py:286: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <_pytest.config.PytestPluginManager object at 0x7f8558758150>
    hook = <_HookCaller 'pytest_runtest_setup'>
    methods = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/Users/nusnus/dev/flask_tester/.venv/lib/python3.7/...855c013450>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f855c034b90>>]
    kwargs = {'item': <MypyStatusItem mypy>}
    
        def _hookexec(self, hook, methods, kwargs):
            # called from all hookcaller instances.
            # enable_tracing will set its own wrapping function at self._inner_hookexec
    >       return self._inner_hookexec(hook, methods, kwargs)
    
    .venv/lib/python3.7/site-packages/pluggy/manager.py:93: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    hook = <_HookCaller 'pytest_runtest_setup'>
    methods = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/Users/nusnus/dev/flask_tester/.venv/lib/python3.7/...855c013450>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f855c034b90>>]
    kwargs = {'item': <MypyStatusItem mypy>}
    
        self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
            methods,
            kwargs,
    >       firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
        )
    
    .venv/lib/python3.7/site-packages/pluggy/manager.py:87: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    hook_impls = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/Users/nusnus/dev/flask_tester/.venv/lib/python3.7/...855c013450>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f855c034b90>>]
    caller_kwargs = {'item': <MypyStatusItem mypy>}, firstresult = False
    
        def _multicall(hook_impls, caller_kwargs, firstresult=False):
            """Execute a call into multiple python functions/methods and return the
            result(s).
        
            ``caller_kwargs`` comes from _HookCaller.__call__().
            """
            __tracebackhide__ = True
            results = []
            excinfo = None
            try:  # run impl and wrapper setup functions in a loop
                teardowns = []
                try:
                    for hook_impl in reversed(hook_impls):
                        try:
                            args = [caller_kwargs[argname] for argname in hook_impl.argnames]
                        except KeyError:
                            for argname in hook_impl.argnames:
                                if argname not in caller_kwargs:
                                    raise HookCallError(
                                        "hook call must provide argument %r" % (argname,)
                                    )
        
                        if hook_impl.hookwrapper:
                            try:
                                gen = hook_impl.function(*args)
                                next(gen)  # first yield
                                teardowns.append(gen)
                            except StopIteration:
                                _raise_wrapfail(gen, "did not yield")
                        else:
                            res = hook_impl.function(*args)
                            if res is not None:
                                results.append(res)
                                if firstresult:  # halt further impl calls
                                    break
                except BaseException:
                    excinfo = sys.exc_info()
            finally:
                if firstresult:  # first result hooks return a single value
                    outcome = _Result(results[0] if results else None, excinfo)
                else:
                    outcome = _Result(results, excinfo)
        
                # run all wrapper post-yield blocks
                for gen in reversed(teardowns):
                    try:
    >                   gen.send(outcome)
    
    .venv/lib/python3.7/site-packages/pluggy/callers.py:203: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <allure_pytest.listener.AllureListener object at 0x7f855c013450>
    item = <MypyStatusItem mypy>
    
        @pytest.hookimpl(hookwrapper=True)
        def pytest_runtest_setup(self, item):
            if not self._cache.get(item.nodeid):
                uuid = self._cache.push(item.nodeid)
                test_result = TestResult(name=item.name, uuid=uuid, start=now(), stop=now())
                self.allure_logger.schedule_test(uuid, test_result)
        
            yield
        
            uuid = self._cache.get(item.nodeid)
            test_result = self.allure_logger.get_test(uuid)
            for fixturedef in _test_fixtures(item):
                group_uuid = self._cache.get(fixturedef)
                if not group_uuid:
                    group_uuid = self._cache.push(fixturedef)
                    group = TestResultContainer(uuid=group_uuid)
                    self.allure_logger.start_group(group_uuid, group)
                self.allure_logger.update_group(group_uuid, children=uuid)
            params = item.callspec.params if hasattr(item, 'callspec') else {}
        
    >       test_result.name = allure_name(item, params)
    
    .venv/lib/python3.7/site-packages/allure_pytest/listener.py:88: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    item = <MypyStatusItem mypy>, parameters = {}
    
        def allure_name(item, parameters):
            name = escape_name(item.name)
    >       title = allure_title(item)
    
    .venv/lib/python3.7/site-packages/allure_pytest/utils.py:110: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    item = <MypyStatusItem mypy>
    
        def allure_title(item):
    >       return getattr(item._obj, '__allure_display_name__', None)
    E       AttributeError: 'MypyStatusItem' object has no attribute '_obj'
    
    .venv/lib/python3.7/site-packages/allure_pytest/utils.py:34: AttributeError
    
    opened by Nusnus 7
  • False positives using when using pytest-xdist -f (--looponfail)

    False positives using when using pytest-xdist -f (--looponfail)

    When doing TDD, after the first mypy error, the plugin start emitting errors on collection.

    It will continue normally until you hit an actual mypy fail, then in the follow round (after mypy error is fixed) this warning is emitted forever until pytest is killed and restarted.

    Steps to Reproduce (assumes python 3.8 and pipenv available):

    1. mkdir ~/tmp20200412
    2. cd ~/tmp20200412
    3. git clone [email protected]:y2kbugger/test_driven_development_by_example_tdd_follow_along.git
    4. cd ./test*
    5. git checkout b0a2f56
    6. replicate versions exactly from Pipfile.lock pipenv sync
    7. put venv on PATH pipenv shell
    8. run pytest pytest --mypy -f money.py test_money.py

    In another terminal:

    1. cd ~/tmp20200412/test*
    2. cause mypy error echo 'lol: str = 2' >> money.py
    3. undo mypy error git checkout b0a2f56 -- .
    ###################################### waiting for changes #######################################
    ### Watching:   /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    # MODIFIED /home/y2k/devel/test_driven_development_by_example_tdd_follow_along/money.py
    ============================= test session starts ==============================
    platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
    rootdir: /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    plugins: forked-1.1.3, mypy-0.6.1, xdist-1.31.0, flake8-1.0.4
    collected 0 items / 1 error
    collected 0 items / 1 error
    
    ==================================== ERRORS ====================================
    ________________________ ERROR collecting test session _________________________
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/runner.py:244: in from_call
        result = func()
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/runner.py:264: in <lambda>
        call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/main.py:498: in collect
        yield from self._collect(fspath, parts)
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/main.py:537: in _collect
        assert not names, "invalid arg {!r}".format((argpath, names))
    E   AssertionError: invalid arg (local('/home/y2k/devel/test_driven_development_by_example_tdd_follow_along'), ['mypy'])
    =========================== short test summary info ============================
    ERROR  - AssertionError: invalid arg (local('/home/y2k/devel/test_driven_deve...
    !!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
    =============================== 1 error in 0.22s ===============================
    ######################################### LOOPONFAILING ##########################################
    money.py::mypy
    test_money.py::test_multiplication
    test_money.py::test_franc_multiplication
    test_money.py::test_equality
    test_money.py::test_currency
    ::mypy
    ###################################### waiting for changes #######################################
    ### Watching:   /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    

    Note I kill with keyboard interrupt here:

    ^C
    

    Then everything goes fine again:

    (test_driven_development_by_example_tdd_follow_along) [[email protected] test_driven_development_by_example_tdd_follow_along]
    $ pytest --mypy -f money.py test_money.py 
    ============================= test session starts ==============================
    platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
    rootdir: /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    plugins: forked-1.1.3, mypy-0.6.1, xdist-1.31.0, flake8-1.0.4
    collected 7 items
    collected 7 items
    
    money.py .                                                               [ 12%]
    test_money.py ......                                                     [ 87%]
    . .                                                                      [100%]. [100%]
    ===================================== mypy =====================================
    
    Success: no issues found in 2 source files
    ============================== 9 passed in 0.34s ===============================
    ###################################### waiting for changes #######################################
    ### Watching:   /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    
    opened by y2kbugger 6
  • Only depend on mypy.api

    Only depend on mypy.api

    Fixes #6

    I think we should strongly discourage such use of interfaces internal to mypy. The only public APIs are the command line and the mypy.api module. https://github.com/python/mypy/issues/4681#issuecomment-371037599

    opened by dmtucker 6
  • Add --mypy-config option

    Add --mypy-config option

    Hello! I have not found how to pass path to mypy config?

    I want something like: pytest --mypy --mypy-config tox.ini

    It's because mypy isn't read config from tox.

    opened by pbelskiy 4
  • Upgrading to 0.10.2 leads to `exceptiongroup` error

    Upgrading to 0.10.2 leads to `exceptiongroup` error

    After upgrading to v0.10.2 my CI system started failing, giving the following error:

    Traceback (most recent call last):
      File "/home/alex/code/FINESSE/.venv/bin/pytest", line 5, in <module>
        from pytest import console_main
      File "/home/alex/code/FINESSE/.venv/lib/python3.9/site-packages/pytest/__init__.py", line 5, in <module>
        from _pytest._code import ExceptionInfo
      File "/home/alex/code/FINESSE/.venv/lib/python3.9/site-packages/_pytest/_code/__init__.py", line 2, in <module>
        from .code import Code
      File "/home/alex/code/FINESSE/.venv/lib/python3.9/site-packages/_pytest/_code/code.py", line 60, in <module>
        from exceptiongroup import BaseExceptionGroup
    ModuleNotFoundError: No module named 'exceptiongroup'
    

    Full output here: https://github.com/ImperialCollegeLondon/FINESSE/pull/58

    It appears that the exceptiongroup package is not being installed via poetry, though it isn't obvious why.

    Any ideas?

    opened by alexdewar 1
  • Add --no-mypy option to disable mypy check

    Add --no-mypy option to disable mypy check

    Right now I have --mypy in my pytest.ini file so that mypy runs by default when my tests are run, both locally and in CI

    However, when I'm quickly iterating in testing a new feature, I would like to skip the mypy check since I first just want to make sure that the feature works.

    Having a --no-mypy option to pass through to pytest when running locally would be great, rather than having to just deal with the mypy run each time, or go and manually modify my pytest.ini file to comment out the --mypy option.

    The pytest-pylint and pytest-cov plugins provide this functionality:

    • https://github.com/carsongee/pytest-pylint/blob/781d6a8d67377b543756d0123c6259b8df77c0a8/pytest_pylint/plugin.py#L33-L38
    • https://github.com/pytest-dev/pytest-cov/blob/00713b3fec90cb8c98a9e4bfb3212e574c08e67b/src/pytest_cov/plugin.py#L110-L112

    I'm happy to add a PR if you agree that this is a worthwhile feature

    opened by pwildenhain 1
  • mypy exited with status 1 - no error messages shown

    mypy exited with status 1 - no error messages shown

    I have some type errors in my code, and would like to find them by running mypy via pytest-mypy. When I run pytest, I get:

    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.6.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- <venv>
    cachedir: .pytest_cache
    rootdir: <project-root>, configfile: setup.cfg, testpaths: proof_of_concept, tests
    plugins: cov-2.11.1, pycodestyle-2.2.0, pydocstyle-2.2.0, mypy-0.8.1
    collected 154 items                                                                                                                                                        
    
    proof_of_concept/__init__.py::mypy PASSED
    proof_of_concept/__init__.py::mypy-status FAILED
    
    ================================================================================= FAILURES =================================================================================
    _______________________________________________________________________________ test session _______________________________________________________________________________
    mypy exited with status 1.
    

    This suggests that there were some errors, but it doesn't show what they were, so I cannot fix them. Running mypy separately reveals a bunch of issues in proof_of_concept/rest/registry_client.py.

    Looking at the pytest-mypy source, it seems that this can happen if mypy checks a file that has not been collected. I'm importing the problem file from the file under test, and mypy gives a bunch of errors about this imported file. I guess the ::mypy test passes anyway, because the errors are not in the file under test. However, pytest-mypy then generates an error using this second mypy-status result, because mypy returned a non-zero exit code.

    Ignoring the errors makes sense I think, they should show up later when the problem file itself is tested. Unfortunately, we never get to that point, because I'm running with -x, which stops the tests as soon as the first error is found, and no error messages are shown for the mypy-status failure, so I cannot fix them.

    I'm a bit confused about the current intent of the pytest-mypy code. There's a comment suggesting that the ::mypy test is intended to fail even if mypy only shows errors in files that weren't collected, and that that is why there's the ::mypy-status result. On the other hand, there used to be a test that checked that no MypyStatusItem was created unless there was at least one MypyFileItem, which I think means the opposite. That was removed in https://github.com/dbader/pytest-mypy/commit/cd459a48ce11d24e1bddf6877ef53f7d26cf3daf however, which also introduced this -status result.

    In my opinion, a mypy failure only because of errors in imported files should either be considered an error in the file under test, in which case the error should be printed, or it should not be considered an error in the file under test, in which case all tests related to that file should pass and the non-zero exit code ignored. The latter makes more sense to me.

    opened by LourensVeen 3
  • Recommended way to set report path?

    Recommended way to set report path?

    Hi, thanks for this excellent plugin! :heart:

    We are running pytest like so; pytest tests/unit_tests and this generates a bunch of reports. Then we also run pytest tests/component_tests, which also generates a bunch of (different) reports. I use a setup.cfg file to configure both pytest and mypy.

    Now, ideally, we want the mypy reports to be named accordingly ("unit" vs "component" respectively). Do you have a recommended approach on how to achieve this? Right now, I've created a simple pytest plugin which analyses pytest's config.args and determines which type of test is executing and then it does the following:

    plugin = config.pluginmanager.getplugin("mypy")
    plugin.mypy_argv.append(f"--html-report=reports/mypy/{test_type}")
    

    But to me, this seems both hacky and a little excessive. There must be some easier way to achieve this? Any ideas? 😃

    opened by fredrikaverpil 1
  • Expected mypy errors

    Expected mypy errors

    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.

    opened by dcbaker 3
Releases(v0.10.3)
Owner
Dan Bader
Full-stack Pythonista & Python Coach. Write Clean and Pythonic code with my free tutorials, books, and courses.
Dan Bader
Testinfra test your infrastructures

Testinfra test your infrastructure Latest documentation: https://testinfra.readthedocs.io/en/latest About With Testinfra you can write unit tests in P

pytest-dev 2.1k Jan 07, 2023
Make Selenium work on Github Actions

Make Selenium work on Github Actions Scraping with BeautifulSoup on GitHub Actions is easy-peasy. But what about Selenium?? After you jump through som

Jonathan Soma 33 Dec 27, 2022
Useful additions to Django's default TestCase

django-test-plus Useful additions to Django's default TestCase from REVSYS Rationale Let's face it, writing tests isn't always fun. Part of the reason

REVSYS 546 Dec 22, 2022
A modern API testing tool for web applications built with Open API and GraphQL specifications.

Schemathesis Schemathesis is a modern API testing tool for web applications built with Open API and GraphQL specifications. It reads the application s

Schemathesis.io 1.6k Jan 06, 2023
Show, Edit and Tell: A Framework for Editing Image Captions, CVPR 2020

Show, Edit and Tell: A Framework for Editing Image Captions | arXiv This contains the source code for Show, Edit and Tell: A Framework for Editing Ima

Fawaz Sammani 76 Nov 25, 2022
Automated mouse clicker script using PyAutoGUI and Typer.

clickpy Automated mouse clicker script using PyAutoGUI and Typer. This app will randomly click your mouse between 1 second and 3 minutes, to prevent y

Joe Fitzgibbons 0 Dec 01, 2021
A Library for Working with Sauce Labs

Robotframework - Sauce Labs Plugin This is a plugin for the SeleniumLibrary to help with using Sauce Labs. This library is a plugin extension of the S

joshin4colours 6 Oct 12, 2021
Webscreener is a tool for mass web domains pentesting.

Webscreener is a tool for mass web domains pentesting. It is used to take snapshots for domains that is generated by a tool like knockpy or Sublist3r. It cuts out most of the pentesting time by scree

Seekurity 3 Jun 07, 2021
A wrapper for webdriver that is a jumping off point for web automation.

Webdriver Automation Plus ===================================== Description: Tests the user can save messages then find them in search and Saved items

1 Nov 08, 2021
Selects tests affected by changed files. Continous test runner when used with pytest-watch.

This is a pytest plug-in which automatically selects and re-executes only tests affected by recent changes. How is this possible in dynamic language l

Tibor Arpas 614 Dec 30, 2022
A pytest plugin to skip `@pytest.mark.slow` tests by default.

pytest-skip-slow A pytest plugin to skip @pytest.mark.slow tests by default. Include the slow tests with --slow. Installation $ pip install pytest-ski

Brian Okken 19 Jan 04, 2023
splinter - python test framework for web applications

splinter - python tool for testing web applications splinter is an open source tool for testing web applications using Python. It lets you automate br

Cobra Team 2.6k Dec 27, 2022
Flexible test automation for Python

Nox - Flexible test automation for Python nox is a command-line tool that automates testing in multiple Python environments, similar to tox. Unlike to

Stargirl Flowers 941 Jan 03, 2023
Python scripts for a generic performance testing infrastructure using Locust.

TODOs Reference to published paper or online version of it loadtest_plotter.py: Cleanup and reading data from files ARS_simulation.py: Cleanup, docume

Juri Tomak 3 Dec 15, 2022
Declarative HTTP Testing for Python and anything else

Gabbi Release Notes Gabbi is a tool for running HTTP tests where requests and responses are represented in a declarative YAML-based form. The simplest

Chris Dent 139 Sep 21, 2022
Sixpack is a language-agnostic a/b-testing framework

Sixpack Sixpack is a framework to enable A/B testing across multiple programming languages. It does this by exposing a simple API for client libraries

1.7k Dec 24, 2022
Automação de Processos (obtenção de informações com o Selenium), atualização de Planilha e Envio de E-mail.

Automação de Processo: Código para acompanhar o valor de algumas ações na B3. O código entra no Google Drive, puxa os valores das ações (pré estabelec

Hemili Beatriz 1 Jan 08, 2022
Based on the selenium automatic test framework of python, the program crawls the score information of the educational administration system of a unive

whpu_spider 该程序基于python的selenium自动化测试框架,对某高校的教务系统的成绩信息实时爬取,在检测到成绩更新之后,会通过电子邮件的方式,将更新的成绩以文本的方式发送给用户,可以使得用户在不必手动登录教务系统网站时,实时获取成绩更新的信息。 该程序仅供学习交流,不可用于恶意攻

1 Dec 30, 2021
Enabling easy statistical significance testing for deep neural networks.

deep-significance: Easy and Better Significance Testing for Deep Neural Networks Contents ⁉️ Why 📥 Installation 🔖 Examples Intermezzo: Almost Stocha

Dennis Ulmer 270 Dec 20, 2022