咨询邮箱 咨询邮箱:service@yitianxinda.com 咨询热线 咨询热线:400-668-3065 微博 微信
北京软件开发测试驱动开发_北京软件开发公司
发表日期:2016-06-13 10:13:04    文章编辑:yitianxinda    浏览次数:

  北京软件开发测试驱动开发(TDD)是一种开发方式,它改变了传统软件开发的流程,即首先设计程序,再进行编码与测试工作。TDD采取了很小的增量式开发方式:首先编写一个测试,再编写实际程序代码以通过测试,较后对代码进行改进。这种方式的结果是大量的(通常可达到几千个)自动化测试,能够在几秒钟之内执行完毕。

  测试人员需要注意到一点,这些高效的自动化单元测试剔除了大多数手工测试的执行。这样一来,我们就需要重新反思是否有必要在TDD团队中继续保留测试人员的角色。

  从表面上看,无论是否采用TDD,“测试人员”都是团队中必不可少的角色,但实际情况要复杂得多,现在让我们来看看这些复杂性体现在何处:

  如果你打算开始尝试TDD,那么建议你不要试图在团队中揉合老派的QA与功能测试人员。

  如果你已经成功地实施了TDD,那么在团队中安排一位专攻测试的成员仍然是有意义的。

  在TDD中团队中能够取得成功的测试人员与传统的功能测试人员的区别在于,前者具有更扎实的技术背景。

  QA的兴衰

  在对“TDD已死?”这一主题所展开的一次对话中,Kent Beck(KB)、Martin Fowler(MF)与David Heinemeier Hansson(DHH)围绕着QA与测试展开了激烈的讨论。他们指出了专职测试人员历史的3个发展阶段:

  堆积QA:通常指机能失调的QA部门,其中充斥着大量的功能测试人员。

  摒弃QA:对于让程序员负责测试的做法过于自信,在开发过程中摒弃测试人员。

  当前现状:在项目中引入适当的QA(甚至是功能性的)仍是有必要的。

  流行于上世纪90年代的堆积QA的做法现在看来似乎已经过时了,许多IT组织已经解散了他们的QA部门,并将测试人员分派到各个敏捷团队中。不过,在许多敏捷团队中,这些测试人员仍在继续着早期的手工测试任务。众多组织仍然受困于延续自20年前的机能失调的测试方法。

  老派的QA方式之所以出现机能失调的情况,是因为这种方式依赖于大量的功能测试人员。这些测试人员是手工测试方面的专家,但对于技术方面的技能知之甚少。测试人员的专业性决定了他们擅长于对功能的“测试”。但是,老派的QA部门更倾向于(同时也出于商业利益的考虑)让这些测试人员对功能进行“检查”。

  “检查”的主要特点在于:这种测试完全可以实现自动化(Bach 与Bolton 2013)。这就意味着“检查”功能可以由程序员完成。至于是应该让测试人员还是程序员进行功能“检查”,这种选择貌似随意,其实不然:无论是发现bug、进行隔离、汇报、跟踪或是提出修复意见,测试人员都要花费更多的时间(Kaner 2001)。

  通过手工测试人员对功能进行“检查”的方式让老派的QA变得非常低效。一旦团队培养出“不要测试自己的代码,把它丢给QA去做”这种观念,测试工作就变得机能失调了(KB与DHH在这次对话中的观点)。这种方式发展到一定程度,就会造成效率的不断下降,随着投入的测试人员越多,反而会造成bug数量的不断升高。('Better Testing - Worse Quality',Hendrickson 2001)

  摒弃QA是对于手工测试这种机能失调的实践的一种自然反应。之所以本文的标题没有取名为“敏捷团队中的测试人员”,是因为摒弃QA的做法在某些情况下并不可行,比如你的敏捷团队虽然实施了Scrum框架,却没有进行任何自动化单元测试,又或是团队正在进行某些商业现成品或技术(COTS)的软件开发。如果团队中没有设立功能测试人员,则必须实施TDD实践,或是其他任何一种能够生成自动化单元测试的方法。

  在大多数情形下,选择了TDD就意味着你必须改变程序员的技能、习惯,并且往往还需要改变他们的态度与自我意识。而实现以上这几点并不容易,同时TDD本身也并非可以一促而就的:“要很好地掌握遗留代码、对单元测试进行适当的隔离、以及集成测试是非常困难的”(Shore 2007)。根据评估,当程序员转为采用TDD实践后,前几个月的生产力会急剧下降。不仅如此,对实践TDD的新手往往要进行几周乃至几个月时间进行手把手的培训(Larman,Vodde 2008)。

  依我的经验看来,老派的程序员与测试人员之间往往存在着一种共生现象。老派的程序员不喜欢进行单元测试,只要项目中有测试人员,他们就企图蒙混过关。而老派的测试人员也不愿意学习技术知识,只要为程序员找到了足够的bug,他们也同样选择应付了事。老派的程序员与测试人员都希望避免进行任何改变。因此,在我看来,如果程序员已经开始实施TDD实践,再往团队中安置一个功能测试人员就是一个坏主意。

  我在多年的经验中观察到了这种反模式:如果你打算采用TDD或其他某种由开发者进行测试的实践,那么仅仅是因为在团队中出现了一位功能测试人员,就会让你的努力付诸东流。因此,如果你确实计划实施TDD,我的建议是从团队中取消功能测试人员的角色!

  但事实上,在实施TDD的过程中,在团队中保留一定的QA仍然是必要的,这是因为某些变化或许会出乎你的意料。在上述关于TDD与QA的对话中,David Heinemeier Hansson说道:“或许你已经通过了所有测试,但或许它并没有发现真正的问题。一旦到了实际应用过程中,用户会以你始料未及的方式使用你的应用。”

  Martin Fowler十分赞同David的观点,但在同一番对话中,Kent Beck的措词显得更为谨慎。但他也同意,在QA这方面,“事情的发展已经趋向于另一个极端”。如果你无法预见到所有的可能性,那么从外部获取某些反馈的做法“非常有意义”。

  TDD团队中的测试与团队组成

  在以上对话的较后,我们已意识到在TDD的实施中,除了在编程过程中所创建的测试外,进行一定其他形式的测试工作仍是有意义的。敏捷测试的概念在“敏捷测试”(Crispin,Gregory 2009)等书籍中进行了详尽的描述。但实施敏捷测试是否仍然需要“测试人员”,即专业从事测试的员工,人们对于这一点似乎还有争论。Google仍然有数百名测试人员,而Facebook几乎完全没有设立测试人员的职位。

  而普通的公司则有着不同的考虑,他们必须保证员工已掌握了工具与概念方面的知识以开发并维护各种应用,并确保高效的分工。让我们实际分析一下在Java环境中引入测试人员意味着什么。

  支持Java的TDD工具包括JUnit与某种模拟测试框架,一般的开发者都能够掌握这些工具。不过,JUnit框架不仅支持在Java环境中应用TDD,它还表现出了测试工作的第二次革新:它不仅支持自动化单元测试,还支持其他各种测试的自动化。

  JUnit目前还支持运行:通过JAX-RS实现的集成测试、自动验收测试、基于Selenium Webdriver的UI测试、以及支持各种数据集的参数化测试等等。并且这些测试都能够与持续集成(CI)方案进行整合。

  除了这些测试工具之外,其他各种工具与框架也大量涌现。可以说,一般的开发者很难掌握在一个普通的现代化项目中所用到的全部工具。

  概念性的知识是创建高质量应用的基本。要实现高可维护性,开发者需要了解代码整洁之道,而要掌握这方面知识需要多年的经验积累。如果我们想要精通这一领域的知识,接下来还可以学习设计模式、线程以及性能的原理。

  准确的、可维护的以及高性能的代码虽然十分重要,但他们并不能保证某个应用是可信赖的。为了弥补这方面的缺失,开发者还需要学习安全方面的知识。而为了创建一个能够吸引用户的应用,开发者还要了解UX方面的知识。较后,为了设计一种高效的方式以保证以上所说的特性,开发者还需要熟悉测试的知识。

  在组建IT部门时,工作的分工是又一项要考虑的重点。在团队的专业构成中,我们可以选择由各领域的专家,例如由一位安全方面的专家、一位UX设计师和一位测试人员组成一个团队,但这样一来就没有编码者的位置了,结果就是团队无法产出任何实际的东西。

  反过来,我们也可以由多面手构成整个团队,但这意味着整个团队必须将较好的光阴花费在学习上,除非他们都是天才。这样的团队同样不会有很高的产出。

  因此,我们的结论是在开发团队中有必要引入部分专利性。我们不能指望每个开发者不仅能够掌握全部的工具,并且还是整洁代码、UX以及安全和测试方面的专家。另一方面,在团队中引入的专家数量也应有所限制。

  既然我们必须引入一定的专业性,那么设置一位测试专家是比较有意义的:对于开发者来说,如果让他们来选择,那么大多数人不会去探索单元测试之外的内容,甚至有很多人根本不愿意承担任何测试工作。这也是为什么许多开发者不喜欢、甚至是厌恶测试的原因。如果要在这种环境中尝试转变为敏捷测试实践,那么就需要设立一位对于测试工作有热情并乐于实现它的专家。

  与TDD的实施类似,以上过程同样需要他人的指导,并且向团队展示其工作结果。如果某位测试专家创建了对某个服务的测试集,并且能够从IDE中执行,那么程序员就很可能会去使用。不仅如此,如果开发者感受到了测试的实用性,那么他们就会开始扩展其功能,并以可维护的方式实现。一旦为测试所触动之后,程序员就会愿意继续进行测试。但以我的经验来看,仅靠程序员自己是无法感受到测试的好处的。

  TDD:具有扎实技术背景的测试人员

  在QA的兴衰这一节的总结部分,我曾表示:在实现了对手工检查工作进行自动化的TDD环境中,对于缺乏技术知识的传统测试人员的需求已经大大降低了。随后在对JUnit与TDD的介绍中,我们又看到开发者创建了大量的测试工具,而缺乏技术知识的测试人员将无法使用这些工具。

  我们现在可以负责任的说,在TDD环境中,我们需要一种新型的测试人员,他们需要具备更扎实的技术背景。至于他的日常活动包括哪些内容,要考虑到TDD所实施的环境。对于敏捷测试来说,TDD实现了自动化金字塔(Cohn 2009)的底层,以及测试象限(testing quadrants)的第1象限(Marick 2003及Crispin 2009)。

  为了更清楚地了解其效果,让我们来考虑这个测试场景:某个表单的一个输入框可以接受一个整数,该数字必须在规定的边界之内,并且要进行后端的校验。我们在此处可以建立16种功能性的测试用例:{ x | boundary,boundary-1,boundary+1,decimal, locale,Z,0,null,“”,“ “,abc,UTF-8,2^31-1,2^31, -2^31,-2^31-1},但这些基本的单元测试只属于测试象限中的第1象限(通过面向技术的测试指导开发)。

  而在TDD实践中,以上测试用例将实现自动化,测试人员不应(参照上文)执行这些测试用例。一般来说,他应当对于该输入字段是否存在以及一个正面用例进行校验(测试象限2,通过面向业务的测试指导开发)。虽然可以通过某种录制与播放工具完成该任务,但这种方案缺乏可维护性。更有效的技术方案是(通过整洁的代码)编写Selenium Webdriver代码,并且让它能够在整个团队共用的IDE中执行。

  象限2中的其他测试技术包括用户故事的测试,而这些测试同样可以实现自动化。“作为InfoQ的用户,我希望能够登录系统,以下载某些特别的内容”这样的行为可以暴露为REST调用等方式,并通过自动化测试执行。对于在GUI层进行的这种简单测试,有人可能会选择使用外部工具(例如SoapUi)。但更高效的做法是让这个测试能够在JUnit中作为集成测试(“LogInIT.java”)而运行。而其他(没有许可证的)团队成员可以直接运行与维护该测试,并且无需学习该工具的使用。

  当基本功能都实现了自动化检查后,我们就达到了第3象限(通过面向业务的测试来评价产品):团队已具备了开始进行探索性测试的先决条件。David Heinemeier Hansson在上述对话表示,用户会以你始料未及的方式使用你的应用。这一点对于其他系统也成立,此时这种方式叫做突现行为(emergent behavior)。由于你不知道应该期望怎样的行为,因此此处可引入探索性测试(Hendrickson 2013)。

  探索性测试(ET)依赖于小型的迭代:执行测试、对应用进行学习并为此设计新的测试。这种测试方式较初是受到Test Heuristics Cheat sheet((Hendrickson 2006))这份非常容易获取的资料而启发的,但并不是说只需简单地执行其中的内容就代表你已经实现了探索性测试。探索性测试的真正价值在于它的迭代式特征以及对于知识的运用。

  举例来说:在Heuristics Cheat Sheet中提到,在web测试中可以“对url进行各种操作,(例如变更或删除某些参数)”。如果在没有准备的情况下直接尝试编写相关的脚本或直接执行是没有实用性的。如果要改善这方面的行为,我们可以首先用几个迭代的时间去学习该应用使用这些参数的方式,随后想出(设计)一个相关的测试,较后才开始测试(执行)。毫无疑问,如果能够正确地运用http协议方面的知识,对于该测试的设计将带来极大的便利。

  我在探索性测试中的常用做法是:在IDE中运行应用程序、对应用程序服务器的日志进行监控、打开数据库并对网络请求进行监控。这种方式显然能够看到一些在GUI中不会显示出来的错误。通过这种方式,我通常能够发现这些内容:大量的网络错误与请求、日志污染、非预期的持久行为、大量的/低效的数据库查询、安全性隐患以及使用性的错误等等。

  这并不是说一旦应用了TDD,所有的测试工作就会变得充满技术性,或是由工具所驱动。依然有一些非常重要的测试与人相关(Ambler 2003-2014),或是与UX的测试相关。这些测试所包含的技术性较少,但并不意味着就不需要了解深入的知识。

  以上内容表示,TDD让测试人员的角色发生了变化,而不再需要进行手工功能性测试(例如检查)。虽然他仍有大量的工作需要完成,但他所负责的功能性测试应该已经实现了自动化。而如果他能够掌握更多的技术、工具或其他方面的知识,那么他的手工(探索性)测试工作很可能会变得更为高效,只是这些知识往往并不容易掌握。

  那么,TDD团队中的测试人员究竟应当掌握哪些技术方面的知识呢?以下陈述基本是没什么疑问的:敏捷测试人员需要掌握良好的技术知识,了解如何与他人合作进行自动化测试,而成为经验丰富的探索性测试人员(Crispin, Gregory 2009)对于TDD团队来说同样有意义。

  但我却相信,对于已开始实践TDD的敏捷团队与尚未开始实践TDD的敏捷团队来说,他们对于职务的需求也是不同的。对于尚未开始TDD的团队来说,敏捷测试人员也许将被迫使用某些不为开发人员所用的测试工作,或是进行大量的手工测试。而在TDD团队中,测试人员更有可能在IDE中进行工作,这时,该角色的技术需求就变为:

  掌握至少一门编程语言(从而能够阅读及编写测试)。

  了解命令行与脚本编写的知识(包括服务器与本地机器)。

  具备数据库方面的经验(用于在没有GUI的情况下检查持久化的情况)。

  结语

  本文引用了Kent Beck、Martin Fowler和David Heinemeier Hansson的对话,这也是激励我撰写本文的动力。如果你对于测试有兴趣,应该听一听他们对于“将代码扔给QA”以及“老派的QA做法还不如不要QA”等观点坦率而直接的表述。

  为了对此问题进行透彻的分析,我首先描述了老派的功能性测试方法,它所造成的结果不经过思考的功能检查,这种方式带来的伤害更大于它的价值。这并非我的臆想,而是有强烈的迹象表明仍有许多组织以这种方式进行测试,无论他们是否采用了“敏捷”实践。

  接下来,我指出了为什么将TDD开发者与“老派的功能测试人员”结合在一起是一种不推荐的方式。在团队组成那一部分,我对于在TDD团队中设置测试人员的角色持保留态度,并将其修正为在团队中应当设立一些对于测试充满热情的成员。

  至于测试人员所需的技能,我认为在TDD过程中已不需要进行老派的功能性检查。在TDD团队中仍然有测试人员的一席之地,但他们的测试工作需要更专业的技术知识。

  收获

  如果你是一位仍在进行手工检查的测试人员,那么应当考虑TDD或其他能够将手工检查自动化的解决方案。如果你还不具备上文所提到的技术知识,那么是时候将你的知识水平提升至这一程度,从测试工作中获得更大的乐趣!《More Agile Testing》(Crispin Gregory 2015)一书对于应当具备的知识进行了详尽的介绍,我极力推荐这本书给那些希望继续从事测试工作的读者们。为了掌握这些知识,我建议大家进行正规的学习,它会让你更好地了解某个主题,并且加快学习的速度,同时也使你有机会证明自己已具备了这些知识。

  如果你是一位团队主管或经理,并且对于测试方面的问题感到受挫,那么你或许应当考虑一下如何实现更高级的测试方案。你需要的是在团队中找到能够实现方案,同时又对测试充满热情的人。在“程序员即测试人员?”(Programmers as Testers?)这篇文章(Gregory 2011)中,Janet Gregory表示她倾向于测试人员应当具备技术背景的观点,但如果他们将测试人员的角色仅仅当作成为程序员的一块垫脚石,那么就不要以测试人员的身份招聘他们。这一点无可厚非,如果测试人员对于测试工作没有热情,他们就无法很好地实现测试象限或探索性测试。反过来说,如果某个测试人员不具备必需的技能,他就无法实现测试自动化,甚至在探索性测试中也做不到完全高效。换句话说,技能与热情是实施敏捷测试的必要条件。

相关文章推荐
通过与北京软件公司​合作,企业可以获得所需的熟练开发人员,以加速创新和发展。北京软件公司 可以通过提供成熟的开发人员和定制解决方案来帮助企业弥补开发人员短缺的差距并实现业务增长。...
企业级软件或应用程序已经发展到几乎所有组织和企业都依赖它来保持市场竞争力的程度。无论您是需要跟踪捐赠者的非营利组织还是寻求更好的库存管理的汽车经销商,都没关系。移动企业应用程序为公司提供了前所未有的灵活性和功能。...
优秀的软件开发技术设施和具有丰富开发知识的高水平专家似乎对于软件开发项目的成功至关重要。...
对于软件开发公司来说几乎每个新程序代码都有错误,在最坏的情况下,这些错误可能会危及安全性...
北京软件开发公司对软件错误检测的研究促使软件开发工程师开发了一种方法——它就像两个说自己语言的朋友一样——来加强对电子邮件和社交媒体消息等数字内容的保护。...
工业控制系统 (ICS) 解决方案需要新的架构,并且需要更适应不断变化的环境的理念。重点介绍了六种方法: 学习目标 工业 4.0 时代的工业控制解决方案需要新的架构和理念。 由于工业...