pytest-clang-tidy
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)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_clang_tidy-0.2.1.tar.gz | 8.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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