{"id":34028747,"url":"https://github.com/davidjrice/autopytest","last_synced_at":"2026-04-05T11:32:20.770Z","repository":{"id":199985926,"uuid":"704573357","full_name":"davidjrice/autopytest","owner":"davidjrice","description":"autopytest observes file system events and runs the appropriate tests","archived":false,"fork":false,"pushed_at":"2024-07-15T16:32:28.000Z","size":96,"stargazers_count":4,"open_issues_count":11,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-20T20:02:00.325Z","etag":null,"topics":["ci","pytest","python","testing"],"latest_commit_sha":null,"homepage":"https://github.com/davidjrice/autopytest","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidjrice.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}},"created_at":"2023-10-13T14:48:29.000Z","updated_at":"2023-11-21T11:45:12.000Z","dependencies_parsed_at":"2023-10-15T01:41:49.568Z","dependency_job_id":"3e46bca4-409d-491f-a286-7f6b99b36991","html_url":"https://github.com/davidjrice/autopytest","commit_stats":null,"previous_names":["davidjrice/autotest"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/davidjrice/autopytest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjrice%2Fautopytest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjrice%2Fautopytest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjrice%2Fautopytest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjrice%2Fautopytest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidjrice","download_url":"https://codeload.github.com/davidjrice/autopytest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjrice%2Fautopytest/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31434624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"last_error":"SSL_read: 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":["ci","pytest","python","testing"],"created_at":"2025-12-13T17:17:45.620Z","updated_at":"2026-04-05T11:32:20.762Z","avatar_url":"https://github.com/davidjrice.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `autopytest`\n\n[![PyPI version][pypi-badge]][pypi-link]\n[![Python versions][python-versions-badge]][pypi-link]\n[![Build Status][build-badge]][build-link]\n[![Maintainability][maintainability-badge]][maintainability-link]\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d5d9781d11f6463e9fb1021c663e286e)](https://app.codacy.com/gh/davidjrice/autopytest/dashboard)\n[![Test Coverage][coverage-badge]][coverage-link]\n\nAn implementation of `autotest` for Python inspired by [autotest][] and [guard][].\n\n[autopytest](pypi-link) observes file change events and whenever you save a file it runs the appropriate tests with `pytest`.\n\n## Features\n\n`autopytest` observes file `modified` events and will perform the following:\n\n* source files\n  * will find and run the associated individual test file\n  * upon success, will run the entire suite\n  * if we can't find a matching test, run the entire suite\n* test files\n  * will run that test file\n  * upon success, will run the entire suite\n\n## Install\n\n```shell\n# pip\npip install autopytest\n\n# poetry\npoetry add autopytest\n```\n\n## Configuration\n\nIn your `pyproject.toml` add the following.\n\n```toml\n[tool.autopytest]\nsource_directories = [\"app\"]\ntest_directory = \"tests\"\n```\n\n## Usage\n\n```shell\ncd {project}\nautopytest\n\nautopytest {path}\n```\n\n## Project Structure\n\n* Test naming is *currently* important.\n* Multiple nested directory structures are supported as long as the convention is followed.\n\n### Applications\n\n#### `pyproject.toml` for applications\n\n```toml\n[tool.autopytest]\nsource_directories = [\"app\", \"lib\"]\ntest_directory = \"tests\"\n```\n\nGiven the above configuration. You should use a directory structure like the following. e.g. If `app/package/module.py` is edited we will attempt to locate and run `tests/app/package/test_module.py`\n\n```markdown\n📁 app\n    📄 __init__.py\n    📁 package\n        📄 __init__.py\n        📄 module.py\n📁 lib\n📁 tests\n    📄 __init__.py\n    📁 app\n        📁 package\n            📄 test_module.py\n    📁 lib\n```\n\n### Libraries\n\n#### `pyproject.toml` for libraries\n\n```toml\n[tool.autopytest]\ninclude_source_dir_in_test_path = false\nsource_directories = [\"src\"]\ntest_directory = \"tests\"\n```\n\nIf you are developing library and want your folder structure like the following. e.g. If `src/package/module.py` is edited we will attempt to locate and run `tests/package/test_module.py`\n\n```markdown\n📁 src\n    📁 package\n        📄 __init__.py\n        📄 module.py\n📁 tests\n    📁 package\n        📄 test_module.py\n```\n\n[autotest]: https://github.com/grosser/autotest\n[guard]: https://github.com/guard/guard\n[maintainability-badge]: https://api.codeclimate.com/v1/badges/f0ec7e4071d41519de65/maintainability\n[maintainability-link]: https://codeclimate.com/github/davidjrice/autopytest/maintainability\n[coverage-badge]: https://api.codeclimate.com/v1/badges/f0ec7e4071d41519de65/test_coverage\n[coverage-link]: https://codeclimate.com/github/davidjrice/autopytest/test_coverage\n[build-badge]: https://github.com/davidjrice/autopytest/actions/workflows/tests.yml/badge.svg\n[build-link]: https://github.com/davidjrice/autopytest/actions/workflows/tests.yml\n[pypi-badge]: https://badge.fury.io/py/autopytest.svg\n[pypi-link]: https://pypi.org/project/autopytest/\n[python-versions-badge]: https://img.shields.io/pypi/pyversions/autopytest.svg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidjrice%2Fautopytest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidjrice%2Fautopytest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidjrice%2Fautopytest/lists"}