【问题标题】:User Stories structure [e.g in BDD]用户故事结构[例如在 BDD 中]
【发布时间】:2016-03-09 19:36:09
【问题描述】:

我目前正在思考如何构建最佳用户故事,就我而言,当我使用 BDD 方法时 - 在开发的开头编写用户故事。

假设我们有以下“新功能”:注册和帐户设置。在系统中是匿名的、经过身份验证的(登录其帐户的普通用户)和管理员用户(高级用户)作为角色。

匿名用户是唯一允许注册但不允许使用设置功能的用户,经过身份验证的用户可以更新其设置,管理员可以更新他的设置和其他内容,但两者都无法(再次)注册。

构建功能的最佳方式是什么 - 可能由不同的角色使用,但并非所有角色都以不同的方式使用 - 或者只能由 bdd 用户故事中的一个角色使用的功能?

【问题讨论】:

  • 您的问题似乎很有趣,但需要更精确,也许可以创建一个实施示例,以便提出真正可挽救的问题。

标签: php symfony bdd behat user-stories


【解决方案1】:

我相信您正在寻找的是一个场景大纲。

您似乎正在尝试实现这样的目标:

@javascript
Feature: When I am not logged in, I should not be able to access certain pages within the site

Rules:
- Logged in users should be able to see pages that users not logged in should not.
- Logged in users should not be able to follow a link to the registrations screen

Scenario Outline: Following links to the registrations screen.
Given I go to "<urlwithlink>"
And I click on "<link>"
And wait "(Insert time to wait for page to load here)"
Then the url should match "(Insert registrationsPage)"

Examples:
|urlwithlink|link|
(Put some examples here)

Scenario Outline: When I am logged in, I should not be able to follow those links
Given I am logged in as a user
And I go to "<urlwithlink>"
Then I should not see "<link>"

Examples:
|urlwithlink|link|
(Insert same examples as above)

Scenario: When I am not logged in, I should not be able to access the settings screen
Given I go to "(Insert where link to settings is, here)"
And the "(link to settings)" should be disabled (or use I should not see an "(link to settings)" element)

Scenario: When I am logged in, I should be able to access the settings screen
Given I am logged in as a user
And I go to "(Insert where link to settings is here)"
Then the "(link to settings)" should not be disabled (or use I should see an "(link to settings)" element)

如果您想要针对您的上下文的额外步骤:

 /**
 * @Then /^(?:|I )click (?:on |)(?:|the )"([^"]*)"(?:|.*)$/
 */
public
function iClickOn($arg1)
{
    $findName = $this->getSession()->getPage()->find("css", $arg1);
    if (!$findName) {
        throw new Exception($arg1 . " could not be found");
    } else {
        $findName->click();
    }
}

/**
 * Simply wait the period of time.
 *
 * @Given /^(?:I |)(?:wait|pause for|take a break for) "([^"]*)"(?:|.*)/
 * @param int $milliseconds
 *
 */
public
function wait($milliseconds)
{
    $this->getSession()->wait($milliseconds);
}

/**
 * @Then /^(?:|the |an? )"([^"]*)" (?:|element )(?:is|should)(?P<negate>(?:n\'t| not)?) (?:|be )disabled$/
 *
 * @param string $elementCSS
 * @param string $negate
 *
 * @throws Exception
 */
public function theElementShouldBeDisabled($elementCSS, $negate)
{
    {
        $page = $this->getSession()->getPage();
        $element = $page->find("css", $elementCSS);
        if (!$element) {
            throw new Exception($elementCSS . ' does not exist');
        }
        $attributeValue = $element->getAttribute("disabled");

        if (is_numeric(strpos($negate, ' not')) || is_numeric(strpos($negate, 'n\'t'))) {
            if ($attributeValue) {
                if (is_numeric(strpos($attributeValue, "disabled"))) {
                    throw new Exception('The element ' . $elementCSS . ' is disabled');
                }
            }
        } else {
            if (!$attributeValue) {
                throw new Exception($elementCSS . ' does not have a disabled attribute');
            } else if (!is_numeric(strpos($attributeValue, "disabled"))) {
                throw new Exception('The element ' . $elementCSS . ' is not disabled');
            }
        }
    }
}

应该这样做,我希望这会有所帮助。

如果您想以不同的方式组织设置,您可能希望将设置和链接拆分为两个不同的文件

【讨论】:

  • 感谢您的回答。是的,我想收集一些人们处理所描述情况的方法,以及大纲场景可能会处理它,感谢您的分享:)
  • 场景大纲是遵循相同步骤的最佳方式,无需每次都遵循相同的链接。 Behat 读取“场景大纲:”找到示例标题行,并获取其中的所有内容:,并将其替换为包含其中字母的列中的任何内容。我使用 Scenario Outlines 来提供面包屑、链接,并且能够在搜索框中搜索各种内容,而不会弄乱 .feature 文件。
  • 是的,我知道场景大纲是什么,这就是为什么我说它们“可能”是处理有时“角色问题”的一种方式,我并没有说这是一个非常好的解决方案,但是这里欢迎所有想法。我在互联网上进行了很多搜索,但找不到展示不同方法或至少任何方法的网站,这就是我创建此线程的原因。
【解决方案2】:

1) “作为[角色]”不是关于访问角色,而是关于谁需要该功能。大多数情况下,是一些利益相关者需要功能,以便公司能够从中受益并开展更好的业务。

2) 不同的访问应该在同一个特征文件中被更多的场景描述。但是,您的所有访问角色对于解释该功能并不重要。尽管 Gherkin 背后的工具可以测试,但 Gherkin 的功能和场景更多的是捕捉它们背后的想法,而不是涵盖所有可能的场景。选择 1 个积极的场景来涵盖每个功能,其余的则归结为较低的测试级别,主要是单元测试。

请记住测试金字塔,其中验收测试只占所有测试的一小部分。

【讨论】:

  • 感谢您的意见。我完全同意你的第二点,我使用 Behat 进行验收,使用 PHPUnit 进行集成,使用 phpspec 进行单元测试,但我不明白的是你的 nr。 1)。用户故事可能包含“作为经过身份验证的用户”或“作为匿名用户”等部分。这是利益相关者的意思吗?如果是这样,我也同意这一点,如果不是,请让我更详细地了解你的 nr 1 :)。你的最后一句话也是对的,但你也应该记住,即使它是一小部分,它是最重要的之一
  • 哦,是的,现在我明白了 - 匿名用户不是角色,这就是您的意思。是的,你是对的!
  • 广告 1) 假设它是一个单人网店项目,那么故事可能是这样的:“作为店主,我希望有一个用户注册,这样用户就不需要再次填写他们的凭据,很可能会再次购买”。也就是说,这个故事是关于描述该功能的好处。如果您有类似“作为用户我想注册以便我可以注册”之类的内容,则没有任何价值。
  • 广告 2) Behat 是关于描述您的应用程序的功能。一个简单的注册场景就足够描述了。当然,覆盖所有边缘情况很重要,但这不是 Behat 的目的,这就是为什么会有单元测试等较低级别的测试。
  • Symfony 是一个框架,而不是一个商业项目。特性文件中的故事是为了理解为什么会有这个特性。 BDD的作者可以在他的帖子http://dannorth.net/whats-in-a-story/告诉你更多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
相关资源
最近更新 更多