【问题标题】:Some questions about the process of BDD from a beginner一个初学者关于BDD过程的一些问题
【发布时间】:2015-11-29 15:29:09
【问题描述】:

这几天我读了几篇关于BDD 的文章,想知道它在说什么。现在我有了一个基本的了解,但还不清楚整个过程。

以下是我认为在 BDD 流程中应该做的事情:

  1. 所有利益相关者(BA、客户、开发人员、QA)坐在一起讨论需求,并将商定的功能写在故事卡上。这里我以“用户注册”功能为例:

    As a user,
    I want to register on the system,
    so that I can use its services
    
  2. 创建几个Given/When/Then格式的场景,这里是其中之一:

    Scenario: user successfully register
        Given an register page
        And an un-registered user
        When the user fills username "Jeff" and password "123456"
        And click on "Register"
        Then the user can see a "Success" message
        And the user "Jeff" is created in the system
    
  3. 用一些 BDD 测试框架来实现这个场景,比如cucumber-jvm,比如:

    import cucumber.api.java.en.Given;
    
    public class Stepdefs {
        @Given("an register page")
        public void an_register_page throws Throwable {
            // ...
        }
        @Given("an un-registered user")
        public void an_register_page throws Throwable {
            // ...
        }
        // ...
    }
    

    一步一步来。

    但我很快就发现自己遇到了麻烦:有页面、模型,也许这个场景需要数据库,似乎有很多事情要做。

我现在该怎么办?

我现在该怎么办?我是否需要与所有利益相关者讨论这种情况?对于BA/Customer/QA,我认为他们并不真正关心实现,与其他开发人员讨论是否是个好主意?

假设在我与其他一些开发人员讨论后,我们同意将其拆分为几个小部分。我们可以将这些小部分制作成 Scenario/Given/When/Then 格式的“场景”,就像我们刚刚在 cucumber-jvm 中所做的那样,或者我们可以像在 TDD 中那样使用 JUnit 吗?

1. If choose "cucumber-jvm", it seems a little heavy for small part
2. If choose JUnit, we need to involve more than one testing framework in a project
3. Is it the best if there is a single testing framework to do both things (not sure if there is)

假设我选择选项2,使用 JUnit 处理小任务

以下是我做出这个决定后要做的事情:

  1. 现在我们创建新的小测试来驱动实现,例如在数据库中创建用户,就像我们通常在 TDD 中所做的那样。 (红色->绿色->重构)。我们暂时不关心黄瓜测试Scenario: user successfully register(失败),把它留在那里。对吧?

  2. 我们使用 JUnit 开发了更多小测试,将它们设置为红色 -> 绿色 -> 重构。 (而且不完整的黄瓜测试总是失败)

  3. 直到所有小测试都通过,我们转向黄瓜测试Scenario: user successfully register。完成它并确保它最后变成绿色。

  4. 现在再开发一个场景,如果简单的话,我们可以只用cucumber来实现,不然就得拆分写几个jUnit测试

肯定有很多误解,即使是非常基本的。因为除了“与所有利益相关者讨论”部分之外,我没有发现自己从 BDD 中获得太多价值。

我的错误在哪里?感谢您的任何建议!

