Skip to main content

pytest-clang-tidy

PyPI Python License CI

A pytest plugin that runs clang-tidy static analysis on C/C++ source files. Each file is collected as a test item and reported as a pass or failure in the normal pytest output.

Useful for Python projects with C/C++ source where you already run pytest and want clang-tidy findings surfaced in the same test run.

Installation

pip install pytest-clang-tidy

This pulls in clang-tidy automatically via the clang-tidy PyPI package.

Usage

The plugin does nothing unless explicitly enabled:

pytest --clang-tidy

This collects all .c, .cpp, .cc, and .cxx files and runs clang-tidy on each one. Files with errors fail; clean files pass.

PASSED src/clean.c::CLANG_TIDY
FAILED src/buggy.c::CLANG_TIDY
  src/buggy.c:4:8: error: Dereference of null pointer (loaded from
  variable 'p') [clang-analyzer-core.NullDereference]

You can combine --clang-tidy with your normal test run — Python tests and clang-tidy items appear together in the results.

Enabling checks

clang-tidy has no checks enabled by default. You need to configure which checks to run via clang_tidy_checks, otherwise every file will pass without being analyzed. The clang-analyzer-* checks (Clang Static Analyzer) are a good starting point — they catch real bugs like null pointer dereferences, use-after-free, and resource leaks. See the full list of checks for other options.

[pytest]
clang_tidy_checks =
    -*
    clang-analyzer-*

clang_tidy_args = --warnings-as-errors=*

By default, clang-tidy exits 0 even when it finds warnings. Adding --warnings-as-errors=* to clang_tidy_args makes warnings fail the test. Without it, warnings are still surfaced as Python warnings in the pytest output (visible in the warnings summary).

Configuration

All options go in pyproject.toml, pytest.ini, or setup.cfg under [pytest].

clang-tidy also reads settings from a .clang-tidy file if one exists in your project (or a parent directory). Options set via pytest configuration are applied after .clang-tidy and take precedence — for example, clang_tidy_checks appends to the Checks value from .clang-tidy and can override individual checks. In general it's recommended to use either .clang-tidy or clang_tidy_checks but not both.

clang_tidy_checks

Checks to enable. Each entry is joined with commas and passed as -checks=.... Default: none (no checks enabled).

[pytest]
clang_tidy_checks =
    -*
    clang-analyzer-*
    bugprone-*
    -bugprone-easily-swappable-parameters

You can also pass -checks=... directly in clang_tidy_args if you prefer a single-line format.

clang_tidy_args

Extra arguments forwarded to every clang-tidy invocation. Use it for --warnings-as-errors, --config-file, and any other clang-tidy flags.

[pytest]
clang_tidy_args = --warnings-as-errors=* --config-file=tools/clang-tidy.yml

clang_tidy_extensions

File extensions to collect. Default: .c .cpp .cc .cxx.

[pytest]
clang_tidy_extensions = .c .cpp .h

clang_tidy_compiler_args

Extra compiler arguments passed after -- in the clang-tidy invocation. Useful for passing defines, include paths, or language standards.

[pytest]
clang_tidy_compiler_args = -std=c11 -DNDEBUG

clang_tidy_include_python_headers

When set to true, the plugin adds -isystem<python_include> to the compiler flags, where <python_include> is the CPython headers directory from sysconfig.get_path('include'). This allows clang-tidy to parse files that #include <Python.h> without a compile_commands.json. The headers are added as -isystem (not -I) so that clang-tidy does not report warnings from CPython's own headers. Default: false.

[pytest]
clang_tidy_include_python_headers = true

compile_commands.json

If a compile_commands.json file exists in your project root, clang-tidy will use it automatically and the plugin will not append any compiler flags (neither clang_tidy_compiler_args nor -isystem<python_include>).

Markers

All clang-tidy items are marked with clang_tidy, so you can select or exclude them with -m:

pytest --clang-tidy -m clang_tidy           # only clang-tidy
pytest --clang-tidy -m "unit or clang_tidy" # unit tests + clang-tidy
pytest --clang-tidy -m "not clang_tidy"     # everything except clang-tidy

Caching

Results are cached based on file modification time, clang_tidy_checks, clang_tidy_args, and clang_tidy_compiler_args. On subsequent runs, files that previously passed are skipped. The cache is automatically invalidated when a file is modified or arguments change. Caching relies on pytest's built-in cache provider (the .pytest_cache directory). If the cache provider is disabled (for example with -p no:cacheprovider), results will not be cached and all files will be re-checked on each run.

To force a full re-check:

pytest --clang-tidy --cache-clear

Acknowledgements

This plugin relies on the clang-tidy PyPI package, which bundles prebuilt clang-tidy binaries so that no system-level LLVM installation is required.

License

MIT

Metadata

Release files for pytest-clang-tidy 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-clang-tidy 0.2.1
File Size Uploaded
pytest_clang_tidy-0.2.1.tar.gz 8.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-clang-tidy 0.2.1
File Interpreter ABI Platform
pytest_clang_tidy-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 15.3 kB

Release files / pytest_clang_tidy-0.2.1.tar.gz

Download URL pytest_clang_tidy-0.2.1.tar.gz
Size 8.1 kB
Tags Source
SHA-256 checksum
How to use checksums
03a972b030a546213225ff180e4338aff6cd89c1d4c3d4e29f3d5611bef9adfa
BLAKE2b-256 checksum
How to use checksums
4b6ab6c4a318998c1f24a6f5bdaed5cb97aa0b2495effd5a993b779d8a9778f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 27, 2026.

Transparency log

Release files / pytest_clang_tidy-0.2.1-py3-none-any.whl

Download URL pytest_clang_tidy-0.2.1-py3-none-any.whl
Size 7.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
85397e38f689f9e51d5856783ff4ef05da8ca0f6d30eefd62ed07bd22d165dc0
BLAKE2b-256 checksum
How to use checksums
5050b28733df6f816b7489ba99fa6c402c6a0bb666d9992c649ce2d55f717e11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 27, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page