《 自动化测试最佳实践:来自全球的经典自动化测试案例解析》一一0.2 技术因素...

    xiaoxiao2021-07-11  260

    0.2 技术因素在我们看来,最重要的技术因素是测试件架构以及多个层次上的抽象。测试件(testware)是所有创建的用于测试的事物,包括脚本、数据、文档、文件、环境信息等。测试件架构就是这些事物是如何组织的,以及它们彼此之间是如何依赖的——例如,高层次的脚本使用了低层次的脚本用来与被测软件进行交互。0.2.1 抽象、抽象、再抽象:测试件架构在最初得到了一个测试执行工具后,通常会期望测试人员开始使用这个工具。当这名测试人员不是开发人员时会发生什么?现在突然需要他们成为程序员,去学习工具的脚本语言。如果他们没有编程背景,他们就不知道如何构建坚固的(自动化)代码,于是当对被测软件进行改动,同时这项改动也需要在自动化代码中进行时,维护他所写的代码可能就要付出很大的代价。通常,公司放弃一个测试执行工具是因为测试脚本维护费用很高!对于成功的自动化测试执行来说,(至少)有两个主要的抽象层次:将工具和工具特定细节与结构化的测试件分离开来;将测试(即测试人员所从事的工作)与结构化的测试件分离开来。这些内容会在0.2.1.1节和0.2.1.2节中进行更详细的描述。自动化测试人员负责实现这些层次的抽象;如果这些层次实现得不好,那么自动化维护起来就会很昂贵而且很难使用。图0-1展示的是我们认为好的测试件架构,其中还包含了为了达到这些层次的抽象自动化测试人员所扮演的角色。

    图0-1 抽象的层次0.2.1.1 将测试执行工具与测试件分离开来一个好的测试件架构能够让测试自动化发挥真正的力量。自动化测试架构师负责设计测试件的架构:脚本、数据文件和实用工具等,这些都是自动化测试所需要的。其他的自动化测试人员在之后必须对其进行补充和完善。这里需要好的编程实践:良好的结构,遵守一些合理标准的模块化代码,这些标准鼓励代码的简易性和复用性。当软件的一些方面有所改变时,也许测试件需要进行改动,但是一个好的架构会让这些变动最小。可以通过框架来实现测试件架构,框架可能是测试执行工具的一部分,也可能和测试执行工具分开;或者也可以通过分开的测试控制程序或者测试解释器来实现测试件架构。有时人们在用户界面(UI)对象(如按钮和编辑框)周围使用包装器(wrapper)。包装器是个好的开始而且对于好的自动化测式来说也很有必要(但是并不足够)。为GUI对象的名字使用对象映射(object map)也是另一个用来实现合适层次抽象的例子。另外一个重要的方面是较高级的测试件不应该直接与任何特定的工具或者工具语言绑定在一起。当然,在工具接口上,脚本必须是以选择的工具语言所编写,但是这仅仅是对于最底层而言;结构化的脚本应该以与工具无关的方式编写。你也许会认为,当前使用的工具很完美,为什么还要这么做?但是随着时间的推移工具会发生变化,应用程序也已意料之外的方式发生改变,系统可能要迁移到其他环境或者平台上,于是3年前看起来完美的工具现在看起来并不那么合适。如果测试件和工具紧紧地绑定到一起,那么很有可能你最终会不得不抛弃测试件的很多部分。如果达到了这个层次的抽象,那么就可以保留结构化的测试件的大部分,仅仅需要改动最底层的那些与工具相关的脚本。这个层次的抽象能让自动化测试有着更长的生命周期。通过使用正确层次的抽象,无论是在应用程序上进行了改动,还是在当前使用的工具发生了变动,依然可以使得自动化测试继续进行下去。在本书提到的所有成功案例研究中都在一定程度上实现了这一层次的抽象。0.2.1.2 将测试与测试件分离开来顶层(高层)的抽象是将测试的基本想法(即对什么进行测试)与测试的实现(如何构建自动化测试)分离。测试人员使用对他们有意义的高级(领域相关的)关键字编写测试,以描述他们想要运行的测试。这一级别的抽象对于那些没有编程技能的测试人员是最重要的。他们的专业技能可能是有关业务或者应用程序的。如果是程序员在开发测试,他们会更加理解这些测试技术是如何实现的,于是这层的抽象对他们来说就没有那么重要;这些对于开发人员最合适的高级关键字可能对那些业务用户来说过于技术性。但是不要忽略这一点,即对于那些编写和维护测试的人员来说,易于使用这些测试是很重要的,而不管他们是不是程序员。测试人员的工作是测试(见0.1.5节中关于技能的部分)。在关注如何最好地对一些事物进行测试时,不应该考虑过多的实现细节。他们应该能够使用对他们来说有意义的语言来编写测试,而不是使用只对工具有意义的编程语言。他们关于测试的想法与他们的领域有关(即他们测试的应用程序),于是他们的测试也应该与这个领域有关。例如,一个拥有保险业务知识的测试人员可能会关注保险索赔和续保。一名专注移动设备的测试人员可能会想对网络连接、会议电话等进行测试。对于不同行业部门的人来说,这些高层次关键字可能非常不同,即使一些低层次的关键词可能会相同。这就是为什么我们喜欢这个词目——“领域相关的测试语言”(Domain-Specific Test Language, DSTC),这点Martin Gijsen曾也提到(www.deanalist.nl)。如果没有任何编程经验的测试人员既能编写也能运行自动化测试,那么自动化测试就能对业务领域有巨大的帮助,而且更有可能广泛地应用,进一步增加ROI。专门地讨论这个层次抽象的案例研究包含在第2、11、12、14、15、20、21、27和29章。0.2.2 自动化测试标准如果人们仅仅关注自己的事情,他们将会以只对他们有意义的方式创建自动化测试和测试件,然而他们创建的东西彼此之间都不相同。如果想要很多人使用自动化测试,那么定义自动化的标准并去遵守这一标准是很重要的。标准的命名约定,存储测试件条目的统一的地方,创建测试的标准方式,归档测试的标准例子,对象、脚本和数据文件的标准名称;每个脚本的标准文件头——需要达成一致并且普遍使用的事情远比你能想到的还要多。之外,使用自动化测试的人越多,遵循标准就越重要,并能带来更大的收益。对这些自动化测试标准的定义最好在试点项目中开始,在试点项目中可以尝试各种方法并且达成一致。之后必须将大家都同意的标准告知所有将要使用自动化测试的人员——无论使用领域相关的测试语言定义自动化测试的人员,还是开发可复用脚本的人员。我们还建议将一些标准构建到支持测试的工具中,以便更容易地创建更多的脚本,而且还能避免很多人为错误。然而这些标准也不应该一成不变。随着自动化测试变得成熟,保证标准可以变更以及遵循新的(改进的)方法进行更新是个很好的主意。另外很重要的是,允许标准中出现例外情况,当然,要对这些例外进行验证。随着自动化测试规模变大,将标准进行集中管理并且就其与所有人员进行沟通就变得更加重要。关于标准的讨论参见第6、9、12、15、21和29章。0.2.3 可复用性、文档和灵活性虽然有时构建一些“可以丢弃的脚本”(disposable script,参见第19章)是很有用的,然而大部分自动化测试中,单个脚本都有很长的生命周期,并且需要以多种方式复用。如果脚本使用多次,那么就值得花费时间去保证它构建良好,如其中包含良好的错误处理方法,并且保证对其进行过测试和审阅。去找寻那些可以复用的模块,而不是一切都从头编写。为了使得测试自动化人员能够找到并且使用可复用的模块,这些模块必须有良好的文档。应该可以很容易地访问这些测试件条目的信息,而且这些信息应该以标准的格式呈现出来。例如,在每个脚本头,写出这个脚本的目的、如何使用这个脚本(它期望接收的数据以及返回的数据),以及一些前置条件和后置条件。一些额外的信息也很有用,如在一些可能的错误条件下会发生什么。这些信息应该可以很容易地搜索到。事实上,将这些信息收集起来就可以作为测试件的文档,而且通常可以很直接地将这些信息收集起来,并将其分类到单独的文档或者集中进行管理。在运行测试时,灵活性是很重要的。例如,如果一个脚本正在处理从电子表格中得到的数据,而且并不需要电子表格中所有项都填满,那么一个更加灵活的脚本应该允许跳过那些没有值的字段,这可使测试人员很容易创建各种不同的测试。为每个测试标注上该测试属于哪一类也是很有用的,例如,可以标记其为冒烟测试、修复bug的测试或者对函数X进行的测试。使用这种“测试选择器”可以很快地选择在给定时间运行测试的不同子集。这些主题在第3、5、11、14、21和29章中讨论。0.2.4 测试结果和报告评估测试的结果是测试所做的最基本的事情:如果不关心结果是什么,那么它就不是一个测试!然而对自动化测试的结果进行检查并不是一件显而易见的事情,尤其是当检查结果是以屏幕截图的位图存储时(要尽可能避免),对结果进行自动化检查就更加困难。工具不会告诉你一个测试通过还是失败;它仅仅能告诉你测试结果和你期望的结果是否匹配。如果期望结果就是错误的,那么工具可能很“高兴地”认为所有的测试都通过,即使它正在做错误的事情!有时,自动化测试可能愚弄你,让你认为它们正在检查一些东西,而实际上没有——通过的测试通常不会有人进行检查,然而这有时会带来严重的问题,正如第15、19和29章所讨论的(第15章称这些测试为“僵尸测试”)。对于测试结果的报告应该让收到报告的人能够理解这些测试;为此可能需要做一些额外的工作来过滤以及解释原始的测试结果,但是这些工作很值得,因为这能让各类人员对这些测试有着更好的交流。这些主题在第3、5、13和20章中讨论。有时通过使用部分的预言(oracle),自动化测试仅仅能够检查测试结果的一部分而不是所有。例如,探索性的自动化测试(第28章和第29章)、猴子测试(第24章)和可靠性测试(第13章),可能会检查系统是否还在运行而不是检查系统的结果是否正确。当能够自动地生成大量测试时,仅仅检查系统是否能存活下来也是很有价值的。更多的关于测试结果和报告的讨论见第3、5、10、13、14、17、19、20和29章。0.2.5 对测试进行测试:审阅、静态分析、对测试件进行测试自动化代码(包括脚本)也是软件,正如所有的软件一样,它们也会有bug,并且必须对其进行测试。对自动化测试件进行审阅,甚至检查,也能帮助找到在测试件本身中的bug和问题,并且保证自动化测试与它的目标是一致的。这还能够有助于团队内沟通知识,让团队人员更好地了解测试件的细节。不需要审阅所有的事情——选择一个具有代表性的测试方案,并且与利益相关者对其进行审阅是一种很有效的方式,有助于确定正在进行的工作是否正常。正如第15章所述,另一个来自软件开发的技术,是对测试脚本的静态分析。静态分析工具能够发现代码(包括自动化代码)中的bug,这些bug在评审过程中以及测试中可能发现不到。虽然静态分析不能找到所有的bug,但其发现bug的速度很快而且成本很低。这些主题在第1、5、7、10、15、17、21和29章中讨论。0.2.6 对哪些测试进行自动化第2章和第12章证明了对那些没有价值的测试进行自动化是没有意义的——首先,保证将进行自动化的测试是值得自动化的;其次仅仅自动化那些重复使用的测试。首先应该对哪些测试进行自动化?那些对测试人员来说执行起来很无聊的、那些普通的并且重复的、或者那些非常复杂的测试,都是开始自动化的最佳候选测试,但是也要根据当前最需要解决的问题来进行选择,总的来说,要对那些能够为测试带来价值的测试进行自动化。第25章给出了一个用于决定是否对某个测试进行自动化的检查列表。知道不要对什么进行自动化以及应该对什么进行自动化是很重要的。过多地进行自动化也会影响自动化的结果,因为这可能使你难于获得一些“快速的回报”(quick win),虽然这些回报能更有效地证明自动化的价值。这些主题在第2、8、19、20、22、25和29章中讨论。0.2.7 自动化测试不仅仅是执行测试大多数人认为测试执行工具仅仅是用来执行测试的工具。然而,要达到好的自动化,仅仅对一项活动有着工具支持是远远不够的。书中很多案例研究都讲到,创造性地思考通过工具能支持自动化过程中的哪些活动——不论是通过使用传统商业工具还有内部实用工具、脚本、宏等,都能给项目带来惊人的收益。第19章主要关注这个主题,除此之外,第3、4、5、14、21、22、24、25和29章还包含了一些有用的小窍门和主意。在自动化测试过程中经常被忽略的一个领域就是,将手动测试引入到自动化过程中是很有用的。第21章讲述的例子很有趣,它在改进自动化的同时也加入了对手动测试的支持,在第1、8、12和19章也讨论了这个主题。另一个常被忽略的领域是对于预处理和后续处理任务的自动化。如果不能对这些任务进行自动化,那么自动化测试就不得不加入手动过程——这在很大程度上违背了自动化的目标!关于这个主题的更多讨论请参见第2、10、11、18和22章。0.2.8 失败分析当测试失败时分析原因可能会花费大量时间,对自动化测试失败的分析所花的时间要多于手动测试所花的时间。例如,手动测试时,在发现bug前你都知道做了些什么,所以在发现bug时就掌握了bug的上下文信息。然而,当自动化测试失败时,你可能仅仅知道测试的ID,而并不清楚这个测试到底是做什么、它所处的位置,以及发生了哪些其他的事情。在写bug的报告前需要重建bug的上下文信息,这需要一些时间。考虑到这种情况,自动化测试应该记录一些日志,这些额外的信息对需要检查测试失败的人是很有用的。失败分析在第20、23、27和29章中讨论。0.2.9 自动化测试是否用来发现bug0.1.1节提到过,发现bug对于测试来说是一个好的目标,然而对于自动化的回归测试来说,找到bug却不是一个好目标。然而,在一些示例中自动化确实可以发现新的bug。如果自动化能够允许运行一些测试,而这些测试不能通过其他手段运行(因为手动运行它们需要大量的时间而且不实用),那么自动化就能增加被测软件的测试覆盖率,而且还能发现那些其他方法找不到的bug。基于模型的测试(model-based testing,参见第9、14、24、28和29章)不仅能够在执行测试时发现bug,还能在模型的开发过程中发现bug。当自动化测试能够运行那些依靠手动几乎不可能执行的长序列的测试时,如猴子测试、可靠性测试和探索性自动化测试,就可以发现手动测试发现不了的bug。如果想要记录哪些bug是通过自动化测试发现的,而不是通过其他方式发现的,第11章对bug跟踪系统提出了一些建议用来找到这些bug。第27章有一些有趣的统计数据,比较了自动化测试发现的bug数量(<10%)与手动脚本测试和探索性测试发现的数量。0.2.10 工具和技术方面0.1.9节从管理的角度讨论了工具,同时也必须考虑到这些工具的技术方面。如果要开发自己的工具,就可以用这些工具做你想要做的事情;理想情况下,你将会得到适用于需求的最好的工具。然而,开发工具需要进行大量的工作(通常比预计的更多),于是通常需要在期望得到的功能和可以利用的资源之间做出折中。可以尝试的是使用多个工具来达成某个目标,而这个目标无法用单独的工具来完成。在采用这些工具时,要充分挖掘它们的用途。那些和当前测试领域密切相关的工具能保证正确使用这些领域知识,而且使用起来更容易,也更少出错。如果你在考虑测试件该使用什么编程语言,那么就挑选那些开发人员已经熟知的并且受欢迎的编程语言。这样就能更好地得到开发人员的帮助来解决测试件中出现的问题。你也需要仔细注意测试的环境;测试发现的失败应该是真正发生的问题,而不是因为在环境中忘记了加入一些因素。很多环境因素的设置也能自动化地进行,这也有效地减少了人为错误。还需要关注测试和软件的同步,尤其是当被测系统并没有限定只能使用标准的GUI控件时。虽然有很多工具对于同步提供很好的支持,并不是在所有的情况下工具都能很好地解决问题。而且有时无法充分地解决所有同步问题。这也就意味着软件中有些部分是不能应用自动化测试的,至少目前不行(或许未来会出现新的技术手段来解决这些问题)。第7、8、14、17、18、19、24、26、27和29章讨论了这些问题。


    最新回复(0)