Ptr
Python Test Runner.
Install / Use
/learn @facebookincubator/PtrREADME
🏃♀️ ptr - Python Test Runner 🏃♂️
Python Test Runner (ptr) was born to run tests in an opinionated way, within arbitrary code repositories.
ptr supports many Python projects with unit tests defined in their setup.(cfg|py) files per repository.
ptr allows developers to test multiple projects/modules in one Python environment through the use of a single test virtual environment.
ptrrequires>=python 3.7ptritself usesptrto run its tests 👌🏼ptris supported and tested on Linux, MacOS + Windows Operating Systems
By adding ptr configuration to your either of your pyproject.toml, setup.cfg or setup.py you can have ptr perform the following,
per test suite, in parallel:
- run your test suite
- check and enforce coverage requirements (via coverage),
- format code (via black)
- perform static type analysis (via mypy)
Quickstart
- Install
ptrinto you virtualenvpip install ptr
- Ensure your tests have a base file that can be executed directly
- i.e.
python3 test.py(possibly usingunittest.main())
- i.e.
- After adding
ptr_paramsto setup.py (see example below), run:
cd repo
ptr
How does ptr perform this magic? 🎩
I'm glad you ask. Under the covers ptr performs:
- Recursively searches for
setup.(cfg|py)files fromBASE_DIR(defaults to your "current working directory" (CWD))- AST parses out the config for each
setup.pytest requirements - If a
pyproject.tomlorsetup.cfgexists, load via configparser/tomli and prefer if a[ptr]section exists
- AST parses out the config for each
- Creates a Python Virtual Environment (OPTIONALLY pointed at an internal PyPI mirror)
- Runs
ATONCEtests suites in parallel (i.e. per setup.(cfg|ptr)) - All steps will be run for each suite and ONLY FAILED runs will have output written to stdout
Usage 🤓
To use ptr all you need to do is cd to your project or set the base dir via -b and execute:
$ ptr [-dk] [-b some/path] [--venv /tmp/existing_venv]
For faster runs when testing, it is recommended to reuse a Virtual Environment:
-k- To keep the virtualenv created byptr.- Use
--venv VENV_PATHto reuse to an existing virtualenv created by the user.
Help Output 🙋♀️ 🙋♂️
usage: ptr.py [-h] [-a ATONCE] [-b BASE_DIR] [-d] [-e] [-k] [-m MIRROR]
[--print-cov] [--print-non-configured]
[--progress-interval PROGRESS_INTERVAL] [--run-disabled]
[--stats-file STATS_FILE] [--system-site-packages] [--venv VENV]
[--venv-timeout VENV_TIMEOUT]
optional arguments:
-h, --help show this help message and exit
-a ATONCE, --atonce ATONCE
How many tests to run at once [Default: 6]
-b BASE_DIR, --base-dir BASE_DIR
Path to recursively look for setup.py files [Default:
/Users/cooper/repos/ptr]
-d, --debug Verbose debug output
-e, --error-on-warnings
Have Python warnings raise DeprecationWarning on tests
run
-k, --keep-venv Do not remove created venv
-m MIRROR, --mirror MIRROR
URL for pip to use for Simple API [Default:
https://pypi.org/simple/]
--print-cov Print modules coverage report
--print-non-configured
Print modules not configured to run ptr
--progress-interval PROGRESS_INTERVAL
Seconds between status update on test running
[Default: Disabled]
--run-disabled Force any disabled tests suites to run
--stats-file STATS_FILE
JSON statistics file [Default: /var/folders/tc/hbwxh76
j1hn6gqjd2n2sjn4j9k1glp/T/ptr_stats_12510]
--system-site-packages
Give the virtual environment access to the system
site-packages dir
--venv VENV Path to venv to reuse
--venv-timeout VENV_TIMEOUT
Timeout in seconds for venv creation + deps install
[Default: 120]
Configuration 🧰
ptr is configured by placing directives in one or more of the following files. .ptrconfig provides
base configuration and default values for all projects in the repository, while each setup.(cfg|py)
overrides the base configuration for the respective packages they define.
.ptrconfig
ptr supports a general config in ini (ConfigParser) format.
A .ptrconfig file can be placed at the root of any repository or in any directory within your repository.
The first .ptrconfig file found via a recursive walk to the root ("/" in POSIX systems) will be used.
Please refer to ptrconfig.sample for the options available.
setup.py
This is per project in your repository. A simple example, based on ptr itself:
# Specific Python Test Runner (ptr) params for Unit Testing Enforcement
ptr_params = {
# Where mypy will run to type check your program
"entry_point_module": "ptr",
# Base Unittest file
"test_suite": "ptr_tests",
"test_suite_timeout": 300,
# Relative path from setup.py to module (e.g. ptr == ptr.py)
"required_coverage": {"ptr.py": 99, "TOTAL": 99},
# Run `black --check` or not
"run_black": False,
# Run mypy or not
"run_mypy": True,
}
pyproject.toml
This is per project in your repository and if exists is preferred over setup.py and setup.cfg.
Please refer to pyproject.toml
for the options available + format.
setup.cfg
This is per project in your repository and if exists is preferred over setup.py.
Please refer to setup.cfg.sample
for the options available + format.
mypy Specifics
When enabled, (in setup.(cfg|py)) mypy can support using a custom mypy.ini for each setup.py (module) defined.
To have ptr run mypy using you config:
- create a
mypy.iniin the same directory as yoursetup.py - OR add [mypy] section to your
setup.cfg
mypy Configuration Documentation can be found here
- An example
setup.cfgcan be seen here.
Example Output 📝
Here are some example runs.
Successful ptr Run:
Here is what you want to see in your CI logs!
[2019-02-06 21:51:45,442] INFO: Starting ptr.py (ptr.py:782)
[2019-02-06 21:51:59,471] INFO: Successfully created venv @ /var/folders/tc/hbwxh76j1hn6gqjd2n2sjn4j9k1glp/T/ptr_venv_24397 to run tests (14s) (ptr.py:547)
[2019-02-06 21:51:59,472] INFO: Installing /Users/cooper/repos/ptr/setup.py + deps (ptr.py:417)
[2019-02-06 21:52:00,726] INFO: Running /Users/cooper/repos/ptr/ptr_tests.py tests via coverage (ptr.py:417)
[2019-02-06 21:52:04,153] INFO: Analyzing coverage report for /Users/cooper/repos/ptr/setup.py (ptr.py:417)
[2019-02-06 21:52:04,368] INFO: Running mypy for /Users/cooper/repos/ptr/setup.py (ptr.py:417)
[2019-05-03 14:54:09,915] INFO: Running flake8 for /Users/cooper/repos/ptr/setup.py (ptr.py:417)
[2019-05-03 14:54:10,422] INFO: Running pylint for /Users/cooper/repos/ptr/setup.py (ptr.py:417)
[2019-05-03 14:54:14,020] INFO: Running pyre for /Users/cooper/repos/ptr/setup.py (ptr.py:417)
[2019-02-06 21:52:07,733] INFO: /Users/cooper/repos/ptr/setup.py has passed all configured tests (ptr.py:509)
-- Summary (total time 22s):
✅ PASS: 1
❌ FAIL: 0
⌛️ TIMEOUT: 0
💩 TOTAL: 1
-- 1 / 1 (100%) `setup.py`'s have `ptr` tests running
Unsuccessful ptr Run Examples:
Here are some examples of runs failing. Any "step" can fail. All output is predominately the underlying tool.
Unit Test Failure
[2019-02-06 21:53:58,121] INFO: Starting ptr.py (ptr.py:782)
[2019-02-06 21:53:58,143] INFO: Installing /Users/cooper/repos/ptr/setup.py + deps (ptr.py:417)
[2019-02-06 21:53:59,698] INFO: Running /Users/cooper/repos/ptr/ptr_tests.py tests via coverage (ptr.py:417)
-- Summary (total time 5s):
✅ PASS: 0
❌ FAIL: 1
⌛️ TIMEOUT: 0
💩 TOTAL: 1
-- 1 / 1 (100%) `setup.py`'s have `ptr` tests running
-- Failure Output --
/Users/cooper/repos/ptr/setup.py (failed 'tests_run' step):
...F....................
======================================================================
FAIL: test_config (__main__.TestPtr)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/cooper/repos/ptr/ptr_tests.py", line 125, in test_config
self.assertEqual(len(sc["ptr"]["venv_pkgs"].split()), 4)
AssertionError: 5 != 4
----------------------------------------------------------------------
Ran 24 tests in 3.221s
FAILED (failures=1)
coverage
[2019-02-06 21:55:42,947] INFO: Starting ptr.py (ptr.py:782)
[2019-02-06 21:55:42,969] INFO: Installing /Users/cooper/repos/ptr/setup.py + deps (ptr.py:417)
[2019-02-06 21:55:44,920] INFO: Running /Users/cooper/repos/ptr/ptr_tests.py tests via coverage (ptr.py:417)
[2019-02-06 21:55:49,628] INFO: Analyzing coverage report for /Users/cooper/repos/ptr/setup.py (ptr.py:417)
Related Skills
node-connect
351.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
110.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
351.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
351.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
