diff --git a/hitch/story/basic-cli.story b/hitch/story/basic-cli.story index 9160664..5ef7038 100644 --- a/hitch/story/basic-cli.story +++ b/hitch/story/basic-cli.story @@ -1,6 +1,6 @@ Creating a basic command line test runner: docs: setup/basic-cli - based on: old quickstart + based on: quickstart about: | This example demonstrates the stories in the README being run via a command line runner. It can be directly diff --git a/hitch/story/old-quickstart.story b/hitch/story/old-quickstart.story deleted file mode 100644 index 0a3af73..0000000 --- a/hitch/story/old-quickstart.story +++ /dev/null @@ -1,92 +0,0 @@ -Old quickstart: - given: - files: - example.story: | - Logged in: - given: - website: /login # preconditions - steps: - - Form filled: - username: AzureDiamond - password: hunter2 - - Clicked: login - - - Email sent: - about: | - The most basic email with no subject, cc or bcc - set. - based on: logged in # inherits from and continues from test above - following steps: - - Clicked: new email - - Form filled: - to: Cthon98@aol.com - contents: | # long form text - Hey guys, - - I think I got hacked! - - Clicked: send email - - Email was sent - - engine.py: | - from hitchstory import BaseEngine, GivenDefinition, GivenProperty - from hitchstory import Failure, strings_match - from strictyaml import Str - - class Engine(BaseEngine): - given_definition = GivenDefinition( - website=GivenProperty(Str()), - ) - - def __init__(self, rewrite=False): - self._rewrite = rewrite - - def set_up(self): - print(f"Load web page at {self.given['website']}") - - def form_filled(self, **textboxes): - for name, contents in sorted(textboxes.items()): - print(f"Put {contents} in name") - - def clicked(self, name): - print(f"Click on {name}") - - def failing_step(self): - raise Failure("This was not supposed to happen") - - def error_message_displayed(self, expected_message): - """Demonstrates steps that can rewrite themselves.""" - actual_message = "error message!" - try: - strings_match(expected_message, actual_message) - except Failure: - if self._rewrite: - self.current_step.rewrite("expected_message").to(actual_message) - else: - raise - - def email_was_sent(self): - print("Check email was sent!") - - steps: - - Run: - code: | - from hitchstory import StoryCollection - from pathlib import Path - from engine import Engine - - StoryCollection(Path(".").glob("*.story"), Engine()).named("Email sent").play() - will output: |- - RUNNING Email sent in /path/to/working/example.story ... Load web page at /login - Put hunter2 in name - Put AzureDiamond in name - Click on login - Click on new email - Put Hey guys, - - I think I got hacked! - in name - Put Cthon98@aol.com in name - Click on send email - Check email was sent! - SUCCESS in 0.1 seconds. diff --git a/hitch/story/pytest-rewrite.story b/hitch/story/pytest-rewrite.story index 57a1999..5cf18e0 100644 --- a/hitch/story/pytest-rewrite.story +++ b/hitch/story/pytest-rewrite.story @@ -1,6 +1,6 @@ Self rewriting tests with pytest and hitchstory: docs: pytest/rewrite - based on: old quickstart + based on: quickstart given: files: failure.story: | diff --git a/hitch/story/quickstart-pytest.story b/hitch/story/quickstart-pytest.story new file mode 100644 index 0000000..0dcd6fe --- /dev/null +++ b/hitch/story/quickstart-pytest.story @@ -0,0 +1,157 @@ +Pytest Quickstart: + about: | + Minimal example (two files) demonstrating two short YAML tests and the + python code necessary to run them from within a pytest file. + given: + files: + example.story: | + Log in as James: + given: + browser: firefox # test preconditions + steps: + - Enter text: + username: james + password: password + - Click: log in + + See James analytics: + based on: log in as james # test inheritance + following steps: + - Click: analytics + test_hitchstory.py: | + from hitchstory import BaseEngine, GivenDefinition, GivenProperty + from hitchstory import Failure, strings_match + from hitchstory import StoryCollection + from strictyaml import Str + from pathlib import Path + from os import getenv + + class Engine(BaseEngine): + """Interprets and validates the hitchstory stories.""" + + given_definition = GivenDefinition( + browser=GivenProperty( + # Available validators: https://hitchdev.com/strictyaml/using/ + Str() + ), + ) + + def __init__(self, rewrite=False): + self._rewrite = rewrite + + def set_up(self): + print(f"Using browser {self.given['browser']}") + + def click(self, name): + print(f"Click on {name}") + + if name == "analytics": + raise Failure(f"button {name} not found") + + def enter_text(self, **textboxes): + for name, text in textboxes.items(): + print(f"Enter {text} in {name}") + + def tear_down(self): + pass + + + collection = StoryCollection( + # All .story files in this file's directory. + Path(__file__).parent.glob("*.story"), + + Engine( + # If REWRITE environment variable is set to yes -> rewrite mode. + rewrite=getenv("REWRITE", "no") == "yes" + ) + ) + + #You can embed the stories in tests manually: + #def test_log_in_as_james(): + # collection.named("Log in as james").play() + + #def test_see_james_analytics(): + # collection.named("See James analytics").play() + + # Or autogenerate runnable tests from the YAML stories like so: + # E.g. "Log in as James" -> "def test_login_in_as_james" + collection.with_external_test_runner().ordered_by_name().add_pytests_to( + module=__import__(__name__) # This module + ) + variations: + Run passing "log in as James" test: + about: | + Running test_log_in_as_james runs the "Log in as James" story. + steps: + - pytest: + args: -s -k test_log_in_as_james + will output: |- + ============================= test session starts ============================== + platform linux -- Python n.n.n, pytest-n.n.n, pluggy-n.n.n + rootdir: /path/to + collected 2 items / 1 deselected / 1 selected + + test_hitchstory.py Using browser firefox + Enter james in username + Enter password in password + Click on log in + . + + ======================= 1 passed, 1 deselected in 0.1s ======================== + + Run failing "see James' analytics" test: + about: | + Failing tests also have colors and highlighting when run for real. + steps: + - pytest: + expect failure: yes + args: -k test_see_james_analytics + will output: |- + ============================= test session starts ============================== + platform linux -- Python n.n.n, pytest-n.n.n, pluggy-n.n.n + rootdir: /path/to + collected 2 items / 1 deselected / 1 selected + + test_hitchstory.py F [100%] + + =================================== FAILURES =================================== + ___________________________ test_see_james_analytics ___________________________ + + story = Story('see-james-analytics') + + def hitchstory(story=story): + > story.play() + E hitchstory.exceptions.StoryFailure: RUNNING See James analytics in /path/to/example.story ... FAILED in 0.1 seconds. + E + E based on: log in as james # test inheritance + E following steps: + E - Click: analytics + E + E + E hitchstory.exceptions.Failure + E + E Test failed. + E + E button analytics not found + + /src/hitchstory/story_list.py:51: StoryFailure + ----------------------------- Captured stdout call ----------------------------- + Using browser firefox + Enter james in username + Enter password in password + Click on log in + Click on analytics + =========================== short test summary info ============================ + FAILED test_hitchstory.py::test_see_james_analytics - hitchstory.exceptions.StoryFailure: RUNNING See James analytics in /path/to/example.story ... FAILED in 0.1 seconds. + + based on: log in as james # test inheritance + following steps: + - Click: analytics + + + hitchstory.exceptions.Failure + + Test failed. + + button analytics not found + ======================= 1 failed, 1 deselected in 0.1s ======================== diff --git a/hitch/story/quickstart.story b/hitch/story/quickstart.story index 0c185d0..ec6dd20 100644 --- a/hitch/story/quickstart.story +++ b/hitch/story/quickstart.story @@ -1,157 +1,92 @@ Quickstart: - about: | - Minimal example (two files) demonstrating two short YAML tests and the - python code necessary to run them from within a pytest file. given: files: example.story: | - Log in as James: + Logged in: given: - browser: firefox # test preconditions + website: /login # preconditions steps: - - Enter text: - username: james - password: password - - Click: log in - - See James analytics: - based on: log in as james # test inheritance + - Form filled: + username: AzureDiamond + password: hunter2 + - Clicked: login + + + Email sent: + about: | + The most basic email with no subject, cc or bcc + set. + based on: logged in # inherits from and continues from test above following steps: - - Click: analytics - test_hitchstory.py: | + - Clicked: new email + - Form filled: + to: Cthon98@aol.com + contents: | # long form text + Hey guys, + + I think I got hacked! + - Clicked: send email + - Email was sent + + engine.py: | from hitchstory import BaseEngine, GivenDefinition, GivenProperty from hitchstory import Failure, strings_match - from hitchstory import StoryCollection from strictyaml import Str - from pathlib import Path - from os import getenv class Engine(BaseEngine): - """Interprets and validates the hitchstory stories.""" - given_definition = GivenDefinition( - browser=GivenProperty( - # Available validators: https://hitchdev.com/strictyaml/using/ - Str() - ), + website=GivenProperty(Str()), ) def __init__(self, rewrite=False): self._rewrite = rewrite def set_up(self): - print(f"Using browser {self.given['browser']}") + print(f"Load web page at {self.given['website']}") + + def form_filled(self, **textboxes): + for name, contents in sorted(textboxes.items()): + print(f"Put {contents} in name") - def click(self, name): + def clicked(self, name): print(f"Click on {name}") - - if name == "analytics": - raise Failure(f"button {name} not found") - def enter_text(self, **textboxes): - for name, text in textboxes.items(): - print(f"Enter {text} in {name}") + def failing_step(self): + raise Failure("This was not supposed to happen") - def tear_down(self): - pass - - - collection = StoryCollection( - # All .story files in this file's directory. - Path(__file__).parent.glob("*.story"), - - Engine( - # If REWRITE environment variable is set to yes -> rewrite mode. - rewrite=getenv("REWRITE", "no") == "yes" - ) - ) - - #You can embed the stories in tests manually: - #def test_log_in_as_james(): - # collection.named("Log in as james").play() - - #def test_see_james_analytics(): - # collection.named("See James analytics").play() - - # Or autogenerate runnable tests from the YAML stories like so: - # E.g. "Log in as James" -> "def test_login_in_as_james" - collection.with_external_test_runner().ordered_by_name().add_pytests_to( - module=__import__(__name__) # This module - ) - variations: - Run passing "log in as James" test: - about: | - Running test_log_in_as_james runs the "Log in as James" story. - steps: - - pytest: - args: -s -k test_log_in_as_james - will output: |- - ============================= test session starts ============================== - platform linux -- Python n.n.n, pytest-n.n.n, pluggy-n.n.n - rootdir: /path/to - collected 2 items / 1 deselected / 1 selected - - test_hitchstory.py Using browser firefox - Enter james in username - Enter password in password - Click on log in - . - - ======================= 1 passed, 1 deselected in 0.1s ======================== - - Run failing "see James' analytics" test: - about: | - Failing tests also have colors and highlighting when run for real. - steps: - - pytest: - expect failure: yes - args: -k test_see_james_analytics - will output: |- - ============================= test session starts ============================== - platform linux -- Python n.n.n, pytest-n.n.n, pluggy-n.n.n - rootdir: /path/to - collected 2 items / 1 deselected / 1 selected - - test_hitchstory.py F [100%] - - =================================== FAILURES =================================== - ___________________________ test_see_james_analytics ___________________________ - - story = Story('see-james-analytics') - - def hitchstory(story=story): - > story.play() - E hitchstory.exceptions.StoryFailure: RUNNING See James analytics in /path/to/example.story ... FAILED in 0.1 seconds. - E - E based on: log in as james # test inheritance - E following steps: - E - Click: analytics - E - E - E hitchstory.exceptions.Failure - E - E Test failed. - E - E button analytics not found - - /src/hitchstory/story_list.py:51: StoryFailure - ----------------------------- Captured stdout call ----------------------------- - Using browser firefox - Enter james in username - Enter password in password - Click on log in - Click on analytics - =========================== short test summary info ============================ - FAILED test_hitchstory.py::test_see_james_analytics - hitchstory.exceptions.StoryFailure: RUNNING See James analytics in /path/to/example.story ... FAILED in 0.1 seconds. - - based on: log in as james # test inheritance - following steps: - - Click: analytics - - - hitchstory.exceptions.Failure - - Test failed. - - button analytics not found - ======================= 1 failed, 1 deselected in 0.1s ======================== + def error_message_displayed(self, expected_message): + """Demonstrates steps that can rewrite themselves.""" + actual_message = "error message!" + try: + strings_match(expected_message, actual_message) + except Failure: + if self._rewrite: + self.current_step.rewrite("expected_message").to(actual_message) + else: + raise + + def email_was_sent(self): + print("Check email was sent!") + + steps: + - Run: + code: | + from hitchstory import StoryCollection + from pathlib import Path + from engine import Engine + + StoryCollection(Path(".").glob("*.story"), Engine()).named("Email sent").play() + will output: |- + RUNNING Email sent in /path/to/working/example.story ... Load web page at /login + Put hunter2 in name + Put AzureDiamond in name + Click on login + Click on new email + Put Hey guys, + + I think I got hacked! + in name + Put Cthon98@aol.com in name + Click on send email + Check email was sent! + SUCCESS in 0.1 seconds. diff --git a/hitch/story/rewrite-bugs.story b/hitch/story/rewrite-bugs.story index 59289b3..726845f 100644 --- a/hitch/story/rewrite-bugs.story +++ b/hitch/story/rewrite-bugs.story @@ -94,10 +94,10 @@ Rewrite single argument incorrect: /src/hitchstory/story_file.py - 91 : step_to_update[self._given_or_step.name] = text - 92 : else: - --> 93 : raise exceptions.RewriteFailure( - 94 : ( + 97 : step_to_update[self._given_or_step.name] = text + 98 : else: + --> 99 : raise exceptions.RewriteFailure( + 100 : (