看家本领之三:软件测试的批判性思维

两千多年前,在谈到正义和非正义时,苏格拉底(Socrates)和尤西德姆斯(Euthydemus)有一次精彩的对话。苏格拉底向尤西德姆斯提问道:“虚伪是人们中间常有的事,是不是?”

“当然是”,尤西德姆斯回答。
“那么,我们把它放在正义和非正义的哪一边呢?”苏格拉底问。
“显然应该放在非正义的一边。”
“人们彼此之间也有欺骗,是不是?”苏格拉底问。
“肯定有”,尤西德姆斯回答。
“这应该放在两边的哪一边呢?”
“当然是非正义的一边。”
“是不是也有做坏事的?”
“也有”,尤西德姆斯回答。
“那末,奴役人怎么样呢?”
“也有。”
“尤西德姆斯,这些事都不能放在正义的一边了?”
“如果把它们放在正义的一边,那可就是怪事了。”
“如果一个被推选当将领的人奴役一个非正义的敌国人,我们是不是也能说他是非正义呢?”
“当然不能。”
“那末我们得说他的行为是正义的了?”
“当然。”
“如果他在作战期间欺骗敌人,怎么样呢?”
“这也是正义的”,尤西德姆斯回答。
“如果他偷窃,抢劫他们的财物,他所做的不也是正义的吗?”
“当然是,不过,一起头我还以为你所问的都是关于我们的朋友哩”,尤西德姆斯回答。
“那末,所有我们放在非正义一边的事,也都可以放在正义的一边了?”苏格拉底问。
“好象是这样。”

这就是苏格拉底反诘法,今天要讨论的“批判性思维”可以追溯到这里。

 

1. 什么是批判性思维

批判性思维是指一种合理的反思性(反省的)思维,是一种训练有素的思维方式的体现。它借助观察、经验、反思、推理或沟通等收集信息,并对这些信息进行抽象、应用、分析、综合或评估,以此决定相信什么或做什么。批判性思维是一种思维方式和能力,不受学科或专业的性质,任何论题都可从批判性思维的视角来审视。

        像上面苏格拉底那种无止境的设问、追问或质疑,就是批判性思维的体现。任何人下结论之前,或多或少包含了假定和推理,而作为批判性思维的践行者就可以质疑其假定、推理和结论,这样可以消除认知中的误区,突破知识构建时的边界,重新认识某个主体。如“人们彼此之间也有欺骗”分为恶意欺骗和善意欺骗、对朋友的欺骗还是对敌人的欺骗。但如果不仔细想,就会局限于一般意义的恶意欺骗,正如尤西德姆斯不假思索地回答:“当然是非正义的一边。”之所以有这结论,其中包含了假定——“通常意义上的(恶意)欺骗”,而忽视了某些情况下的“善意欺骗”或欺骗敌人。如果尤西德姆斯这样回答“对朋友的恶意欺骗是属于非正义的” ,苏格拉底就不容易抓住漏洞。实际上,人类认知是有限的,人们在常识(普遍接触的条件,这也是有边界的)下得出的理论,当达到或超出边界时,认知就会发生谬误。例如现在人们常常用“黑天鹅事件”比喻发生了意想不到的事情。原来欧洲人通过对天鹅的观察,认为天鹅都是白色的,这是普遍法则(成为一种常识),但是后来发现澳洲的天鹅是黑色的,证明原来的普遍法则不成立。

“你是谁?”,回答自己的名字有意义吗?回答自己是:

  • 一个好人?
  • 一个人民的教师?
  • 一个来自农村的乡下人?
  • 一个来自东北的汉子?
  • ……

这样简单的问题都难以回答,因为要看问问题的人问这话的目的是什么?想弄清楚有关你的哪些信息?许多信息包含着一定的模糊性、不确定性和局限性,只有消除这种模糊性、不确定性和局限性,认知才会前进一大步。如果总是认为信息是明确的、已知的,思想就很可能陷于“僵化”、固步自封。而具有批判性思维的人,其心态相对开放,能够虚心倾听他人不同的观点,接受不同于自己但正确的观点。

