Search code examples
pythonpyteststatic-analysis

How to validate keyword arguments match function signature with pytest?


Writing unit tests is the best. Totally on the same page. But is there a way to catch the following call with pytest, without running main()? Some sort of linting plugin perhaps? I can't seem to find anything that does this. pytest, flake8, and black all think this is fine.

def myfunc(a, b):
    print(a, b)


def main():
    myfunc(c=5) # should raise an error on tests - c not in myfunc signature

Would be open to a plugin or to some sort of pytest hook, as long as it doesn't require modifying the module source (modifying the test suite e.g. conftest.py is fine).


Solution

  • pylint will raise an exception for the above, and the pytest-pylint package (pip install pytest-pylint) bundles this into a pytest plugin:

    $ pytest --pylint
    ================================== test session starts ==================================
    platform darwin -- Python 3.10.4, pytest-7.1.1, pluggy-1.0.0
    rootdir: /Users/mikedelgado/pytest-kwargs
    plugins: anyio-3.5.0, pylint-0.19.0, mock-3.8.2, flakes-4.0.5, cov-3.0.0
    collected 3 items
    --------------------------------------------------------------------------------
    Linting files
    ....
    --------------------------------------------------------------------------------
    
    pytest_kwargs/__init__.py s                                                       [ 33%]
    pytest_kwargs/myfile.py F                                                         [ 66%]
    tests/test_myfile.py s                                                            [100%]
    
    ======================================= FAILURES ========================================
    ___________________________ [pylint] pytest_kwargs/myfile.py ____________________________
    C:  1, 0: Missing module docstring (missing-module-docstring)
    C:  1, 0: Missing function or method docstring (missing-function-docstring)
    C:  1,11: Argument name "a" doesn't conform to snake_case naming style (invalid-name)
    C:  1,14: Argument name "b" doesn't conform to snake_case naming style (invalid-name)
    C:  5, 0: Missing function or method docstring (missing-function-docstring)
    E:  6, 4: Unexpected keyword argument 'c' in function call (unexpected-keyword-arg)
    E:  6, 4: No value for argument 'a' in function call (no-value-for-parameter)
    E:  6, 4: No value for argument 'b' in function call (no-value-for-parameter)
    ================================ short test summary info ================================
    FAILED pytest_kwargs/myfile.py::PYLINT
    ======================= 1 failed, 2 skipped, 4 warnings in 0.08s ========================