【IT168 技术文章】
来自于 Rational Edge:包含良好自动化测试实践的基础结构可以是一个幸事,也可以是一个祸根。这篇文章描述了这样一种场景,它避免了测试小组随着时间的推移,产生出不断蔓延的测试基础结构。
这是我在项目中的第一天,我把每周一次的关于自动化测试的讨论作为文章的开始。我发现即使精通多种操作系统,数据库,程序语言,并且阅读过很多产品特性的资料,但我依然很难明白所讨论的内容。而且似乎参加会议的每个人都在谈论着某种程序语言,而这种语言对我来说却是陌生的。人们不断地谈到"enabler routines"和API方法,而这些API方法在我所读过的API文档中从未见到过。
我花了些工夫才意识到,人们在探讨测试框架中的惯例和方法,而不是测试中的产品。在过去的几年里,测试框架已包括了许多的惯例,这些惯例封装了实际产品的API方法。
现今这种方法的确有很多优点。它减少了冗余测试代码,能够强制使用标准的机制执行任务,并且可以跟踪API方法的返回值。随着它不断的发展,这种特殊的框架结构已经变的如此广泛以至于它自身已变成一种程序语言。创建整套完整用户文档和处理定期框架更新版本的小组成员推荐这种方法。
但是还是有不足之处的。由于测试框架是如此的广泛,而且许多自动化的测试都基于这个框架,使得维护框架结构和测试变的十分昂贵。为了保持与测试产品的新版本的同步,框架不断被更新,这不仅使得任务变的越来越大,而且使得像我这样的新成员不得不花费更多时间学习测试框架。
当我第一次参加会议时,我震惊于人们对于测试框架学习的花费。他们能够用同样的方法讨论各种"enabler routines"的程序,就像我讨论JDBC的使用或者在Java中使用一个数组或矢量的优缺点一样。
诚实地讲,会议有点胁迫的感觉。这有点像身处在外国,而你却不会讲他们的语言一样。但是我最担心的是:对我来说似乎提供自动化测试程序框架的过程,能够使工作变得容易并且有效率,但是我们增加了如此复杂的抽象层,使得人们更少的接触到所测试的产品。或许我有点夸大其词了,但这确确实实是我的感受。
Infrastructure-itis
我突然记起几年前的相似经历。当时我正创建软件质量评价小组来检测Internet防火墙。我们需要一种方法来检测某些命令行工具,并且决定在Expect中写测试脚本。开始的两天进行的很顺利,直到Al(不是他的真名)称他"改进"了Expect。并把他的创造叫做"RunExpect"。你可以想象,它是一串在Expect中写的封装好的函数。我感谢他,但是我谢绝成为第二个,最终也是最后一个加入RunExpect用户社区的人。我选择使用Expect并且创建我们所需要的并且可随时使用的惯例。
因此,这里发生了什么?这是经常出现在软件质量保证团队中的情况:infrastructure-itis。
什么是infrastructure-itis?这是一个适应坏状况的很好的主意。这个好主意用来创建(或调整)软件工具使得测试更加自动化且更有效率。坏状况就是这些工件的维护变得过于沉重。
如何开发一个infrastructure-itis实例?
它可以从一个小范围开始。我们可以向他们说,你们正在测试一个数据库应用程序。你的自动化测试将需要通过一些注册或者使用者身份验证的形式访问数据库。你可以在每一个测试程序中通过复制代码来为注册用户编号,或者你可以使它成为一个单一的,可调用的例行程序。这是一个好方法。这个例行程序为你的测试程序提供了访问数据库的路径,但它同时使测试程序设计员无法处理注册程序的准确语义。相反,他们处理可调用例行程序提供的抽象注册界面。最终,你将创建越来越多的可调用的例行程序来支持测试。
问题是,这些例行程序的创建可以成为它之中和它本身的一个结束,在极端情况下,实际也可以分散你对手边实际工作的注意力——指的是自动化测试的创建和执行。但它是恶性的循环。你创建一个有用的例行程序,然后再一个,接着又一个,很快所有你所做的工作就是创建,重分解和改进测试的基础结构。它能使人成瘾。做软件工作的众多乐趣之一就是你可以随意设计,创建,然后再设计,再创建。它把软件的自然特性当作一种媒介。如果你用钢或花岗岩来工作,重新设计或增加一些东西是很贵的。然而,在软件工作中,你可以通过按压键盘来完成工作。(是的,有很多键,但改变软件仍然要比建一座吊桥容易。)
避免恶性循环
你将如何避免影响?警示符号是什么?技巧在于,在你陷入恶性循环之前控制住你自己。在你实际已经离开很远的时候很难意识到你离开太远了。一个很老的Buggs Bunny卡通片说明了这一点。Buggs感到沮丧是因为对于兔子的慷慨比更具破坏性的动物少得多。他决定要通过跨越南北美洲来迂回前进破坏出一条路以便表示慷慨。他的慷慨是1百万美元。后来他发现他正被整个陆军和海军搜寻。正当炮弹在他周围降落,他悔恨,"可能我离开得有一些远了。"
你可以避免这种命运。这里是三种你需要注意的情况:
人们把他们的精力倾注在基础结构,而不是测试上面
正如我们早先所讨论的,做软件工作的乐趣之一就是如果你的想象力无限,你将可以创建出任何复杂的系统。成为软件测试工程师的人们,当他们通常是以破坏东西来拿薪水的时候,对这个警报器的声音是没有免疫力的,并且经常将他们的创造精力倾注在建立复杂的测试基础结构上。(有几分像想当导演的演员。)这将自动成为一个问题吗?不,但当工程师们对于基础结构的情感因素,使他们对它的真实效用和限制失去判断力时,它可能会成为一个问题。
测试工程师们可能将他们的基础结构,看作所有问题的理想解决方法,但是在某些情况下,它甚至根本就不是一个解决方法。(记住一句古老的说法"当你所拥有的全部就是一把锤子时,任何东西看起来都像一个钉子")。更糟糕的是,他们对于基础结构的巨大投入以及不断地追加,会阻止他们看到他们的基础结构该到停止使用或至少需要重新架构的时候了。他们可能没有记住,他们的基础结构曾经也是新的,并且取代了其它一些工具。
讽刺的是这个竟然发生在软件测试工程师的身上,因为软件测试的基本原则之一就是测试团队必须独立于软件开发组织,为的是使测试团队保持客观性。一个简单的事实是:你很难客观和严格地对待自己的工作。
基础结构的维护费用在不断增长
你是否留意过城市和乡镇是怎样建设新公园的,但只是几年之后,它们便因为失修变得破烂了?城市看起来总是找到一条筹集资金的路来建公园,并且有时以需要正面新闻的人的名字来命名,但他们通常没有资金来维护它们。
维护:那是软件开发的成本,包括软件测试基础结构开发,这一点每个人都忘了去记住。是什么使一个软件测试基础结构的维护成本的增长超出控制?通常的情况是一个软件程序开始时很小,并且被设计成服务于一个特殊的需要。接着它变成了它自己的一个牺牲品,并被扩展来执行更多的任务。然而,它的基础体系结构并没有被修改,以便来处理这种增长。随着时间的过去,越来越多的用户可见的特性被增加,并且每一个新变化都会导致出现问题;当缺乏一个基础结构时,这些问题可能十分严重,它允许使一个程序变成一个单一的巨大的实体,而不是一个由组件支持的核心。结果,越来越多的人需要修改软件,并测试它,以便保证每一个修改不会使程序变得不稳定。
投入在基础结构的时间和精力是无关紧要的;它总是缺乏一个你执行当前任务所需要的功能或特性。为什么会出现这种情况呢?可能是因为基础结构尝试成为所有人的一切基础,并且它的维护人员总是尝试扩展它的原始基础结构来符合新的测试要求。
简单代码和智能数据的开源社区模型通常被认为是设计和创建一个程序的一个非常有效的方法。一个经常扩展的,单片的程序与这个模型正好相反,它可能是维护人员的一个梦魇。
使用测试基础结构,高维护成本的一个征兆是建立一支"工具团队"来维护基础结构。这个工具团队是独立于软件测试团队的,而软件测试团队是工具的实际使用者。我已经在多元化公司见到了这个模型,但我一直没有看见它们很好地工作。测试团队和工具团队不可避免地要在工具的成本和时间消耗上产生分歧。为什么?就是因为创建工具的人不用工具完成他们的工作。我认为一个模型在所有,或至少是许多创建和维护测试工具的软件测试工程师那儿,会工作得更好。这个模型可以追随开源社区模型,在开源社区模型中工具使用者(或是"消费者")可以直接对工具的创建和维护作出贡献。
基础结构变得如此繁重以至于人们都避免使用它
这有一个说法——列宁所说——在陷入困境时,人们"用他们的脚投票" 。换句话说,当情况变得艰苦,大多数人就会去别的地方。当软件使用的工具没有用或使用起来很麻烦时,他们就会寻找其它的工具或创建他们自己的工具。当一个测试基础结构扩展变得如此复杂,以至于它成为使用的一个负担时,人们可能就会创建基础结构的一个更简单的版本,或者干脆不去使用它。否则他们可能人为地限制他们对基础结构的使用。几年前我看见过这种人为限制使用的一个实例。问题中的基础结构是一个测试结果跟踪系统。系统开始时就是一个带有GUI前端界面的简单数据库,但经过多年的使用,它发展成为一个非常复杂的,很难使用的系统。系统是高度劳动密集的:需要大量的手工干预以使得 1)按照一种可以使用的形式使信息进入系统和 2)从系统中生成进度报告。结果,一些工程师就直接拒绝使用它,一些整体团队构建了其它的报告系统,而另外一些工程师则人为地限制测试用例的数量。以便他们能(勉强地)运行系统记录。
结论
首先也是最重要的是:要记住,作为软件测试工程师,你创建的工具是通往一个终点的路。并且那个终点使你可以更好地发现不易察觉的小错误。你做的所有工作就是:要在消费者发现这些小错误之前去发现它们。
第二,要记住维护的成本。你增加到基础结构的每一行代码都是你需要维护的另一行代码。同时,因为你测试的产品将不可避免地要不断变化,你需要具有修改和扩展你的工具的能力。你的基础结构设计必须支持你正在进行的改变。
第三,使工具创建者/维护者和工具使用者保持成为一个整体。最理想的情况是,至少一些使用者需要积极参与工具的设计和维护,同样,一些工具的设计者和创建者实际上也是工具的使用者。这种"异花授粉"的方式将减少定义工具或整个基础结构而造成的混乱。