没有审视和分析就不能做出正确的判断。批判性思维促进我们重新审视问题或主题、意图和陈述之间实际的推论关系,勇于质疑证据,去分析和评估陈述、论证的过程。清楚对方是表达一种信念、判断还是一种经验?其理由正当、充分吗?仅仅是个人的感觉?有前提吗?相关的因素都考虑了?有依据支撑吗?什么情况下成立?依据来源哪里?可靠吗?也就是要评估陈述的可信性,分析其推理的合理性、前后逻辑关系的严谨性等。

批判性思维不仅质疑别人的陈述,也可以质疑自己的信念、主张或判断,如:

  • 抱着实事求是的态度,避免主观臆断,促进我们自己收集数据、证据;如果与个人主张、信念冲突,依旧尊重事实,有必要调整自己的观点。
  • 表明问题所处的语境(上下文),明确列出陈述所涉及的条件;
  • 根据客观事实和上下文做出可信的假定、制定合理的原则;
  • 听取不同的意见,对不同的意见采取宽容的态度,防范个人偏见,尽量系统全面地考虑问题;即使在欠缺全面知识的情况下,也能明白权宜之计有时是必要的。
  • 明确阐释概念或问题,避免含糊其辞,采用规范的术语;
  • 有警觉性地去接受多种解决问题的方法,审慎地作出判断;
  • 以强有力的论证形式表达论证,合理推理,客观预测,准确地陈述结论。

批判性思维践行者不仅具有良好的系统性思维、分析性思维,而且更具求知欲,更加开放、自信,不断追求真理,使自己的认知不断深入下去,修正自己,更加成熟。

 

2. 批判性思考者与非批判性思考者的区别

耶鲁大学校长莱文认为教育就是培养批判性思考者,曾经这样评价中国的本科教育:缺乏跨学科的广度;缺乏批判性精神的培养。我们如何理解批判性思考者与非批判性思考者的区别呢?可以参考《超越感觉——批判性思考指南》一书的总结

批判性思考者 非批判性思考者
以诚待己,承认自已所不知道的事情,认识自己的局限性,能看到自己的缺点。 假装自己知道的比做的还多 ,无视自己的局限性,并假设自己的观点无差错。
把问题和有争议的议题视为令人兴奋的挑战。 把问题和有争议的议题视为对自我的损害或威胁。
尽力领会复杂性,对其保持好奇心和耐心,并准备花时间去解决难题。 对复杂性缺乏耐心,宁可困惑不解也不努力搞明白。
把判断建立在证据而不是个人喜好上;只要证据不充分就推迟判断。当新证据揭示出错误时,他们就修改判断。 把判断建立在第一印象和直觉反应上。他们不关心证据的数量和质量,并且顽固地坚持自己的观点。
对他人的思想感兴趣,因而愿意专心地阅读和倾听,即使他们往往不同意他人的观点。 只关注自身和自己的观点,因而不愿关注他人的观点。一看到

不同意见,他们往往会想“我怎么能够反驳它?”

 

认识到极端的观点(无论是保守的还是自由派的)很少正确,所以他们避免走向极端,践行公正性并且寻求平衡的观点。 忽视平衡的必要性,优先考虑支持他们既成观点的看法。
践行克制,控制自己的感情而不是受感情所控制,三思而后行。 容易遵从自己的感情和冲动地行动。

3. 批判性思维在软件测试中的应用

基于批判性思维,我们需要重新定义“软件测试”:软件测试就是测试人员不断质疑被测系统的过程(注:这里的测试人员是泛指,而不是指专职的测试人员,开发人员在做测试时就是扮演测试人员的角色)。需求定义、系统设计中存在研发人员太多的猜测、不真实的假定、片面的理解、不合理的推理等等,软件测试在需求评审、设计评审、代码评审和系统测试中就是要重新审视被测对象,质疑那些不合理、不真实的内容,发现软件中的错误、漏洞。

这种软件测试定义,特别适合探索式测试方式。探索式测试聚焦被测系统(SUT),侧重发现缺陷,强调在一个相对封闭时间(session)内“设计、执行、分析、学习”循环的、不断优化的测试过程。这里的session 不宜翻译为“测程”,而可以理解为就是“会话”——测试人员和SUT一次真正的对话,测试人员不断地向系统提出问题(质疑系统),然后审视系统所做出的回答(系统的响应),从而根据test oracle做出判断:系统的响应是否符合我们的期望。