【问题讨论】:

    标签: junit cucumber bdd scenarios


    【解决方案1】:
    1. 不要从登录开始;从与其他系统不同的东西开始。为什么有人登录?他们为什么要使用该服务?硬编码用户,假装他们已经登录,专注于价值。

    2. 如果您专注于 UI 细节,您就会将自己与 UI 紧密地联系在一起,这会使 UI 难以更改。相反,请查看系统提供的功能。我不建议使用登录场景,但如果我这样做了,我希望它看起来更像:

      Given Jeff isn't registered with the site
      When he registers with the username "Jeff" and password "123456"  
      Then his account creation should be confirmed  
      And he should be invited to log in for the first time.
      

      在此处查看“声明式与命令式”以了解更多信息。

    3. 如果您的 UI 确实在不断变化,请手动尝试该场景,直到 UI 稍微稳定下来。那时自动化会更容易。随着您进入更稳定的场景,最好先自动化(TDD 风格)。

    4. 你现在应该做什么?好吧,大多数人不会为 UI 编写类级别的测试,所以在你开始驱动控制器和演示器层之前不要担心它。使用相同语言的框架通常更容易,但是两个不同的框架很好。 Cucumber / RSpec、JBehave / JUnit、SpecFlow / NUnit 是非常典型的组合。做你需要的最小量来让第一个场景工作。它不会太多,因为你可以硬编码很多。第二个场景将开始引入更多有趣的行为,然后您将开始看到您的类级测试出现。

    顺便说一句,BDD 从类级别开始,所以你可以对类做同样的事情;想一个如何使用它的例子,如果你的框架还不能这样工作,在 cmets 中写下“Given, When, Then”,然后填补空白!

    1. 是的,您的 Cucumber 场景将始终为红色,直到不是。

    2. 理想情况下,您将同时进行最后一个单元测试和 Cucumber 场景,而不仅仅是编写一些额外的代码。看到它终于变绿了,真是令人欣慰。

    3. BDD 的初衷是去掉“测试”这个词,因为它使人们认为 TDD 之类的东西是关于测试的。 TDD 真的是关于简洁的设计;理解代码的职责和行为,就像场景帮助您理解系统的功能和行为一样。编写系统级场景类级测试也应该是正常的。

    不过,您已经领先于所有在开始编码之前忘记讨论场景的人!与利益相关者的对话是最重要的部分。您可能会从在这些对话中包含测试人员中获得价值。测试人员非常擅长发现其他人错过的场景。

    看起来您在处理其余流程方面几乎走在了正确的轨道上。您可能会在我的个人资料中发现其他一些 BDD 答案对您也有帮助。恭喜你,祝你好运!

    【讨论】:

      【解决方案2】:

      我认为,当您学习 BDD 的机制时,首先进行注册/登录是一件非常好的事情。几乎每个人都明白你为什么要登录系统,每个人都明白系统必须先知道你是谁,然后你才能这样做,所以你必须先注册。

      执行这个简单的任务可以让您专注于 BDD 的较小子集。通过缩小您的关注范围,您可以提高质量,同时意识到以后还有很多东西要学。

      要编写登录场景,您需要关注两件事:

      • 编写场景
      • 实施步骤定义

      这些是 BDD 的基本机制,但它们只是整个过程的一小部分。我仍然认为你会从他们的工作中受益,因为目前你没有很好地执行机制,这是可以预料的,因为你是新手。

      当您编写场景时,您应该专注于您正在做什么以及您为什么要这样做。场景不需要知道你“如何”做事的任何事情。任何与填写内容、点击内容等有关的事情都是一种气味。当您的场景只处理内容和原因时,它们会变得更加简单。

      Feature: Registration
        A pre-requistite for signing in, see sign_in.feature
      
        Scenario: Register
          Given I am a new user
          When I register
          Then I should be registered
      
      Feature: Sign in
        Dependant on registration ...
        I want to sign in so I can have personalised content and ...
      
        Scenario: Sign in
          Given I am registered 
          When I sign in
          Then I should be signed in
      

      你真的没有什么比这更能推动一个简单的登录系统的开发。一旦你开始运行,你就可以处理一些悲伤的路径,例如

      Scenario: Sign in with bad password
        Given I am registered
        When I sign in with a bad password
        Then I should not be signed in
        And I should be told ...
      

      如果你很好地实现了这些东西,那么这个悲伤的路径场景应该很容易实现,因为所有基础设施都已经准备好登录,不同的是你使用了错误的密码。

      您可以在https://github.com/diabolo/cuke_up 看到一个这样的例子。使用此示例的方法是遵循提交历史记录,并特别注意我如何使用 extract_method 重构将所有代码从步骤定义中取出。我提取的每个方法都是在编写后续场景时重复使用的工具。在实施方案时,制作一套有效的工具是提高生产力的关键。

      Nowadys sign_up 非常简单,因为我们可以依赖第三方库及其单元测试。这意味着我们可以得到很好的结果,而不必担心转换到我们自己的代码和做一些 TDD。所以现在真的没有必要考虑 TDD。

      只要您知道您只做 BDD 的一小部分,我认为您可以成功地使用这种方法为您在处理使您的系统与众不同的事物时必须处理的所有额外事物提供基础来自其他人。

      总结一下,只关注

      • 编写简单的场景
      • 让您的步骤定义更优雅
      • 创建可在您编写的下一个场景中使用的工具(提取的方法)

      你有足够的时间来学习其他东西,如果你的基本机制得到更好的发展,它会容易得多。

      【讨论】:

      • +1 用于使用易碎玩具学习 BDD 的自动化。不过,我仍然对在实际项目中使用“登录”作为场景持谨慎态度。大部分价值来自与利益相关者的合作,当他们看到您不仅按照他们的要求做,而且您可以证明它总是会做时,他们会感到惊喜。在编写场景之前,有一个步骤是您谈论场景,它比其他步骤更重要。登录有点无聊。在实际项目中使用不同且有趣的东西。但除此之外可以使用登录进行练习。
      猜你喜欢
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多