{"id":16610832,"url":"https://github.com/max-sixty/pytest-accept","last_synced_at":"2026-03-01T07:00:20.415Z","repository":{"id":37953358,"uuid":"245051470","full_name":"max-sixty/pytest-accept","owner":"max-sixty","description":"A pytest plugin for automatically updating doctest outputs","archived":false,"fork":false,"pushed_at":"2026-02-23T21:58:32.000Z","size":509,"stargazers_count":71,"open_issues_count":1,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-25T02:25:04.666Z","etag":null,"topics":["literate-testing","pytest","regression-testing","snapshot-testing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/max-sixty.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-03-05T02:34:19.000Z","updated_at":"2026-02-23T21:58:34.000Z","dependencies_parsed_at":"2023-02-19T11:16:07.384Z","dependency_job_id":"a596bb6f-6f91-45d3-a083-15a9e82df65b","html_url":"https://github.com/max-sixty/pytest-accept","commit_stats":{"total_commits":116,"total_committers":5,"mean_commits":23.2,"dds":0.6206896551724138,"last_synced_commit":"d809c24c576d9709fe04d660b5c21a4a7cda6876"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/max-sixty/pytest-accept","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sixty%2Fpytest-accept","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sixty%2Fpytest-accept/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sixty%2Fpytest-accept/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sixty%2Fpytest-accept/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/max-sixty","download_url":"https://codeload.github.com/max-sixty/pytest-accept/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sixty%2Fpytest-accept/sbom","scorecard":{"id":492312,"data":{"date":"2025-08-11","repo":{"name":"github.com/max-sixty/pytest-accept","commit":"1ef52ed897b318985f3983a3d65677c5915778da"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/9 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"23 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pypi-release-test.yaml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/pypi-release-test.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pypi-release-test.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/pypi-release-test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pypi-release.yaml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/pypi-release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pypi-release.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/pypi-release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pypi-release.yaml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/pypi-release.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/test.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yaml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/max-sixty/pytest-accept/test.yaml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/test.yaml:26","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/pypi-release-test.yaml:1","Warn: no topLevel permission defined: .github/workflows/pypi-release.yaml:1","Warn: no topLevel permission defined: .github/workflows/test.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/pypi-release.yaml:8"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T19:29:52.897Z","repository_id":37953358,"created_at":"2025-08-19T19:29:52.897Z","updated_at":"2025-08-19T19:29:52.897Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29963117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T06:55:38.174Z","status":"ssl_error","status_checked_at":"2026-03-01T06:53:04.810Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["literate-testing","pytest","regression-testing","snapshot-testing"],"created_at":"2024-10-12T01:32:52.712Z","updated_at":"2026-03-01T07:00:20.338Z","avatar_url":"https://github.com/max-sixty.png","language":"Python","funding_links":[],"categories":["Plugins"],"sub_categories":[],"readme":"# pytest-accept\n\n[![GitHub Workflow CI Status](https://img.shields.io/github/actions/workflow/status/max-sixty/pytest-accept/test.yaml?branch=main\u0026logo=github\u0026style=for-the-badge)](https://github.com/max-sixty/pytest-accept/actions?query=workflow:test)\n[![PyPI Version](https://img.shields.io/pypi/v/pytest-accept?style=for-the-badge)](https://pypi.python.org/pypi/pytest-accept/)\n[![GitHub License](https://img.shields.io/github/license/max-sixty/pytest-accept?style=for-the-badge)](https://github.com/max-sixty/pytest-accept/blob/main/LICENSE)\n\npytest-accept is a pytest plugin for automatically updating outputs. It runs\nalong with pytest, observes the generated outputs, and writes them to the test's\ndocumented outputs.\n\n## Before\n\n```python\ndef extract_functions(code):\n    return re.findall(r\"(\\w+)\\(\", code)\n\n\ndef test_extract_functions():\n    assert extract_functions(\"print('hi')\") == [\"print\"]\n    assert extract_functions(\"sum(map(f, x))\") == [\"sum\"]\n```\n\n## After `pytest --accept`\n\n```diff\ndef test_extract_functions():\n    assert extract_functions(\"print('hi')\") == [\"print\"]\n-   assert extract_functions(\"sum(map(f, x))\") == [\"sum\"]\n+   assert extract_functions(\"sum(map(f, x))\") == [\"sum\", \"map\"]\n```\n\npytest-accept is decoupled from the tests it works with — it can be used with\nexisting tests, and the tests it edits are no different from normal tests. It\nworks with both doctests and normal `assert` statements.\n\n## Installation\n\n```sh\nuv tool install -U pytest-accept\n```\n\nOr with pip:\n\n```sh\npip install pytest-accept\n```\n\nTo run, just pass `--accept` to pytest:\n\n```sh\npytest --accept\n```\n\n## Why?\n\n- Often it's fairly easy to observe whether something is working by viewing the\n  output it produces\n- ...but often the output is verbose, and copying and pasting the output into\n  the test is tedious\n- `pytest-accept` does the copying \u0026 pasting for you\n- Similarly, lots of folks generally find writing any tests a bit annoying, and\n  prefer to develop by \"running the code and seeing if it works\". This library\n  aims to make testing a joyful part of that development loop\n\nThis style of testing is fairly well-developed in some languages, although still\ndoesn't receive the attention I think it deserves, and historically hasn't had\ngood support in python.\n\nThe best explanation I've seen on this testing style is from\n**[@yminsky](https://github.com/yminsky)** in a\n[Jane Street Blogpost](https://blog.janestreet.com/testing-with-expectations/).\n**[@matklad](https://github.com/matklad)** also has an excellent summary in his\nblog post [How to Test](https://matklad.github.io//2021/05/31/how-to-test.html).\n\n## How it works\n\n`pytest-accept`:\n\n- Intercepts test failures from both doctests and assert statements\n- Parses the files to understand where the documented values are\n- Updates the documented values to match the generated values\n- Writes everything back atomically\n\nThings to know:\n\n- **Simple comparisons only**: Assert rewriting only works with `==` comparisons\n  against literals or simple expressions\n- **Overwrite by default**: Pass `--accept-copy` to write to `.py.new` files\n  instead.\n\n\u003cdetails\u003e\n\u003csummary\u003eDoctest quirks\u003c/summary\u003e\n\nDoctests are great for examples, but they have quirks\n\n- Use raw strings for examples with backslashes:\n\n  ```python\n  r\"\"\"\n  \u003e\u003e\u003e print(\"\\n\")\n  \\n\n  \"\"\"\n  ```\n\n- We handle blank lines automatically:\n\n  ```python\n  \"\"\"\n  \u003e\u003e\u003e print(\"one\\n\\ntwo\")\n  one\n  \u003cBLANKLINE\u003e\n  two\n  \"\"\"\n  ```\n\n- Really long outputs get truncated so they won't break your editor\n\n\u003c/details\u003e\n\n## Prior art\n\nThis testing style goes by many names: \"snapshot testing\", \"regression testing\",\n\"expect testing\", \"literate testing\", or \"acceptance testing\". Whatever the\nname, the pattern is the same: write tests, see what they produce, accept what's\ncorrect.\n\n[@matklad](https://github.com/matklad) has an excellent overview in\n[How to Test](https://matklad.github.io//2021/05/31/how-to-test.html). The\napproach is well-established in many languages:\n\n- [cram](https://bitheap.org/cram/) (command-line tests)\n- [ppx_expect](https://github.com/janestreet/ppx_expect) (OCaml)\n- [insta](https://github.com/mitsuhiko/insta) (Rust)\n\nFor more complex test scenarios, consider:\n\n- [pytest-regtest](https://gitlab.com/uweschmitt/pytest-regtest) for file-based\n  testing\n- [syrupy](https://github.com/tophat/syrupy) for snapshot testing\n- [pytest-insta](https://github.com/vberlier/pytest-insta) for insta-style\n  review\n\nthanks to [@untiaker](https://github.com/untitaker), who found how to expand the\noriginal doctest solution into an approach that works with standard `assert`\nstatements.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmax-sixty%2Fpytest-accept","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmax-sixty%2Fpytest-accept","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmax-sixty%2Fpytest-accept/lists"}