Skip to content

python-testing-debugging/pytest-starter-config

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pytest-starter-config

Generate a strict, well-commented pytest setup — config, conftest.py, markers, and starter tests — and drop it into any project in one command.

Every Python project reinvents the same pytest boilerplate: the addopts line you always mean to make strict, the four markers you register slightly differently each time, the conftest.py fixture that chdirs into a temp directory, the auto-skip hook for slow tests. pytest-starter-config writes all of it for you — commented, opinionated, and safe to run against an existing repo (it merges into your pyproject.toml instead of overwriting it).

$ python -m pytest_starter_config --preset full --target . --package myapp --yes
pytest-starter-config 0.1.0: preset=full format=pyproject features=[core, markers, coverage, parallel, randomize, conftest, starter]
Writing into /home/you/myapp:
  merge     pyproject.toml
    kept your existing keys (not overwritten): addopts
  create    conftest.py
  create    tests/test_starter.py

The generated config references these plugins:
  pip install pytest pytest-cov pytest-xdist pytest-randomly

Prefer to look before you leap? --dry-run prints a real unified diff and writes nothing:

$ python -m pytest_starter_config --preset standard --dry-run --yes
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,34 @@
+[tool.pytest.ini_options]
+# Strict, fail-fast pytest defaults for a trustworthy suite.
+# see: https://python-testing-debugging.com/.../pytest-configuration-best-practices/
+minversion = "7.0"
+addopts = "-ra --strict-markers --strict-config --cov=src ..."
...

Why this exists

Good pytest configuration is mostly a set of defaults you wish every project started with: treat warnings as errors so deprecations fail CI instead of production; --strict-markers and --strict-config so a typo in a marker or a config key is a hard error, not a silent no-op; xfail_strict so an xfail that starts passing tells you; registered markers with a hook that keeps slow and integration tests out of the default run. None of it is hard — it is just tedious to reassemble, and easy to get subtly wrong, on every new repo.

This tool encodes those defaults as composable features and assembles them. The generated blocks are commented so the config teaches as much as it configures; if you want the reasoning behind a particular default, each block links to the relevant write-up — for example, more on why unregistered markers should be a hard error.

Running it

pytest-starter-config is a self-contained, standard-library-only Python package. It has no third-party dependencies — it only writes files. (The config it emits references plugins like pytest-cov, pytest-xdist, and pytest-randomly; install those in the project you generate into, not here.)

Run it from a clone of the source:

git clone https://github.com/python-testing-debugging/pytest-starter-config.git
cd pytest-starter-config
python -m pytest_starter_config --help

Interactive mode (a short menu) runs when you launch it in a terminal without --yes; add --yes (or pipe input) for non-interactive/CI use.

Presets

Preset Features
minimal core, markers
standard core, markers, coverage, conftest, starter
full core, markers, coverage, parallel, randomize, conftest, starter

Features

Feature What it contributes
core Strict [tool.pytest.ini_options] defaults (always on).
markers Registered slow/integration/unit/smoke markers + auto-skip hook.
coverage --cov in addopts plus [tool.coverage.run]/[report].
parallel A note on opting into pytest-xdist (-n auto).
randomize A note on pytest-randomly and reproducing a failing order by seed.
conftest conftest.py fixtures: tmp_workspace, deterministic seed, a factory.
starter tests/test_starter.py demonstrating markers + parametrization.

Flags

Flag Purpose
--preset {minimal,standard,full} Starting feature set (default: standard).
--with FEATURE Turn a feature on (repeatable).
--without FEATURE Turn a feature off (repeatable).
--target DIR Directory to generate into (default: current directory).
--format {pyproject,ini} Config in pyproject.toml or a standalone pytest.ini.
--package NAME Import package coverage should measure (default: src).
--dry-run Print a unified diff of what would change; write nothing.
--force Overwrite existing conftest.py / test / pytest.ini files.
-y, --yes Non-interactive: accept the preset/flags without prompting.
--list-features Print available presets and features, then exit.

How it works

  1. Resolve the preset plus --with/--without into a final feature set, pulling in any required features (starter needs markers and conftest) and keeping mandatory ones (core).
  2. Render each feature's contributions: keys for the pytest section, addopts fragments, extra TOML sections (coverage), conftest.py blocks, and the starter test file. The __PACKAGE__ placeholder is filled from --package.
  3. Plan the writes. For pyproject format, if a pyproject.toml already exists the pytest section is merged key-by-key — your existing keys win (so re-running never overwrites your settings and is idempotent), and only missing keys are added. Coverage sections are added only if absent. Other files are never overwritten unless --force.
  4. Apply — or, for --dry-run, print a difflib unified diff and stop. If an existing pyproject.toml is too irregular to merge safely, the tool falls back to writing a standalone pytest.ini and tells you.

The generated conftest.py wires --run-slow / --run-integration options to the slow / integration markers, so pytest stays fast by default and pytest --run-slow opts in.

Exit codes

Code Meaning
0 Files generated (or dry-run diff printed) successfully.
2 Bad input — unknown feature or preset name.

Demo

Preview and then generate a full setup into a throwaway directory:

python -m pytest_starter_config --preset full --target ./demo-out --yes

Or run the bundled script, which does a dry-run preview followed by a real generation into a temp directory and prints the result:

./examples/demo.sh

Background reading

The defaults here come from the pytest configuration, fixture, and marker material at python-testing-debugging.com. For the reasoning behind each generated block:

License

MIT

About

Generate a strict, well-commented pytest config, conftest.py, markers, and starter tests in one command.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages