认真对待测试工作的测试者通常面临一个挑战,即如何让他人理解测试工作的重要性。
这个问题就是"the insider/outsider problem"(局内人/局外人问题),指在特定领域、群体、文化或专业内,内部成员(局内人)与外部成员(局外人)之间存在的理解和认知差异。具体来说:
局内人指的是那些属于某个特定群体、有共同经验、知识或背景的人,他们对该领域的细节、规则、价值观和隐含意义有深刻的理解。
局外人则是指不属于这个特定群体,对这个领域相对不熟悉或缺乏深入了解的人,他们可能难以完全理解局内人的视角、动机或行为逻辑。
这个问题体现在,局内人可能认为某些信息、术语或实践是常识,而局外人却觉得难以理解或不知所云。反过来,局外人可能提出的问题或观点,局内人可能会觉得过于基础或偏离重点。这种现象在很多情境下都会出现,比如专业领域、文化差异、团队合作等,它强调了沟通和知识传递中的障碍,以及建立有效跨领域或跨文化理解的必要性。
我们不知道自己不知道什么。当我们不了解某事物时,往往意识不到自己对其了解得有多么匮乏。我们的经验都可能导致误解。“开车很简单!只要挂上挡,就可以出发了!”这在你当前所处的环境下或许非常适用。但现在,请尝试在班加罗尔的街道上驾驶。
说这么多,这和软件测试有何关系呢?
没有人能坐在电脑前随便就敲出一段能正常工作的程序,因此人们直观且正确地认识到编程必定很难。
相比之下,几乎任何人都能在电脑前偶然发现缺陷,因此人们直观但错误地认为测试必定很容易!
在软件开发的世界里,存在着一种幻想:只要大家都有善意且都全力以赴,一切就会顺利进行。如果我们相信这种幻想,就不必去寻找那些深层的、隐藏的、罕见的、微妙的、间歇性的问题;人们所谓的美德似乎会神奇地让这些问题不可能发生。这无疑是一种对风险非常乐观的处理方式。对于不太重要的产品来说,这或许还可以接受。但若我们的产品至关重要,就必须主动寻找问题。为了有意地发现深层次的问题,拥有熟练的测试人员将大有帮助。
然而,测试的角色并不总是受到欢迎。问题在于,要开发一款新颖且复杂的产品,你需要巨大的乐观精神和积极主动的态度。但正如我的朋友Fiona Charles曾引用Tom DeMarco和Tim Lister的话对我说的那样:“在一个‘a can-do environment’的环境中,风险管理几乎是被禁止的。”我甚至认为,这样的环境不仅禁止风险管理,连承认风险都是一种禁忌。
"can-do environment" 可以理解为“积极主动的工作环境”或“一切皆有可能的环境”。在这种环境中,鼓励创新思维、积极态度和解决问题的能力,团队成员相信自己能够克服挑战、实现目标,组织文化倾向于支持尝试新事物和从失败中学习。这样的环境促进了个人成长、团队协作和企业的持续进步。
在《与熊共舞》(Waltzing With Bears)一书中,DeMarco和Lister提到:“‘a can-do environment’的直接后果是抑制任何暗示‘can't-do’的分析……当你建立起风险管理的框架时,你就授权人们在某种程度上进行负面思考。明白这一点的公司理解,只有通过负面思考,才能避免项目进展过程中因风险而措手不及。”
在一部精彩的纪录片《General Magic》中,这种风险否认得到了生动体现。这部纪录片讲述了一家同名开发公司的故事。在20世纪90年代初,General Magic正在研发一种设备,其功能、设计和雄心壮志几乎与大约15年后发布的iPhone无异。
这部纪录片非常值得一看。其中一段,项目领导人Marc Porat回顾了General Magic为何未能成功发射,反而遭遇惨败的原因。他说:“有一种无所畏惧和正确的感觉,没有质疑‘我可能错了吗?’的想法。完全没有……这就是突破地球引力所需的东西。你需要巨大的动力……而这来自于压制对失败可能性的反思。”
直到今天,这种思维方式仍然在软件开发中普遍存在。作为一种工艺,软件开发行业系统性地抵制对问题和风险进行批判性思考。对于测试员而言,不幸的是,这正是我们所处的领域。
开发者在连接人类世界和机器世界方面拥有高超的技能和专业知识。但他们往往缺乏发现问题的倾向。开发者感兴趣的是消除人们的困扰。而测试员则承担着社会挑战性的任务,无论看向哪里都要发现并报告问题。与项目中的其他人不同,测试员专注于揭示尚未解决的问题,或是我们提出的解决方案所引入的问题。这种关注点,建设者出于天性往往会抗拒。
对问题的思考所遇到的阻力导致了许多无益且错误的观点。有些人认为,唯一的问题就是编码错误。有人认为,唯一重要的是满足建设者对产品的意图。还有一些人确信,我们可以通过编写构建的机械式检查来发现产品中的所有重要问题。这些观点反映了建设者——即乐观主义者——的自然偏见。这些观点使人们想象测试可以自动化成为可能。
认为测试可以自动化的错误且无益的想法促成了将测试分为“手工测试”和“自动化测试”的划分。
请注意:软件开发的任何其他方面(或实际上任何人类社会、认知、智力、批判性、分析性或调查性工作)都没有这样划分。没有“手工程序员”。没有“自动化研究”。管理者不会手工管理项目,也没有“自动化管理”。医生可能会使用非常强大和复杂的工具,但没有“自动化医生”,也没有“手工医生”,医生不会接受被这样分类哪怕一分钟。
测试无法自动化。测试及相关的某些任务可以从工具中获益良多,但让机器敲击虚拟键盘并将产品输出与特定输出进行比较,并不比拼写检查更算是“自动化测试”。请不要再这样对比了。
将测试中所有非自动化的任务归类为“手工测试”是没有帮助的。这样做就像是将烹饪的手艺、社会、文化、审美、化学、营养或经济方面统称为“手工烹饪”。任何关心人类乃至动物提供食物的人都不会认为烹饪中唯一重要的是食品处理器、微波炉和搅拌机。请理解这一点。
为“手工测试”提供更精确的术语
如果你关心了解产品的状态,你可能会关心测试它。你希望通过测试来了解你得到的产品是否是你想要的产品。如果你关心这一点,你就需要了解关于测试的一些重要事情。
如果你想了解关于测试的重要内容,你可能需要考虑一些常常用“手工测试”这个词反复掩盖的事情。考虑这些事情可能需要命名一些之前未曾命名的测试方面。
体验式测试
思考体验式测试,其中测试者与产品的接触以及执行的动作与预期用户的无法区分。毕竟,产品不仅仅是代码,也不仅仅是屏幕上的虚拟对象。软件产品是我们为人们提供的体验,当这些人试图完成任务、满足愿望、享受游戏、赚钱、与人交谈、获得抵押贷款、学习新事物...
将体验式测试与设备化测试进行对比。仪表化测试是测试中的一种,其中某种媒介(某些工具、技术或机制)介于测试者与产品自然体验之间。仪表化会改变、加速、重构或扭曲;在某些方面是有帮助的,在其他方面则不然。我们必须意识到仪器化给我们的测试带来的既有利又有弊的影响。
Instrumented testing 可译为“设备化测试”,是一种特定类型的软件测试方法,尤其在Android开发领域中较为常见。这种测试方式能够让测试在真实的或模拟的Android设备上运行,区别于仅在Java虚拟机(JVM)上运行的本地单元测试。设备化测试允许开发者和测试工程师利用Android框架和专门的测试库(如Android Testing Support Library)来创建更加复杂的测试场景。这些测试可以包括设备单元测试(Instrumented Unit Tests)、组件集成测试以及应用程序级别的集成测试,能够覆盖UI交互、系统服务交互、数据库操作等多个方面。
交互式测试
你说的是“手工测试”吗?你可能指的是测试的交互式、参与或投入的方面。在这种模式下,测试者直接且立即观察和分析产品及其行为在发生时刻的各个方面。测试者可能正在通过用户界面直接或通过某种工具间接控制产品。
当你注意到有时你会在产品行为发生的那一刻观察并与产品互动时,你可能想对比一下那些不需要你立即在场或控制的测试工作。一些任务可以通过算法、机械式的、机器无人值守即可完成的事情来处理。其中一些被某些人标记为“自动化测试”——尽管测试本身无法自动化。要使某事成为一个测试,需要在自动化行为之前的设计以及之后的解释。测试中依赖于人类社交能力做出判断的部分无法自动化。
探索性测试
你说的是“手工”吗?你可能指的是探索性工作,这与上述的体验性工作有明显的区别。至少在快速软件测试领域中,探索性指的是代理;谁或什么在从一个瞬间到另一个瞬间关于测试的选择上起主导作用。关于这个还有很多值得一读的内容。
wait……体验性和探索性测试不是一样的吗?
你可能在以一种完全不像用户正常接触产品的方式进行探索,即无剧本的选择。你可能在生成大量的数据并与产品互动以对其施压;或者你可能在尝试剥夺产品的资源时进行探索。你可能正在执行一个动作,然后分析产品产生的数据来发现问题,每一刻都保持对自己选择的掌控,不受正式程序脚本的控制。
也就是说,你可以在接触产品以调查它时进行探索。这是件好事,但这更像是以测试者的身份而不是用户的身份接触产品。意识到这两种接触方式之间的差异并加以利用,而不是混淆它们,可能是一个非常好的主意。
你也可以以高度脚本化、探索性较弱的方式进行体验性测试。例如,你可以遵循面向用户的教程,逐步完成其每个步骤,观察教程与产品行为之间的不一致性。对外部观察者来说,你的接触看起来几乎就像用户的接触;他们大部分时间会看到你以自然的方式与产品互动——除了你记录观察、错误、问题、风险和测试想法的时刻。但测试生活形式之外的大多数观察者都不会注意到这些时刻。
当然,这两种接触方式之间存在重叠。关键的区别在于,测试者在遇到问题时会进行调查并报告。用户这样做可能性要小得多。(尝试从LinkedIn的文章编辑器中输入链接时,请注意这一现象;“应用”按钮不可见,隐藏在弹出窗口的右侧。这是我以体验性方式与LinkedIn互动时发现的问题。我希望我在以探索性方式进行有意识的测试时也能发现这个问题。)
变革性测试
你说的是“手工”吗?你可能指的是具有变革性的测试活动,即执行测试的某些方面在某种意义上改变了测试者。变革性测试涉及学习、促进顿悟、识别风险或触发测试设计思路。在测试的早期阶段,特别是放松或暂停我们对发现问题的关注,更多地关注建立我们对产品的心理模型可能非常重要。这为后续更深入的测试铺平了道路。
与之形成对比的是高度程序化的测试方式:交易性测试,相当于死记硬背、例行公事、勾选框。大多数交易性事务都可以机械化完成。机器并不会真正受到发生的事情的影响,也不会在任何有意义的层面上学习。人类会,如果我们想找到深层次的bug,就需要深入了解产品。
无疑,“手工测试”还有其他维度。一段时间以来,我们曾考虑过“推测性测试”作为人们提到“手工测试”时可能指代的内容;“如果……会怎样?”我们将此与“演示性”测试进行了对比——但随后我们认为演示其实根本就不是测试。至少不是有意为之的。对于一个行动来说,要成为测试,我们认为它本质上必须是推测性的。
Manual Testing is… Testing
主要的一点是:如果你是一名“手工测试者”,那么你一直在做测试工作。如果你是一名“自动化测试”或“自动化工程师”,你也一直在做大量的“手工测试”——除非你只是根据规范编写自动化检查,运行它们,并完全忽略结果。
测试人员经常被灌输一些胡言乱语。其中一份胡言乱语放在了一个盘子上,说“自动化”测试不知何故比“手工”测试“更好”。但除非你是通过实验来体验、探索和与产品互动,否则你不能声称自己在进行测试。(这里的“产品”可能是正在运行的软件,或者是它的一部分。但它也可能是原型、设计、图纸、想法的描述;这些都可以通过在脑海中体验、探索和实验来进行测试。)工具可以为这类工作提供巨大支持,但将测试特征为“自动化”则是忽略了不涉及机器的一切。
有一种说法是,“手工测试”是“缓慢且容易出错的”——好像人们在将自动化应用于检查时不会犯错误一样。他们会,而且自动化使得这些错误在更大和更快的规模上得以实现。
当然,自动化检查运行迅速;它们的执行成本低。但它们可能有巨大的开发成本;巨大的维护成本;很高的解释成本(弄清楚哪里出了问题可能需要大量工作);高转移成本(向非作者解释它们)。
还有另一种成本,与其他成本相关。它被很好地隐藏起来,没有被计算:我们可能称之为解释成本或分析成本。一个足够大的自动化检查套件是难以穿透的;没有非常昂贵的审查就无法理解。那些总是绿色运行的检查真的做了什么吗?除非你进入一个“手工”过程并评估你所看到的,否则谁知道……
运行红色的检查会频繁受到关注,但很多都是“不稳定”的;当它们实际运行红色时,它们应该运行绿色。在数千个运行绿色的检查中,有多少实际上应该运行红色?认知上了解这一点的成本很高——因此人们通常会忽略它。
所有这些成本代表了另一种隐藏的成本:机会成本;做一些事情,以至于它阻止我们做其他同等或更有价值的事情的成本。这个成本是巨大的,因为在我们本可以直接与该死的产品互动的时候,花费如此多的时间和精力去自动化GUI的行为。
更奇怪的是,我们不是在教非技术测试人员编码并自然地体验API,而是让他们面对API的GUI前端。因此,我们有了熟练的编码人员试图自动化GUI,同时也有非编程测试人员,使用Cypress去体验化API的使用!测试人员通过Cypress体验API与程序员尝试使用API的体验截然不同。
而且没有任何测试人员被鼓励去分析他们采取的方法的成本和价值。技术至上主义(很好的词汇;阅读Meredith Broussard的《人工非智能》一书)强化了一种错觉,即测试软件是一项常规的、工厂式的、机械的任务,正等着被编程取代。这是一个谎言。测试可以从工具中受益,但测试不能被机械化。
测试必须专注于发现伤害人们或使他们不开心的问题。为什么?因为正在构建产品的乐观主义者往往对这些问题没有察觉,而这些问题可能潜伏在产品中。当建设者意识到这些问题时,建设者就可以解决它们。从而让自己看起来不错,赚到钱,并帮助人们拥有更好的生活。
测试必须被视为一种社会(且社会上有挑战性)、认知、风险聚焦、批判性(在多个意义上)、分析性、调查性、熟练、技术性、探索性、体验性、实验性、科学性、启示性、光荣的手工艺。而不是“手工”或“自动化”。让我们敦促这种误导性的区分在一个荒岛上度过一个长假,直到它因忽视而消亡。
下方扫码关注 软件质量保障,与质量君一起学习成长、共同进步,做一个职场最贵Tester!
往期推荐