Skip to main content

A linter to scrutinize how you are using mocks in Python.

Project description

Pillory

A linter to scrutinize how you are using mocks in Python.

If you often hear or make the comment "patch the import not the definition" or spend a lot of time explaining or helping people debug mocks, this linter could help you.

Usage

Install from PyPI with pip:

pip install pillory

Run pillory on the current directory:

python -m pillory

Or give a specific file, directory, or glob:

python -m pillory 'tests/**/test_*.py'

Rules

PM101 patched implementation You patched the implementation of a class or function instead of where it is imported to in the module under test. e.g. "parsers.Parser" where Parser is defined instead of "main.Parser" where it is used. This means you may not have affected the module under test at all, or you have replaced the target in a way which will affect other code that uses it, which is bad for test isolation (making sure tests don't affect other tests, and that each test tests what is intended and don't change how other parts of the code work). There is a warning about not affecting the right module in the Python Standard Library docs, but there is an even better article by Ned Batchelder explaining how it works and the additional problems with test isolation.

PM102 patched is not a top level module attribute You patched something like a method on a class. Because class methods can't be imported by themselves, this means all uses of the class will be affected, not just the module under test.

PM103 patched builtins You patched the builtins module instead of the built-in function in the module under test. Built-ins are actually added to every module and that's where they should be patched, to avoid similar issues to patching the implementation. There is a CPython detail that means the builtins module may be added to the lookup of each module, so patching the builtins module can work, but it's not guaranteed and it still has problems with test isolation.

Known issues

  • No --help text.
  • No console script entry point (pillory command), have to use with python -m.
  • Only takes one path or glob.
  • No config file support.
  • Not fast.
  • Must import modules. Doesn't work well with frameworks like Django that require special setup for things like settings before importing.
  • Globs have to be relative to the current directory.
  • No further explanations for the errors.
  • No pretty error handling, just tracebacks.
  • Will error when mocking something in the module under test, which is arguably "OK".
  • No pre-commit integration.
  • No strong, written justification for the reasons behind the errors.

What's with the name?

I thought it was funny that mock can also mean "make fun of" as well as the meaning of "mimic" that we use in testing. I imagined the linter cruelly calling out how you are using mocks incorrectly. Except I couldn't call it "mock", or "mock mocker", that would be confusing! So I picked a name with a similar meaning, and starting with a P for that Python feeling.

Contributing

Thank you for your interest in making a contribution.

Please talk to the maintainer before making a pull request to make sure what you are adding is wanted.

This project uses the Apache License 2.0. You will be credited in the git history, but for ease of maintenance copyright stays with the maintainer.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pillory-1.0.0.tar.gz (6.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pillory-1.0.0-py2.py3-none-any.whl (7.3 kB view details)

Uploaded Python 2Python 3

File details

Details for the file pillory-1.0.0.tar.gz.

File metadata

  • Download URL: pillory-1.0.0.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.31.0

File hashes

Hashes for pillory-1.0.0.tar.gz
Algorithm Hash digest
SHA256 66a8c655e905a0cfbeda94957dc07542341bf87b60dc7151c96765a4c6091e00
MD5 fcc417e42fd47ad28e383fd2da3ce573
BLAKE2b-256 9f73a54d106e99402b1749e57f1a463f8593a98d4e8c56f15e4382ff82dcc42c

See more details on using hashes here.

File details

Details for the file pillory-1.0.0-py2.py3-none-any.whl.

File metadata

  • Download URL: pillory-1.0.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 7.3 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.31.0

File hashes

Hashes for pillory-1.0.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 ae8167a021c99ec5684e0d0b971b6c9498de74fd89288792462141e1c03987eb
MD5 ab2c7c00d86fc27c0fe27bc48b29ed0c
BLAKE2b-256 608b21cff7b520eb120f6aa980d6a62f7b03952bb3f0c9d21c90c723e1a95500

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page