作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
测试. 它经常被留到最后一分钟, 那就停,因为没时间了, 超出预算, 或者别的什么.
管理层想知道为什么开发人员不能“一开始就做好”。, 当不同的涉众描述系统的不同部分时,开发人员(特别是在大型系统上)可能会措手不及, 喜欢的故事 盲人描述大象.
这是不可避免的, 然而, 每个项目的第一步是讨论要构建的软件或功能的行为. 客户或业务人员向开发团队中的某个人解释他们想要什么.
有时这些相互作用以an的形式出现 敏捷 用户故事. 有时它们以设计文件的形式出现,如 克里斯·福克斯的 博客条目 去年. 它们也可以在Keynote中以流程图或模型的形式出现,甚至是匆忙的电话.
仅从这些通信来看, 开发人员负责构建一个“正常工作”的系统。. 这对……尤其困难 自由职业者 在更大的系统之外工作.
这里有一个明显的差距:如果业务所有者在一开始就设想了系统的行为, 为什么要测试这些行为呢 工作 通常是被切断的那一步?
答案可能简单得令人眼花缭乱:测试通常不被视为 共享资本; they are not thought of as having value to the project, 因为“它们只是为工程师准备的”, 或类似的, 为一个部门或一群人提供价值.
我们如何让测试成为共同的资本,这个系统行为列表? 通过不仅采用测试驱动开发(TDD),而且采用行为驱动开发(BDD).
行为驱动开发应该关注代码实现的业务行为: 代码背后的“为什么”. 它支持以团队为中心(特别是跨职能)的工作流.
当开发人员和敏捷产品负责人或业务分析师坐在一起,在纯文本编辑器中编写待完成的规范(稍后由开发人员填写)时,我看到敏捷BDD工作得非常好:
在理想的情况下, 双方都可以参考当前系统行为列表,看看这个新功能是否会破坏现有功能.
我发现这个简单的行为给了我足够的约束,使我能够像开发人员一样思考:“考虑到我必须实现这些测试, 这是如何约束我/每个人的规范,我可以在代码中实现”? 由于它们是待定的规范,因此在协作的过程中编写它们既快速又容易.
这种协作方法使我能够专注于该特性为最终用户提供了什么, 有商务人士在场,我就不能谈行为了, 没有实现. 这突出了BDD与TDD的区别.
场景:你是负责公司会计系统的团队中的开发人员, 用Rails实现. 有一天,, 一位业务人员要求您实现一个提醒系统,以提醒客户未处理的发票. Because you’re practicing BDD per this tutoria; (versus TDD), 你和那个商务人士坐下来,开始定义行为.
你打开你的文本编辑器,并开始为业务用户想要的行为创建待定规范:
它“在创建发票时添加提醒日期”。
它“在提醒日期过后向发票账户的主要联系人发送电子邮件”。
它“标志着用户已经阅读了发票中的电子邮件”
在开发过程中对行为的关注使得测试在验证您正在构建正确的特性时非常有用, 不仅仅是你 代码是正确的. 请注意,措辞使用的是业务语言,而不是系统的内部实现语言. 你不会看到也不会在意发票 belongs_to
一个账户,因为除了开发团队没有人关心这个.
有些开发人员更喜欢当场编写测试用例, 调用系统中的方法, 设定期望, 像这样:
它“在创建发票时添加了一个提醒日期”
Current_invoice = create:invoice
current_invoice.reminder_date.应该== 20.天.from_now
结束
测试套件将会失败,因为我们还没有编写代码来设置 reminder_date
.
我理解编写失败规范的开发人员, 但是有那个商人在我身边, 这对我来说从来都不管用. 错误的业务人员要么会被细节分散注意力,要么会利用这些新知识,试图对开发人员更了解的事情进行微观管理 数据库设计(代码重用).
根据我的经验, 对特定行为的概述超过一行会让商务人士感到厌烦. 他们会认为这是对时间的不合理利用,或者当他们想到下一个行为时,他们会变得焦虑起来.
我们换个角度看, 使用测试驱动的开发方法, 并写出挂起的测试:
如果“after_create一个发票设置一个提醒日期为创建+ 20个工作日”
如果“帐户#primary_payment_contact返回当前付款联系人或客户项目经理”
它“InvoiceChecker#mailer发现过期的发票并发送电子邮件”
这些测试是有帮助的,但只对一群人有帮助:工程师. BDD对于与 每一个 跨职能产品团队成员.
在BDD思维模式下,您当然可以通过使用挂起行为来进行测试优先的开发. First, write the test; then run it (red); then make it 工作 (green); 然后让它正确(重构).
BDD社区做了大量工作,使测试中的断言检查读起来像英语. 下面是一个典型的RSpec测试:
a = 42
a.应该== 42
这种格式使得以后的阅读更容易. 但请记住,这不是我们在这里要做的——重点是让行为尽可能快地下降和 执行“每个规范一个测试行为”的原则. 理想情况下,待定的规范标题应该告诉您正在测试什么.
BDD isn’t about fancy ways to validate your results; it’s about sharing expected behaviors across 所有 members of the team.
让我们回到我们的场景:处理公司会计系统.
您将与业务人员一起讨论产品的功能, 通过内部分析系统(对象如何在内部组合在一起), 他们从外部分析系统.
您考虑一些条件,并询问业务分析师在以下场景中会发生什么:
*默认的提醒日期是什么时候? 离发票到期日还有多少天?
*那些是工作日还是日历日?
*如果没有与帐户关联的主要联系人会发生什么?
得到 答案. 重要的是,商务人士要明白,你并不是想要在他们喜欢的想法上打孔, 或者过于迂腐.
以这种方式, 行为驱动开发是一种帮助两个部门之间开展合作和对话的工具. 这也是一种明确所需功能范围的方法,并从开发团队获得更好的估计. Perhaps you realize 那 there’s no way to calculate 10 business 天 from a given point in time; 那’s an additional, 单独的, 需要实现的功能.
开发者会有开发者的考虑(“当你说‘day’的时候,你到底是什么意思??”), 而商务人士则有他们自己的考虑(“请不要在这里使用逾期这个词, 这意味着不同的东西。”. 让一组或另一组去尝试自己编写这些业务逻辑行为测试(承诺) 黄瓜)切断了双方宝贵的投入.
当敏捷客户不在房间时,这也是一个很好的替代品:把他们的愿望写在纸上, 混合了开发人员对所构建内容的分析(和翻译).
An 早前,Chris Fox在Toptal 博客的一篇文章中谈到了设计文件尤其是在项目开始的时候. 理解和提取业务行为从系统在一定程度上是可知的项目向下扩展, 对于那些需要几十年的程序员才能完成,并且有成百上千的行为规范的人.
克里斯的文章也提到 屏幕上的行为 的元素, 这是我经常与设计师产生分歧的地方:“这个按钮在暗淡的时候看起来像什么?, “这个在11英寸的屏幕上是什么样子?, 因为这个页面显然是为24英寸的屏幕设计的?这种与业务人员的来回交流可以发现项目图形资产或页面布局中的漏洞.
在非常大的跨职能团队中, 许多团队成员都有自己的关注点:设计师, 开发人员, 可能是行动组的人, 数据库管理员——可能是QA人员(是的,每个人在TDD和BDD中都有一席之地!),每个人都有自己的担忧和问题. BDD比测试驱动开发更能推动这种协作. 从“当数据对于这个表来说太大时会发生什么”?” to, “嗯, 这将是一个昂贵的查询, 我们希望以某种方式将其缓存到, “等, 如果用户看到 所有 那些机密信息?”, 对这个新特性有疑问的可能不仅仅是开发人员和业务分析师
我喜欢将软件工程中的“工件”视为描述项目或项目团队的潜在物理事物, 六个月后才能找到. 好的人工制品解释了为什么事物是这样的.
走廊里的谈话不是人工制品. 白板上的画也不是. 白板上的图纸变成了长长的类文档或设计文档这些 是工件. 会议记录也是工件.
工件是保存到存储库或共享空间的一些源代码, 还有票务系统里的票, 或内部wiki上的注释,甚至是持久的聊天记录.
在我看来,共享的文物是最好的文物. 它们不仅展示了 为什么 有些东西是这样的,但为什么它存在于应用程序中 在所有.
行为应该是一个共享的团队工件——测试不应该只是程序员的忙碌工作! 虽然最好有一个整个团队都可以轻松查看当前规范的系统(也许部署系统还提取并保存行为列表到站点的私有区域或wiki)。, 您也可以在每个sprint中手动执行.
游戏的名称是“帮助开发人员创建我们需要的规范,以更快地交付业务价值。, 跨部门协作, 做出更好的估计。”.
这种全公司范围内的系统理解是什么 做 也是资本的一种形式吗. 这是“为什么”,而不是代码的“如何”.
我们如何解决交付给客户的有缺陷的软件的问题? 通过确保测试不被视为“只有开发人员才关心”的事情.
描述和理解系统的需求除了代码正确之外还有很多好处:建立部门间的对话,确保所有涉众的关注点都得到满足(而不仅仅是那些有大头衔的涉众)。. 使用行为驱动开发从一开始就理解这些需求,并测试整个团队关心的外部业务行为那 是保证项目质量的好方法吗.
世界级的文章,每周发一次.
世界级的文章,每周发一次.