跳至内容

代码示例

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!")
failure.story

Failing story:
  given:
    website: /login  # preconditions
  steps:
  - Failing step
rewritable.story

Rewritable story:
  given:
    website: /error
  steps:
  - Error message displayed: old message
test_integration.py

from hitchstory import StoryCollection
from pathlib import Path
from engine import Engine
import os

hs = StoryCollection(
    # All *.story files in this test's directory
    Path(__file__).parent.glob("*.story"),

    # Rewrite if REWRITE environment variable is set to yes
    Engine(rewrite=os.getenv("REWRITE", "") == "yes")
).with_external_test_runner()

def test_email_sent():
    hs.named("Email sent").play()

def test_logged_in():
    hs.named("Logged in").play()
test_other.py

from hitchstory import StoryCollection
from pathlib import Path
from engine import Engine
import os

hs = StoryCollection(
    # All *.story files in this test's directory
    Path(__file__).parent.glob("*.story"),

    # Rewrite if REWRITE environment variable is set to yes
    Engine(rewrite=os.getenv("REWRITE", "") == "yes")
).with_external_test_runner()

def test_failure():
    hs.named("Failing story").play()

def test_rewritable():
    hs.named("Rewritable story").play()

运行所有通过的测试

这将运行 test_integration.py 中的两个测试。

pytest test_integration.py

输出

============================= test session starts ==============================
platform linux -- Python n.n.n, pytest-n.n.n, pluggy-n.n.n
rootdir: /path/to
collected 2 items

test_integration.py ..                                                   [100%]

============================== 2 passed in 0.1s ===============================

重写故事

通过设置环境变量 REWRITE 为“yes”,可以配置 pytest 以重写模式运行测试。

当前唯一配置为自我重写的 story 是 test_other.py 中的 test_rewritable。

REWRITE=yes pytest -k test_rewritable test_other.py

输出

============================= 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_other.py .                                                          [100%]

======================= 1 passed, 1 deselected in 0.1s ========================

文件 rewritable.story 现在应该包含

Rewritable story:
  given:
    website: /error
  steps:
  - Error message displayed: error message!

失败的测试

失败的测试将导致引发 StoryFailure 异常。

异常中的消息将包含测试失败的步骤的详细信息。

对于大多数异常(不是这个),还将显示堆栈跟踪。

请注意,如果在命令行上运行,[[ COLOR ]] 将被替换为实际颜色。

pytest -k test_failure test_other.py

输出

============================= 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_other.py F                                                          [100%]

=================================== FAILURES ===================================
_________________________________ test_failure _________________________________

    def test_failure():
>       hs.named("Failing story").play()
E       hitchstory.exceptions.StoryFailure: RUNNING Failing story in /path/to/failure.story ... FAILED in 0.1 seconds.
E
E               website: /login  # preconditions
E             steps:
E             - Failing step
E
E
E       hitchstory.exceptions.Failure
E
E           Test failed.
E
E       This was not supposed to happen

test_other.py:15: StoryFailure
----------------------------- Captured stdout call -----------------------------
Load web page at /login
=========================== short test summary info ============================
FAILED test_other.py::test_failure - hitchstory.exceptions.StoryFailure: RUNNING Failing story in /path/to/failure.story ... FAILED in 0.1 seconds.

        website: /login  # preconditions
      steps:
      - Failing step


hitchstory.exceptions.Failure

    Test failed.

This was not supposed to happen
======================= 1 failed, 1 deselected in 0.1s ========================

可执行规范

pytest-rewrite.story storytests 自动生成的文档。