这也是“系统隐喻”的一个实例,即把“测试人员”看成客户端(浏览器),把SUT看成服务器,测试过程就是测试人员和SUT建立session的过程,客户端不断发出请求,并检验系统发回来的响应结果。

     再举一个例子,帮助大家理解这样一个过程。我们招聘一个新人,会给出职位描述(JD)——详细描述工作岗位要求和责任,应聘者会根据JD提交详细的简历。本来我们就可以根据应聘者的简历来决定是否录用他/她了,为什么不能?还需要安排面试呢?因为:

  • 它的简历某些内容可能不真实,这种情况虽然很少;
  • 简历中某些描述,大家理解可能不一致,例如“精通Java”、“沟通能力”、“情商”没有明确的标准,应聘者和企业对此认识可能差别很大,需要收集更多信息和数据,进行比较分析,才能更加具体客观;
  • 有些内容缺失或不宜在简历中描述,个人气质、性格、情绪控制能力等需要在面试中获得相关信息,做出判断。
  • 简历中某些描述可能比较粗糙,不够具体,和企业需求匹配程度如何?需要从多个应聘者中择优录用。

从批判性思维角度来理解软件测试,就是测试人员“面试”SUT的一次会话过程,因为软件测试和面试有许多相似之处。虽然我们也有需求文档和设计文档,但是不够,存在矛盾、缺失、二义性、……今天敏捷开发模式下,需求描述就更不充分,更需要测试人员去“面试”系统。探索式测试的核心(出发点)就是质疑系统,不断深入系统的每一个业务入口、应用场景、业务操作和数据输出等进行质疑,质疑某个地方存在某类缺陷

  • 开发人员对用户真实的需求的错误理解;
  • 漏掉某些需求
  • 错误地实现了需求或设计;
  • 没有完整实现需求或设计;
  • 算法不够优化,存在性能问题;
  • 数据输入缺乏保护;
  • ……

这就要求测试人员善于质疑、善于向系统提问,可以参考 M.N.Browne: Asking the Rright Questions: A Guide to Ctitical Thinking (10thedition).

探索式测试中“设计、执行、分析、学习”也体现了批判性思维的“抽象、应用、分析、综合或评估”,或者说,测试人员就需要具备良好的“抽象、应用、分析、综合或评估”能力,分析和评估软件产品的质量。这就要求测试人员:

  • 善于和产品经理、业务人员、开发人员的沟通,收集SUT及其测试的相关信息;
  • 善于分析所收到的信息,能够用结构化的思维呈现测试需求等;
  • 善于观察,能敏锐地捕捉到异常现象;
  • 总结自己的测试经验、业务经验,实现更好、更快的测试设计;
  • 随时反思自己的测试设计、测试操作过程和测试分析等;

探索式测试也是开放的、动态的,强调上下文驱动。“设计、执行、分析、学习”循环中的“分析”是对当前执行测试的结果进行分析,基于当前的分析获得学习,然后设计出更好的测试(tests)。测试的结果是在变的,分析和学习就要理解这种变化,对产品的理解也在不断深入,需求可能也会改变,设计和代码也重构了,这些都意味着“新的设计和执行”的上下文在改变给了我们测试优化的空间要求我们对测试策略、测试思路也要做出相应的调整

即使在传统的测试方式中,批判性思维也能发挥很好的作用,当然,我们可以将批判性思维看作是分析性思维的一种分支,只是它更强调“质疑”、“求真”的思维方式,对假定、推理过程、结论进行主动的审视,这和测试思维有着非常高度的吻合性。所以,批判性思维是软件测试人员需要掌握的看家本领,在工作中我们需要不断进行训练、不断提升这项技能。

参考文献:

看家本领之一:软件测试的系统性思维

看家本领之二:软件测试的分析性思维

周末读书:学会提问——批判性思维指导


 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我
  • 上海市嘉定区曹安公路4800号同济大学软件学院
  • kerryzhu@vip.163.com