6. 考虑使用其他类型的自动化
LAWST会议的重点在GUI级回归测试工具,所以本文的重点也是这个内容。在LAWST会议召开前夕,我们每人都介绍了我们在测试自动化方面的经验。其中的一些人报告了大量的成功案例,但大多数案例都涉及到那些编写测试应用程序的程序员的协作。这些成功案例中用到的工具各式各样,说明不同的测试工具能带来不同的收益。
对于基于GUI的回归自动化测试,有很多带有欺骗性的、不切实际的想法。它们制造出测试能覆盖所有地方的假象,并且引起严重的员工跳槽,并且还使你最有技术的员工专注于设计和维护相对较少bug的测试用例。
这些工具确实很有用,但是它们需要大量投资、审慎规划、培训员工以及十分小心地使用。
附录 LAWST会议上得到的若干结论
在讨论会议每天日程的后三分之一,我们把在讨论中得到的一些论述抄写到写字版上并进行投票。我们并非想获得一致意见。这样做的目的,是想看看每条论述与这些经验丰富的测试工程师的经验符合的程度。在有些情况下,我们中的一些人并没有投票,可能是因为我们缺乏对要投票的论述的具体经验,也可能是因为我们认为该论述不够合理。(这里我已经省略了大多数论述。)
如果你正试图把自动化的成本和风险告诉给你的一位经理,那么以下这些投票结果或许是你们讨论的有用数据。
一般原则
1. 这些论述并非终极真理。在规划自动化时,由于投入了这么多的努力,你必须时刻记住哪个问题是你试图要解决的,以及在何种环境下解决它。(一致同意)
2. GUI级自动化测试是软件开发中的一项重大工作。它需要架构、标准和纪律。适用于软件设计和实现的一般原则同样适用于自动化设计和实现。(一致同意)
3. 为了效率和可维护性,我们需要首先开发一个不随特性改变的自动化结构。我们应该开发像特性一样稳定的基于GUI的自动化。(一致同意)
4. 我们中的一些人认为一个公司的自动化工作可以采用演化模式来进行。
第一代(7票赞成,1票反对):在缺乏以前的自动化经验时,大多数自动化工作将经历以下三个过程:
a. 截取/回放失败。我们截取的是比特还是窗口部件都无关紧要(面向对象的截取/重放)
b. 使用个人编程的测试用例失败。(个人编码的测试用例是按他自己的标准编写的,没有遵循一般标准以及构建共享库)
c. 开发维护在正在进行的基础之上的函数库。这个库可以包括脚本测试用例或数据驱动测试。
第二代(10票赞成,1票反对):一般自动化的主动失败源于以下几点:
a. 把截取/回放作为创建测试用例的原则性方法。
b. 使用个人编写脚本测试用例 (个人编码的测试用例是按他自己的标准编写的,没有遵循一般标准以及构建共享库)
c. 使用设计不好的框架。这是一个普遍问题。
5. 测试用例的直接重放会带来低缺陷(一致同意)
一旦一个程序通过了测试,那么以后就不太可能不通过该测试了。这种说法导出了一些论述(没有一个被明确赞成),即自动化测试有危险,因为它给我们一种很舒服的错觉,认为程序没有问题。即使程序今天没有出现昨天出现的问题,但是依然还有很多情况可以使程序出问题。而如果你总是在没有bug的地方寻找,你就永远找不到它们。
6. 在一次自动化测试工作中找到的bug里,60%到80%是在开发测试中被发现的。也就是说,除非你从一开始就用自动化工具创建并运行新的测试用例,不然大多数bug都会在手动测试中被发现。(一致同意)
我们大多数人都不是第一次使用自动化工具来运行测试用例。在传统规范中,你首先要手动运行测试用例,然后在程序通过测试后把它添加到自动化套件中。但是,如果你有一种办法不依靠先前的截取的输出结果就能确定程序是否通过了测试,那么你就能更加有效的使用工具。例如:
要在不同的操作系统版本或配置上运行相同系列的测试。你可能从未在一种特殊配置环境下测试过程序,但是你知道它应该怎样工作。
要运行一个功能等价测试。这时,你可以并行地运行两个程序,并且给它们同样的输入。如果程序的结果总是与对照程序一样,就说明它通过了测试。
要在测试中操作代码,这样就能在出现异常情况时生成日志,比如,程序到达了一个异常状态、做了一个异常状态转换、以异常方式管理内存、堆栈或其他资源、或者做了任何一种错误的事情。先通过大量的状态转换以及记录执行的命令使用测试工具随机地驱动程序。然后在第二天,测试人员和程序员通过跟踪日志来寻找bug和触发它们的环境。这是模拟出的一个简单例子。如果你正在与应用程序团队合作,那你就能像这样,相对自己手工编写新的测试用例脚本,更加扩展地、有效地(每周都可以找到新的bug) 用你的工具创建测试。
7. 当我们与程序员合作开发链接、接口和调试输出时,自动化会更加成功。(一致同意)
很多这种协作方法并不依赖基于GUI的自动化工具,或者说,人们只是用这些工具做测试驱动,并没有考虑我提到的基于GUI的回归测试规范。在 LAWST会议的第一天,我们兴高采烈地听着自动化的成功案例。但这其中,很多重大的成功都涉及到与编程团队的协作,而并没有涉及到传统的基于GUI回归测试工具的使用。
我们将在今后的LAWST会议中探讨可协作的测试设计与开发。
8. 大多数用截取工具生成的代码是不可维护的,且没有长期价值。但是,在编写测试时,截取工具很有用,因为它能显示工具是如何翻译一系列最近发生事件的。而且,用截取工具生成的脚本能在你编写代码时给你有用的信息。(一致同意)
9. 我们根本不使用屏幕截图,因为这是在浪费时间。(事实上,我们的意思是我们不喜欢使用屏幕截图并只在必要时使用它。例如,我们发现它在对比屏幕小分区方面有一定价值。而且,我们有时不得不对比屏幕截图,或许是因为我们正在测试一个自绘制控件。但是更可能的情况是,我们会对比逻辑结果,而不是位图。)(一致同意)
10. 不要在测试自动化时弄丢测试点。比起查找bug,在编写脚本时犯糊涂真是太容易了。(一致同意)
测试设计
11. 对容易的东西进行自动化不是正确的策略。(一致同意)
如果你从创建一组简单的测试用例开始工作,那么你很可能在你创建强大的测试用例之前就把时间用光。一个大型、简单、且易于通过的测试用例集合会比专门的手动测试看起来更加严格,但是,一个有能力的手动测试者能在程序稳定的情况下运行日益复杂的测试。
12. 联合测试能找出新的bug。(总和比各部分要强大) (一致同意)
13. 虽然我们需要方法确定一个测试用例,但是使用不确定的(例如随机的)自动化测试也有价值。(一致同意)
我们并不鼓励盲目的测试。你需要知道你在运行什么测试。而且有时,你需要能指明准确的输入和输入序列。然而,如果你能确定程序是否通过了你在运行的测试,那将会不断带给它新的测试用例,而不是重新运行它已经通过的旧测试。
14. 我们需要规划能记录已经完成的测试的功能。(一致同意)
有些工具能容易地记录测试进程,而有些则很困难。对于调试目标和跟踪测试过程,你会想要大体知道已经运行了哪些测试用例,以及它们的结果是什么。