Skip to main content

Fast-first mutation testing for pytest. Let the gremlins loose, see which ones survive.

Project description

pytest-gremlins

Fast-first mutation testing for pytest. Speed that makes mutation testing practical for everyday TDD.

PyPI version Python versions CI codecov Documentation License: MIT

Let the gremlins loose. See which ones survive.


Key Features

  • Speed-First Architecture - Mutation switching eliminates file I/O and module reloads. Run gremlins in seconds, not hours.
  • Native pytest Integration - Zero configuration to start. Just add --gremlins to your pytest command.
  • Coverage-Guided Selection - Only runs tests that actually cover the mutated code. 10-100x fewer test executions in well-modularized codebases.
  • Incremental Caching - Results cached by content hash. Unchanged code skips re-testing entirely.
  • Parallel Execution - Distribute gremlins across CPU cores for linear speedup.

Quick Start

# Install
pip install pytest-gremlins

# Run mutation testing
pytest --gremlins

That's it. pytest-gremlins will instrument your code, release the gremlins, and report which ones your tests zapped (good!) and which survived (test gaps!).


Why pytest-gremlins?

Code coverage lies. It tells you what code your tests execute, but not whether your tests would catch bugs.

Mutation testing answers a harder question: If I introduce a bug, will my tests fail?

The Problem with Existing Tools

Tool Limitation
mutmut Single-threaded by default, no incremental analysis
Cosmic Ray Complex setup; distributed mode requires Celery
MutPy Unmaintained (last update 2019), Python 3.4-3.7 only
mutatest Unmaintained (last update 2022)

Our Solution: Speed Through Architecture

pytest-gremlins is fast because of how it works, not just parallelization:

  1. Mutation Switching - Instrument once, toggle mutations via environment variable
  2. Coverage Guidance - Only run tests that cover the mutated code
  3. Incremental Analysis - Skip unchanged code on repeat runs
  4. Parallel Execution - Safe parallelization with no shared state

Performance

Benchmarked against mutmut on a synthetic project:

Mode Time vs mutmut Speedup
--gremlins (sequential) 17.79s 14.90s 0.84x (see note)
--gremlins --gremlin-parallel 3.99s 14.90s 3.73x faster
--gremlins --gremlin-parallel --gremlin-cache 1.08s 14.90s 13.82x faster

Key findings:

  • Sequential mode is slower due to subprocess isolation overhead; detailed profiling shows 1.7x slower on small targets
  • Parallel mode delivers 3.73x speedup over mutmut
  • With caching, subsequent runs are 13.82x faster
  • pytest-gremlins found 117 mutations vs mutmut's 86, with 98% kill rate vs 86%

Example Output

================== pytest-gremlins mutation report ==================

Zapped: 142 gremlins (85%)
Survived: 18 gremlins (11%)
Timeout: 5 gremlins (3%)
Error: 2 gremlins (1%)

Top surviving gremlins:
  src/auth.py:42                   >= -> >               (comparison)
  src/utils.py:17                  + -> -                (arithmetic)
  src/api.py:88                    True -> False         (boolean)

Run with --gremlin-report=html for detailed report.
=====================================================================

Timeout and Error categories are only shown when their count is greater than zero.


Installation

# With pip
pip install pytest-gremlins

# With uv
uv add pytest-gremlins

# With poetry
poetry add pytest-gremlins

Requires Python 3.11+


Configuration

Zero configuration required for most projects. The plugin auto-discovers source paths from your pyproject.toml setuptools config (e.g., [tool.setuptools.packages.find]). If auto-discovery doesn't find your code, configure paths explicitly:

[tool.pytest-gremlins]
# Operators to use (default: all)
operators = ["comparison", "arithmetic", "boolean"]

# Paths to mutate (optional -- auto-discovered from setuptools metadata)
paths = ["src"]

# Patterns to exclude
exclude = ["**/migrations/*", "**/test_*"]

# Minimum mutation score to pass
min_score = 80

The Gremlins Theme

We use Gremlins movie references as our domain language:

Traditional Term Gremlin Term Meaning
Original code Mogwai Your clean, untouched source code
Start mutation testing Feed after midnight Begin the mutation process
Mutant Gremlin A mutation injected into your code
Kill mutant Zap Your test caught the mutation
Surviving mutant Survivor Mutation your tests missed

Documentation

Full documentation: pytest-gremlins.readthedocs.io


Related Projects


Contributing

Contributions welcome! See our Contributing Guide.

This project uses strict TDD discipline with BDD/Gherkin scenarios. All contributions must include tests written before implementation.

Note on code coverage: We target 69% coverage due to inherent limitations in measuring pytest plugins (import timing, subprocess execution). See CONTRIBUTING.md for details.


License

MIT License. See LICENSE.


Changelog

See CHANGELOG.md for release history.

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

pytest_gremlins-1.5.0b1.tar.gz (3.9 MB view details)

Uploaded Source

Built Distribution

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

pytest_gremlins-1.5.0b1-py3-none-any.whl (93.3 kB view details)

Uploaded Python 3

File details

Details for the file pytest_gremlins-1.5.0b1.tar.gz.

File metadata

  • Download URL: pytest_gremlins-1.5.0b1.tar.gz
  • Upload date:
  • Size: 3.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pytest_gremlins-1.5.0b1.tar.gz
Algorithm Hash digest
SHA256 a3e3e8565fdcc710fabe2e4361df8efb04f2e1e04d214a4749fca14a687271d5
MD5 552455bd2bf67d501b4cd79539aaf72a
BLAKE2b-256 98c862735d318278adcfd207f2222210038e2f332c4a3253c57e761ca6080d2c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_gremlins-1.5.0b1.tar.gz:

Publisher: release.yml on mikelane/pytest-gremlins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytest_gremlins-1.5.0b1-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_gremlins-1.5.0b1-py3-none-any.whl
Algorithm Hash digest
SHA256 f9cd9a3f5a620349aa30090c4743963ba251b7a3fefca81210ec25baa66d0abe
MD5 ad424a2a7ae17c48df223d46475418ae
BLAKE2b-256 b9d8745da8263afe0233c3db50010dd61b2d8bac5a0e9dd77b07fed30aecaaff

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_gremlins-1.5.0b1-py3-none-any.whl:

Publisher: release.yml on mikelane/pytest-gremlins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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