A pytest plugin that runs clang-tidy static analysis on C/C++ source files
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytest_clang_tidy-0.2.1.tar.gz.
File metadata
- Download URL: pytest_clang_tidy-0.2.1.tar.gz
- Upload date:
- Size: 8.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03a972b030a546213225ff180e4338aff6cd89c1d4c3d4e29f3d5611bef9adfa
|
|
| MD5 |
b71f7760257b5ec8b69c0b2f54cf6697
|
|
| BLAKE2b-256 |
4b6ab6c4a318998c1f24a6f5bdaed5cb97aa0b2495effd5a993b779d8a9778f5
|
Provenance
The following attestation bundles were made for pytest_clang_tidy-0.2.1.tar.gz:
Publisher:
release.yml on alexdej/pytest-clang-tidy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_clang_tidy-0.2.1.tar.gz -
Subject digest:
03a972b030a546213225ff180e4338aff6cd89c1d4c3d4e29f3d5611bef9adfa - Sigstore transparency entry: 1188917631
- Sigstore integration time:
-
Permalink:
alexdej/pytest-clang-tidy@6207bd73b33e94b619780d86697a51a0e6810714 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/alexdej
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6207bd73b33e94b619780d86697a51a0e6810714 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pytest_clang_tidy-0.2.1-py3-none-any.whl.
File metadata
- Download URL: pytest_clang_tidy-0.2.1-py3-none-any.whl
- Upload date:
- Size: 7.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85397e38f689f9e51d5856783ff4ef05da8ca0f6d30eefd62ed07bd22d165dc0
|
|
| MD5 |
d3bdac2189bbbb4f2950bdd892e637db
|
|
| BLAKE2b-256 |
5050b28733df6f816b7489ba99fa6c402c6a0bb666d9992c649ce2d55f717e11
|
Provenance
The following attestation bundles were made for pytest_clang_tidy-0.2.1-py3-none-any.whl:
Publisher:
release.yml on alexdej/pytest-clang-tidy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_clang_tidy-0.2.1-py3-none-any.whl -
Subject digest:
85397e38f689f9e51d5856783ff4ef05da8ca0f6d30eefd62ed07bd22d165dc0 - Sigstore transparency entry: 1188917633
- Sigstore integration time:
-
Permalink:
alexdej/pytest-clang-tidy@6207bd73b33e94b619780d86697a51a0e6810714 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/alexdej
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6207bd73b33e94b619780d86697a51a0e6810714 -
Trigger Event:
push
-
Statement type: