{"id":18676599,"url":"https://github.com/hitchdev/hitchstory","last_synced_at":"2025-04-13T04:09:01.969Z","repository":{"id":65739323,"uuid":"79493405","full_name":"hitchdev/hitchstory","owner":"hitchdev","description":"Type-safe YAML integration tests. Tests that write your docs. Tests that rewrite themselves.","archived":false,"fork":false,"pushed_at":"2024-07-09T20:32:24.000Z","size":2687,"stargazers_count":95,"open_issues_count":6,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T08:27:43.974Z","etag":null,"topics":["bdd","bdd-framework","bdd-specs","bdd-style-testing-framework","bdd-tests","behavior-driven-development","documentation-tool","integration-testing","pytest","pytest-bdd","pytest-plugin","specification","strongly-typed","test-automation","testing","testing-framework","tests","yaml"],"latest_commit_sha":null,"homepage":"https://hitchdev.com/hitchstory","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hitchdev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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":"2017-01-19T20:45:39.000Z","updated_at":"2025-02-14T15:15:14.000Z","dependencies_parsed_at":"2023-10-01T21:43:12.833Z","dependency_job_id":"8296f3b1-94c3-4b2b-ac2f-f0e625b30d60","html_url":"https://github.com/hitchdev/hitchstory","commit_stats":null,"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hitchdev%2Fhitchstory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hitchdev%2Fhitchstory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hitchdev%2Fhitchstory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hitchdev%2Fhitchstory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hitchdev","download_url":"https://codeload.github.com/hitchdev/hitchstory/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248661704,"owners_count":21141450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["bdd","bdd-framework","bdd-specs","bdd-style-testing-framework","bdd-tests","behavior-driven-development","documentation-tool","integration-testing","pytest","pytest-bdd","pytest-plugin","specification","strongly-typed","test-automation","testing","testing-framework","tests","yaml"],"created_at":"2024-11-07T09:29:58.450Z","updated_at":"2025-04-13T04:09:01.938Z","avatar_url":"https://github.com/hitchdev.png","language":"Python","readme":"# HitchStory\n\n[![Main branch status](https://github.com/hitchdev/hitchstory/actions/workflows/regression.yml/badge.svg)](https://github.com/hitchdev/hitchstory/actions/workflows/regression.yml)\n\nType-safe [StrictYAML](https://hitchdev.com/hitchstory/why/strictyaml) python integration testing framework. With this\nframework, your tests can:\n\n## Rewrite themselves from program output (command line test example)\n\n![Test rewriting itself](https://hitchdev-videos.netlify.app/rewrite-demo.gif)\n\n## Autogenerate documentation (website test example)\n\n![Test writing docs](https://hitchdev-videos.netlify.app/rewrite-docs-demo.gif)\n\nThe tests can be run on their own or as pytest tests. \n\n## Demo projects with demo tests\n\nProject | Storytests | Python code | Doc template | Autogenerated docs\n---|---|---|---|---\n[Website](https://github.com/hitchdev/hitchstory/tree/master/examples/website) | [add todo](https://github.com/hitchdev/hitchstory/tree/master/examples/website/hitch/story/add-todo.story), [correct spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/website/hitch/story/correct-my-spelling.story) | [engine.py](https://github.com/hitchdev/hitchstory/tree/master/examples/website/hitch/engine.py) | [docstory.yml](https://github.com/hitchdev/hitchstory/tree/master/examples/website/hitch/docstory.yml) | [Add todo](https://github.com/hitchdev/hitchstory/blob/master/examples/website/hitch/docs/add-and-retrieve-todo.md), [Correct my spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/website/hitch/docs/correct-my-spelling.md)\n[REST API](https://github.com/hitchdev/hitchstory/tree/master/examples/restapi) | [add todo](https://github.com/hitchdev/hitchstory/tree/master/examples/restapi/hitch/story/add-todo.story), [correct spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/restapi/hitch/story/correct-my-spelling.story) | [engine.py](https://github.com/hitchdev/hitchstory/tree/master/examples/restapi/hitch/engine.py) | [docstory.yml](https://github.com/hitchdev/hitchstory/tree/master/examples/restapi/hitch/docstory.yml) | [Add todo](https://github.com/hitchdev/hitchstory/blob/master/examples/restapi/hitch/docs/add-and-retrieve-todo.md), [Correct my spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/restapi/hitch/docs/correct-my-spelling.md)\n[Interactive command line app](https://github.com/hitchdev/hitchstory/tree/master/examples/commandline) | [add todo](https://github.com/hitchdev/hitchstory/tree/master/examples/commandline/story/add-todo.story), [correct spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/commandline/story/correct-my-spelling.story) | [test_integration.py](https://github.com/hitchdev/hitchstory/tree/master/examples/commandline/tests/test_integration.py) | [docstory.yml](https://github.com/hitchdev/hitchstory/tree/master/examples/commandline/tests/docstory.yml) | [Add todo](https://github.com/hitchdev/hitchstory/blob/master/examples/commandline/docs/add-and-retrieve-todo.md), [Correct my spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/commandline/docs/correct-my-spelling.md)\n[A Python API](https://github.com/hitchdev/hitchstory/tree/master/examples/pythonapi) | [add todo](https://github.com/hitchdev/hitchstory/tree/master/examples/pythonapi/story/add-todo.story), [correct spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/pythonapi/story/correct-my-spelling.story) | [test_integration.py](https://github.com/hitchdev/hitchstory/tree/master/examples/pythonapi/tests/test_integration.py) | [docstory.yml](https://github.com/hitchdev/hitchstory/tree/master/examples/pythonapi/tests/docstory.yml) | [Add todo](https://github.com/hitchdev/hitchstory/blob/master/examples/pythonapi/docs/add-and-retrieve-todo.md), [Correct my spelling](https://github.com/hitchdev/hitchstory/tree/master/examples/pythonapi/docs/correct-my-spelling.md)\n\n\n\n\n\n\n# Code Example\n\n\n\nexample.story:\n\n```yaml\nLogged in:\n  given:\n    website: /login  # preconditions\n  steps:\n  - Form filled:\n      username: AzureDiamond\n      password: hunter2\n  - Clicked: login\n\n\nEmail sent:\n  about: |\n    The most basic email with no subject, cc or bcc\n    set.\n  based on: logged in             # inherits from and continues from test above\n  following steps:\n  - Clicked: new email\n  - Form filled:\n      to: Cthon98@aol.com\n      contents: |                # long form text\n        Hey guys,\n\n        I think I got hacked!\n  - Clicked: send email\n  - Email was sent\n```\nengine.py:\n\n```python\nfrom hitchstory import BaseEngine, GivenDefinition, GivenProperty\nfrom hitchstory import Failure, strings_match\nfrom strictyaml import Str\n\nclass Engine(BaseEngine):\n    given_definition = GivenDefinition(\n        website=GivenProperty(Str()),\n    )\n    \n    def __init__(self, rewrite=False):\n        self._rewrite = rewrite\n\n    def set_up(self):\n        print(f\"Load web page at {self.given['website']}\")\n\n    def form_filled(self, **textboxes):\n        for name, contents in sorted(textboxes.items()):\n            print(f\"Put {contents} in name\")\n\n    def clicked(self, name):\n        print(f\"Click on {name}\")\n    \n    def failing_step(self):\n        raise Failure(\"This was not supposed to happen\")\n    \n    def error_message_displayed(self, expected_message):\n        \"\"\"Demonstrates steps that can rewrite themselves.\"\"\"\n        actual_message = \"error message!\"\n        try:\n            strings_match(expected_message, actual_message)\n        except Failure:\n            if self._rewrite:\n                self.current_step.rewrite(\"expected_message\").to(actual_message)\n            else:\n                raise\n\n    def email_was_sent(self):\n        print(\"Check email was sent!\")\n```\n\n\n\n\n\n\n```python\n\u003e\u003e\u003e from hitchstory import StoryCollection\n\u003e\u003e\u003e from pathlib import Path\n\u003e\u003e\u003e from engine import Engine\n\u003e\u003e\u003e \n\u003e\u003e\u003e StoryCollection(Path(\".\").glob(\"*.story\"), Engine()).named(\"Email sent\").play()\nRUNNING Email sent in /path/to/working/example.story ... Load web page at /login\nPut hunter2 in name\nPut AzureDiamond in name\nClick on login\nClick on new email\nPut Hey guys,\n\nI think I got hacked!\n in name\nPut Cthon98@aol.com in name\nClick on send email\nCheck email was sent!\nSUCCESS in 0.1 seconds.\n```\n\n\n\n\n\n\n\n\n## Install\n\n```bash\n$ pip install hitchstory\n```\n\n## Community\n\nHelp is available if you ask questions in these places: [Github discussions](https://github.com/hitchdev/hitchstory/discussions) | [Github issues](https://github.com/hitchdev/hitchstory/issues) (not just for bugs) | [Slack channel](https://join.slack.com/t/hitchstory/shared_invite/zt-1uvrtozlz-vK92y5HN4SETkriUbBIHUQ)\n\n## Using HitchStory\n\nEvery feature of this library is documented and listed below.\nIt is tested and documented with itself.\n\n\n## Using HitchStory: With Pytest\n\nIf you already have pytest set up, you can quickly and easily write\na test using hitchstory that runs alongside your other pytest tests:\n\n- [Self rewriting tests with pytest and hitchstory](https://hitchdev.com/hitchstory/using/pytest/rewrite)\n\n\n## Using HitchStory: Engine\n\nHow to use the different features of the story engine:\n\n- [Hiding stacktraces for expected exceptions](https://hitchdev.com/hitchstory/using/engine/expected-exceptions)\n- [Given preconditions](https://hitchdev.com/hitchstory/using/engine/given)\n- [Gradual typing of story steps](https://hitchdev.com/hitchstory/using/engine/gradual-typing)\n- [Match two JSON snippets](https://hitchdev.com/hitchstory/using/engine/match-json)\n- [Match two strings and show diff on failure](https://hitchdev.com/hitchstory/using/engine/match-two-strings)\n- [Extra story metadata - e.g. adding JIRA ticket numbers to stories](https://hitchdev.com/hitchstory/using/engine/metadata)\n- [Story with parameters](https://hitchdev.com/hitchstory/using/engine/parameterized-stories)\n- [Story that rewrites given preconditions](https://hitchdev.com/hitchstory/using/engine/rewrite-given)\n- [Story that rewrites itself](https://hitchdev.com/hitchstory/using/engine/rewrite-story)\n- [Story that rewrites the sub key of an argument](https://hitchdev.com/hitchstory/using/engine/rewrite-subkey-of-argument)\n- [Raising a Failure exception to conceal the stacktrace](https://hitchdev.com/hitchstory/using/engine/special-failure-exception)\n- [Arguments to steps](https://hitchdev.com/hitchstory/using/engine/steps-and-step-arguments)\n- [Strong typing](https://hitchdev.com/hitchstory/using/engine/strong-typing)\n\n\n## Using HitchStory: Documentation Generation\n\nHow to autogenerate documentation from your tests:\n\n- [Generate documentation with extra variables and functions](https://hitchdev.com/hitchstory/using/documentation/extra)\n- [Generate documentation from story](https://hitchdev.com/hitchstory/using/documentation/generate)\n\n\n## Using HitchStory: Inheritance\n\nInheriting stories from each other:\n\n- [Inherit one story from another simply](https://hitchdev.com/hitchstory/using/inheritance/about)\n- [Story inheritance - given mapping preconditions overridden](https://hitchdev.com/hitchstory/using/inheritance/override-given-mapping)\n- [Story inheritance - override given scalar preconditions](https://hitchdev.com/hitchstory/using/inheritance/override-given-scalar)\n- [Story inheritance - parameters](https://hitchdev.com/hitchstory/using/inheritance/parameters)\n- [Story inheritance - steps](https://hitchdev.com/hitchstory/using/inheritance/steps)\n- [Variations](https://hitchdev.com/hitchstory/using/inheritance/variations)\n\n\n## Using HitchStory: Runner\n\nRunning the stories in different ways:\n\n- [Continue on failure when playing multiple stories](https://hitchdev.com/hitchstory/using/runner/continue-on-failure)\n- [Flaky story detection](https://hitchdev.com/hitchstory/using/runner/flaky-story-detection)\n- [Play multiple stories in sequence](https://hitchdev.com/hitchstory/using/runner/play-multiple-stories-in-sequence)\n- [Run one story in collection](https://hitchdev.com/hitchstory/using/runner/run-just-one-story)\n- [Shortcut lookup for story names](https://hitchdev.com/hitchstory/using/runner/shortcut-lookup)\n\n\n## Approach to using HitchStory\n\nBest practices, how the tool was meant to be used, etc.\n\n- [Is HitchStory a BDD tool? How do I do BDD with hitchstory?](https://hitchdev.com/hitchstory/approach/bdd)\n- [Complementary tools](https://hitchdev.com/hitchstory/approach/complementary-tools)\n- [Domain Appropriate Scenario Language (DASL)](https://hitchdev.com/hitchstory/approach/domain-appropriate-scenario-language-dasl)\n- [Executable specifications](https://hitchdev.com/hitchstory/approach/executable-specifications)\n- [Flaky Tests](https://hitchdev.com/hitchstory/approach/flaky-tests)\n- [The Hermetic End to End Testing Pattern](https://hitchdev.com/hitchstory/approach/hermetic-end-to-end-test)\n- [ANTIPATTERN - Analysts writing stories for the developer](https://hitchdev.com/hitchstory/approach/human-writable)\n- [Separation of Test Concerns](https://hitchdev.com/hitchstory/approach/separation-of-test-concerns)\n- [Snapshot Test Driven Development (STDD)](https://hitchdev.com/hitchstory/approach/snapshot-test-driven-development-stdd)\n- [Test Artefact Environment Isolation](https://hitchdev.com/hitchstory/approach/test-artefact-environment-isolation)\n- [Test concern leakage](https://hitchdev.com/hitchstory/approach/test-concern-leakage)\n- [Tests as an investment](https://hitchdev.com/hitchstory/approach/test-investment)\n- [What is the difference betweeen a test and a story?](https://hitchdev.com/hitchstory/approach/test-or-story)\n- [The importance of test realism](https://hitchdev.com/hitchstory/approach/test-realism)\n- [Testing non-deterministic code](https://hitchdev.com/hitchstory/approach/testing-nondeterministic-code)\n- [Specification Documentation Test Triality](https://hitchdev.com/hitchstory/approach/triality)\n\n\n## Design decisions and principles\n\nDesign decisions are justified here:\n\n- [Declarative User Stories](https://hitchdev.com/hitchstory/why/declarative)\n- [Why does hitchstory mandate the use of given but not when and then?](https://hitchdev.com/hitchstory/why/given-when-then)\n- [Why is inheritance a feature of hitchstory stories?](https://hitchdev.com/hitchstory/why/inheritance)\n- [Why does hitchstory not have an opinion on what counts as interesting to \"the business\"?](https://hitchdev.com/hitchstory/why/interesting-to-the-business)\n- [Why does hitchstory not have a command line interface?](https://hitchdev.com/hitchstory/why/no-cli)\n- [Principles](https://hitchdev.com/hitchstory/why/principles)\n- [Why does HitchStory have no CLI runner - only a pure python API?](https://hitchdev.com/hitchstory/why/pure-python-no-cli)\n- [Why Rewritable Test Driven Development (RTDD)?](https://hitchdev.com/hitchstory/why/rewrite)\n- [Why does HitchStory use StrictYAML?](https://hitchdev.com/hitchstory/why/strictyaml)\n\n\n## Why not X instead?\n\nHitchStory is not the only integration testing framework.\nThis is how it compares with the others:\n\n- [Why use Hitchstory instead of Behave, Lettuce or Cucumber (Gherkin)?](https://hitchdev.com/hitchstory/why-not/gherkin)\n- [Why not use the Robot Framework?](https://hitchdev.com/hitchstory/why-not/robot)\n- [Why use hitchstory instead of a unit testing framework?](https://hitchdev.com/hitchstory/why-not/unit-test)\n\n\n## Using HitchStory: Setup on its own\n\nIf you want to use HitchStory without pytest:\n\n- [Creating a basic command line test runner](https://hitchdev.com/hitchstory/using/setup/basic-cli)\n\n\n## Using HitchStory: Behavior\n\nMiscellaneous docs about behavior of the framework:\n\n- [Abort a story with ctrl-C](https://hitchdev.com/hitchstory/using/behavior/aborting)\n- [Upgrade breaking changes between v0.14 and v0.15](https://hitchdev.com/hitchstory/using/behavior/breaking-changes-between-v014-and-v015)\n- [Handling failing tests](https://hitchdev.com/hitchstory/using/behavior/failing-tests)\n- [Running a single named story successfully](https://hitchdev.com/hitchstory/using/behavior/run-single-named-story)\n\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhitchdev%2Fhitchstory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhitchdev%2Fhitchstory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhitchdev%2Fhitchstory/lists"}