c#发展

首页 » 常识 » 预防 » 首席架构师看敏捷核心实践测试驱动开发
TUhjnbcbe - 2024/6/6 18:22:00

测试驱动开发(TDD)(Beck;,是一种渐进的开发方法,它结合了测试优先的开发,即在编写足够的产品代码以完成测试和重构之前编写测试。TDD的主要目标是什么?一个观点是TDD的目标是规范而不是验证(Martin,Newkirk,和Kess)。换句话说,这是在编写功能代码之前考虑需求或设计的一种方法(这意味着TDD是一种重要的敏捷需求和敏捷设计技术)。另一种观点认为TDD是一种编程技术。正如RonJeffries喜欢说的,TDD的目标是编写有效的干净代码。我认为这两种观点都是有价值的,尽管我倾向于规范的观点,但是我把它留给您来决定。

表的内容

TDD是什么?TDD和传统测试TDD和文档测试驱动的数据库开发通过敏捷模型驱动开发(AMDD)扩展TDD为什么TDD?神话和误解到底是谁在做这件事?总结工具1.TDD是什么?

图1的UML活动图中概述了测试优先开发(testfirstdevelopment,TFD)的步骤。第一步是快速添加一个测试,基本上只需要足够的代码就可以失败。接下来运行您的测试,通常是完整的测试套件,尽管出于速度的考虑,您可能决定只运行一个子集,以确保新测试确实失败。然后更新函数代码,使其通过新的测试。第四步是再次运行测试。如果它们失败了,您需要更新您的功能代码并重新测试。一旦测试通过,下一步就是重新开始(您可能首先需要根据需要重构设计中的任何重复,将TFD转换为TDD)。

图1所示。测试优先开发(TFD)的步骤。

我喜欢用这个简单的公式来描述TDD:

TDD=重构+TFD。

TDD彻底改变了传统开发。当您第一次实现一个新特性时,您要问的第一个问题是,现有的设计是否是使您能够实现该功能的最佳设计。如果是,则通过TFD方法进行。如果没有,则在本地重构它,以更改受新特性影响的设计部分,使您能够尽可能轻松地添加该特性。因此,您将始终提高您的设计质量,从而使它更容易在未来的工作。

与其先编写函数代码,然后再编写测试代码,如果您真的编写了测试代码,那么您应该在编写函数代码之前编写测试代码。此外,您可以通过非常小的步骤来完成—一次测试和少量对应的函数代码。采用TDD方法的程序员拒绝编写新函数,直到第一个测试失败,因为该函数不存在。事实上,在对代码进行测试之前,他们甚至拒绝添加任何一行代码。一旦测试就绪,他们就会执行确保测试套件现在通过所需的工作(您的新代码可能会破坏几个现有的测试以及新的测试)。这在原则上听起来很简单,但是当您第一次学习使用TDD方法时,它需要严格的规程,因为不首先编写新的测试,很容易“滑倒”并编写功能代码。结对编程的一个优点是,结对可以帮助您保持在正确的轨道上。

TDDSpecificationbyexample有两个级别的TDD:

验收测试驱动开发(ATDD)。使用ATDD,您可以编写一个验收测试,或者根据您喜欢的术语编写行为规范,然后编写足够的产品功能/代码来完成该测试。ATDD的目标是在准时(JIT)的基础上为您的解决方案指定详细的、可执行的需求。ATDD也被称为行为驱动开发(BDD)。开发人员TDD。使用开发人员TDD,您可以编写单个开发人员测试,有时不准确地称为单元测试,然后编写足够的生产代码来完成该测试。开发人员TDD的目标是在JIT的基础上为您的解决方案指定一个详细的、可执行的设计。开发人员TDD通常简单地称为TDD。图2描述了一个UML活动图,展示了ATDD和开发人员TDD是如何结合在一起的。理想情况下,您将编写一个验收测试,然后使用开发人员TDD方法实现实现该测试所需的生产代码。这反过来要求您迭代多次,通过编写测试、编写生产代码,使其在开发人员TDD级别上工作。

图2。验收TDD和开发人员TDD如何协同工作。

请注意,图2假设您同时做这两件事,尽管可以不做任何一件事。事实上,有些团队会在不使用ATDD的情况下使用开发人员TDD,请参阅下面的调查结果,尽管如果您正在使用ATDD,那么几乎可以肯定您也在使用开发人员TDD。挑战在于,这两种形式的TDD都要求从业者具有技术测试技能,而许多需求专家通常没有这些技能(这也是为什么泛化专家比专家更可取的另一个原因)。

TDD的一个基本假设是您有一个可用的测试框架。对于可接受的TDD,人们将使用Fitnesse或RSpec等工具,对于开发人员TDD,敏捷软件开发人员通常使用xUnit系列的开源工具,如JUnit或VBUnit,尽管商业工具也是可行的选择。没有这些工具,TDD实际上是不可能的。图3展示了一个UML状态图,展示了人们通常如何使用这些工具。这个图表是KeithRay向我提出的。

图3。通过xUnit框架进行测试。

kentBeck在eXtremeProgramming(XP)(Beck)中推广了TDD,他为TDD定义了两个简单的规则(Beck)。首先,只有在自动化测试失败时,才应该编写新的业务代码。其次,您应该消除发现的任何重复。Beck解释了这两条简单的规则是如何产生复杂的个人和群体行为的:

您的开发是有机的,运行中的代码在决策之间提供反馈。您编写自己的测试,因为您不能每天等待20次别人为您编写测试。您的开发环境必须对小的变化提供快速的响应(e。你需要一个快速的编译器和回归测试套件)。您的设计必须由高度内聚、松散耦合的组件(例如,您的设计高度规范化)组成,以使测试更容易(这也使系统的演化和维护更容易)。对于开发人员来说,这意味着他们需要学习如何编写有效的单元测试。Beck的经验是好的单元测试:

跑得快(他们有短的设置,运行时间和故障)。单独运行(应该能够重新排序)。使用易于阅读和理解的数据。在需要时使用真实数据(例如生产数据的副本)。代表向你的总体目标迈出的一步。2.TDD和传统测试

精益敏捷atddtdd主要是一种规范技术,它的副作用是确保您的源代码在验证级别得到彻底的测试。然而,还有比这更多的测试。特别是在规模上,您仍然需要考虑其他敏捷测试技术,如生产前集成测试和调查性测试。如果您选择这样做(您应该这样做),那么大部分测试也可以在项目的早期完成。

使用传统的测试,成功的测试会发现一个或多个缺陷。TDD也是如此;当测试失败时,您已经取得了进展,因为您现在知道需要解决问题。更重要的是,当测试不再失败时,您可以清楚地度量成功。TDD增加了您的信心,您的系统实际上满足为它定义的需求,您的系统实际上工作,因此您可以满怀信心地继续。

与传统测试一样,系统的风险概要越大,您的测试就需要越全面。对于传统的测试和TDD,您并不追求完美,而是测试系统的重要性。套用敏捷建模(AgileModeling,AM)的说法,您应该“有目的地进行测试”,并且知道您为什么要进行测试,以及需要测试到什么级别。TDD的一个有趣的副作用是,您可以实现%的覆盖率测试—每一行代码都经过测试—这是传统测试无法保证的(尽管它推荐这样做)。总的来说,我认为可以相当肯定地说,尽管TDD是一种规范技术,但是它有一个有价值的副作用,那就是它比传统技术的代码测试结果要好得多。

如果值得构建,就值得测试。如果不值得测试,为什么要浪费时间在上面呢?

3.TDD和文档

不管喜欢与否,大多数程序员都不阅读系统的书面文档,相反,他们更喜欢使用代码。这没什么不对的。当试图理解一个类或操作时,大多数程序员首先会寻找已经调用它的示例代码。编写良好的单元测试正是这样做的——提供功能代码的工作规范——因此单元测试有效地成为技术文档的重要部分。这意味着支持文档的人群的期望需要反映这一现实。类似地,验收测试可以成为需求文档的重要部分。当你停下来思考的时候,这是很有意义的。您的验收测试准确地定义了涉众对您的系统的期望,因此它们指定了您的关键需求。您的回归测试套件,特别是使用测试优先的方法,有效地成为详细的可执行规范。

测试是否有足够的文档?很可能不会,但它们确实构成了其中重要的一部分。例如,您可能会发现仍然需要用户、系统概述、操作和支持文档。您甚至可能发现,您需要摘要文档来查看系统支持的业务流程。当您以开放的心态处理文档时,我怀疑您会发现这两种类型的测试涵盖了开发人员和业务涉众对文档的大部分需求。此外,它们是AM的单一源信息实践的一个很好的例子,也是您在文档方面保持尽可能敏捷的整体努力的一个重要部分。

4.测试驱动的数据库开发

在撰写本文时,敏捷社区中提出的一个重要问题是“TDD可以用于面向数据的开发吗?”“当您查看图1中描述的流程时,需要注意的是没有一个步骤指定对象编程语言,比如Java或c#,即使这些是通常使用TDD的环境。为什么不能在更改数据库模式之前编写测试?为什么不能根据需要进行更改、运行测试和重构模式呢?在我看来,你只需要选择这样做。

我的猜测是,在短期内,数据库TDD,或者测试驱动数据库设计(TDDD),将不会像应用程序TDD那样工作得那么顺利。第一个挑战是工具支持。尽管诸如DBUnit之类的单元测试工具现在已经可用,但在撰写本文时,它们仍然是一种新兴的技术。一些dba正在改进他们所做的测试的质量,但是我还没有看到任何人采用TDD方法进行数据库开发。一个挑战是单元测试工具在数据社区中仍然没有被很好地接受,尽管这正在发生变化,所以我的预期是在未来几年数据库TDD将会增长。其次,对许多数据专业人员来说,演进开发的概念是新的,因此采用TDD方法的动机尚未形成。这个问题影响了数据专业人员可用的工具的性质——因为在传统的数据社区中,串行思维仍然占主导地位,大多数工具不支持渐进开发。我希望工具供应商能够跟上这种范式的转变,但是我的期望是我们需要开发开源工具。第三,我的经验是,大多数从事数据导向工作的人似乎更喜欢模型驱动的方法,而不是测试驱动的方法。其中一个原因可能是因为测试驱动方法直到现在才被广泛考虑,另一个原因可能是许多数据专业人员可能是视觉思考者,因此更喜欢模型驱动方法。

5.通过敏捷模型驱动开发(AMDD)扩展TDD

TDD非常擅长于详细的规范和验证,但不擅长考虑更大的问题,比如总体设计、人们将如何使用系统或UI设计(例如)。建模,或者更接近于敏捷模型驱动开发(AMDD)(图4中捕捉到的生命周期)更适合于此。AMDD解决了TDD没有解决的敏捷扩展问题。

图4。敏捷模型驱动开发(AMDD)生命周期。

比较TDD和AMDD:

TDD缩短了编程反馈循环,AMDD缩短了建模反馈循环。TDD提供了详细的规范(测试),而AMDD更适合考虑更大的问题。TDD促进高质量代码的开发,而AMDD促进与涉众和其他开发人员的高质量通信。TDD提供了软件工作的具体证据,而AMDD支持您的团队(包括涉众)朝着共同的理解努力。TDD与程序员“交谈”,而AMDD与业务分析师、涉众和数据专业人员交谈。TDD提供了非常细粒度的关于分钟顺序的具体反馈,而AMDD支持关于分钟顺序的口头反馈(具体的反馈要求开发人员按照实践用代码证明它,因此依赖于非am技术)。通过

1
查看完整版本: 首席架构师看敏捷核心实践测试驱动开发