跳至内容

此示例演示了 README 中的故事通过命令行运行器运行。它可以直接复制和粘贴。

如果你想在 pytest 之外运行测试,这很有用。

它使用流行的 click 包来解释命令行参数。

代码示例

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: [email protected]
      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!")
runner.py

from hitchstory import StoryCollection
from click import argument, group, pass_context
from engine import Engine
from pathlib import Path

THIS_DIR = Path(__file__).absolute().parents[0]

STORIES = THIS_DIR.glob("*.story")

@group(invoke_without_command=True)
@pass_context
def cli(ctx):
    """Integration test command line interface."""
    pass

@cli.command()
@argument("keywords", nargs=-1)
def atdd(keywords):
    """
    Run single story with name matching keywords.
    """
    StoryCollection(STORIES, Engine())\
        .shortcut(*keywords)\
        .play()

@cli.command()
@argument("keywords", nargs=-1)
def ratdd(keywords):
    """
    Run single story with name matching keywords in rewrite mode.
    """
    StoryCollection(STORIES, Engine())\
        .shortcut(*keywords)\
        .play()

@cli.command()
def regression():
    """
    Run all tests.
    """
    StoryCollection(STORIES, Engine())\
        .only_uninherited()\
        .ordered_by_name()\
        .play()


if __name__ == "__main__":
    cli()

常规 ATDD

运行单个测试。

重写 ATDD

在重写模式下运行单个测试。

回归

运行所有测试。

可执行规范

basic-cli.story storytests 自动生成的文档。