https://github.com/max-sixty/pytest-accept
A pytest plugin for automatically updating doctest outputs
https://github.com/max-sixty/pytest-accept
literate-testing pytest regression-testing snapshot-testing
Last synced: 3 months ago
JSON representation
A pytest plugin for automatically updating doctest outputs
- Host: GitHub
- URL: https://github.com/max-sixty/pytest-accept
- Owner: max-sixty
- License: apache-2.0
- Created: 2020-03-05T02:34:19.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2026-02-23T21:58:32.000Z (4 months ago)
- Last Synced: 2026-02-25T02:25:04.666Z (4 months ago)
- Topics: literate-testing, pytest, regression-testing, snapshot-testing
- Language: Python
- Homepage:
- Size: 497 KB
- Stars: 71
- Watchers: 2
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-pytest - pytest-accept - Plugin to automatically update doctest outputs. It runs doctests, observes the generated outputs, and writes them to the doctests' documented outputs. (Plugins)
README
# pytest-accept
[](https://github.com/max-sixty/pytest-accept/actions?query=workflow:test)
[](https://pypi.python.org/pypi/pytest-accept/)
[](https://github.com/max-sixty/pytest-accept/blob/main/LICENSE)
pytest-accept is a pytest plugin for automatically updating outputs. It runs
along with pytest, observes the generated outputs, and writes them to the test's
documented outputs.
## Before
```python
def extract_functions(code):
return re.findall(r"(\w+)\(", code)
def test_extract_functions():
assert extract_functions("print('hi')") == ["print"]
assert extract_functions("sum(map(f, x))") == ["sum"]
```
## After `pytest --accept`
```diff
def test_extract_functions():
assert extract_functions("print('hi')") == ["print"]
- assert extract_functions("sum(map(f, x))") == ["sum"]
+ assert extract_functions("sum(map(f, x))") == ["sum", "map"]
```
pytest-accept is decoupled from the tests it works with — it can be used with
existing tests, and the tests it edits are no different from normal tests. It
works with both doctests and normal `assert` statements.
## Installation
```sh
uv tool install -U pytest-accept
```
Or with pip:
```sh
pip install pytest-accept
```
To run, just pass `--accept` to pytest:
```sh
pytest --accept
```
## Why?
- Often it's fairly easy to observe whether something is working by viewing the
output it produces
- ...but often the output is verbose, and copying and pasting the output into
the test is tedious
- `pytest-accept` does the copying & pasting for you
- Similarly, lots of folks generally find writing any tests a bit annoying, and
prefer to develop by "running the code and seeing if it works". This library
aims to make testing a joyful part of that development loop
This style of testing is fairly well-developed in some languages, although still
doesn't receive the attention I think it deserves, and historically hasn't had
good support in python.
The best explanation I've seen on this testing style is from
**[@yminsky](https://github.com/yminsky)** in a
[Jane Street Blogpost](https://blog.janestreet.com/testing-with-expectations/).
**[@matklad](https://github.com/matklad)** also has an excellent summary in his
blog post [How to Test](https://matklad.github.io//2021/05/31/how-to-test.html).
## How it works
`pytest-accept`:
- Intercepts test failures from both doctests and assert statements
- Parses the files to understand where the documented values are
- Updates the documented values to match the generated values
- Writes everything back atomically
Things to know:
- **Simple comparisons only**: Assert rewriting only works with `==` comparisons
against literals or simple expressions
- **Overwrite by default**: Pass `--accept-copy` to write to `.py.new` files
instead.
Doctest quirks
Doctests are great for examples, but they have quirks
- Use raw strings for examples with backslashes:
```python
r"""
>>> print("\n")
\n
"""
```
- We handle blank lines automatically:
```python
"""
>>> print("one\n\ntwo")
one
two
"""
```
- Really long outputs get truncated so they won't break your editor
## Prior art
This testing style goes by many names: "snapshot testing", "regression testing",
"expect testing", "literate testing", or "acceptance testing". Whatever the
name, the pattern is the same: write tests, see what they produce, accept what's
correct.
[@matklad](https://github.com/matklad) has an excellent overview in
[How to Test](https://matklad.github.io//2021/05/31/how-to-test.html). The
approach is well-established in many languages:
- [cram](https://bitheap.org/cram/) (command-line tests)
- [ppx_expect](https://github.com/janestreet/ppx_expect) (OCaml)
- [insta](https://github.com/mitsuhiko/insta) (Rust)
For more complex test scenarios, consider:
- [pytest-regtest](https://gitlab.com/uweschmitt/pytest-regtest) for file-based
testing
- [syrupy](https://github.com/tophat/syrupy) for snapshot testing
- [pytest-insta](https://github.com/vberlier/pytest-insta) for insta-style
review
thanks to [@untiaker](https://github.com/untitaker), who found how to expand the
original doctest solution into an approach that works with standard `assert`
statements.