写点什么

青眼看测试

  • 2019-06-14
  • 本文字数:4941 字

    阅读完需:约 16 分钟

青眼看测试

男女有别,尽管许多国家不断地采取措施提高女性的地位,男女不平等至今还是全世界的难题。同样地,一个公司无论怎样努力地标榜对测试的重视,也难以抚慰测试工程师在和开发工程师比较时那种青涩、暧昧、欲语还休的复杂心绪。坦率且勇敢地面对现实,不妨就直说了吧,测试和开发天生存在不可逾越的鸿沟吗?测试工程师注定低开发工程师一头吗?


稍安勿躁,让我们从测试工程师和开发工程师共同工作的对象程序的构造说起吧。众所周知,构成程序的两大要素是过程(Procedure)和数据(Data),正如 MIT 计算科学教材 SICP (Structure and Interpretation of Computer Programs)开篇所讲的那样,程序是抽象的精灵。


“Computational processes are abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data.”


因“四人帮“(Gang of Four)的著作(Design Patterns: Elements of Reusable Object-Oriented Software)而名噪一时的软件设计模式(Software Design Pattern)系统地描述了解决一般性问题的可复制的编码(programming)参考模板,它本身就是最佳开发实践的抽象。而经典的模式如简单工厂模式(Simple Factory)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)、适配器模式(Adapter)、策略模式(Strategy)等背后的共同原理不过是抽象在程序设计中的具体应用。


抽象并没有想象中那样的抽象。简单地讲,名正则言顺,给程序的过程(方法和函数)或数据(类、对象或变量)赋予一个名字,则其他的过程或数据通过引用该名字而重用该过程或数据,这其实就是抽象了。就程序设计而言,隔离是抽象相伴而生的孪生兄弟,仿佛一枚硬币的正反两面,有抽象就有隔离,反之亦然。抽象出来的是程序中一般的、可重用的的过程,而其余的处理千万种特定情况的过程就是要隔离的过程。过程如此,数据亦然,比如,类的组合与继承就是数据的抽象和隔离。我们引用 SICP 中的一个平凡的(Trivial)scheme 的例子来说明这种抽象与隔离的艺术:


(define (map proc items)  (if (null? items)    nil    (cons (proc (car items))      (map proc (cdr items)))))

(define (scale-list items factor) map (lambda (x) (* x factor)) Items))

(scale-list (list 1 2 3 4) 10)结果是:(10 20 30 40)

(map (lambda (x) (* x x)) (list 1 2 3 4))结果是:(1 4 9 16)
复制代码


map 完成了 list 的遍历和再组装,这是 list 处理的一般的和可重用的过程,即为可抽象的部分。对 list 的元素的转换却有千万种情况,而这种不同被隔离在了传递给 map 的过程参数 ((lambda (x) (* x factor))和(lambda (x) (* x x)))中。作为参数传递的过程扮演着数据的角色,这正是所谓的函数型编程语言(Functional Programming Language)如 scheme 再平常不过的抽象机制。抽象和隔离给程序设计带来了极大的灵活性。比如说,将 list 中的数值元素转换为它的绝对值,并不需要重新写一个过程,遍历 list 的每个元素,算出绝对值,并把转换后的元素组成新的 list。取而代之的是仅仅把取绝对值的过程作为参数传递给 map,这是何等的简洁便当:


(define (abs-list items factor)  map (lambda (x) (if (< x 0)                (- x)                x))      Items))
复制代码


抽象不是为了抽象而抽象,耍酷或故作高深更不是抽象的目的。抽象是克服程序复杂性的一种计算思维方法,由抽象定义的类似软件设计模式那样的结构可以把代码以可理解的方式有效地组织起来,来保证代码的可读性,降低代码维护的成本。否则,一切混乱的象一堆麦秸,开发百万行乃至于千万行代码的大型软件系统从项目的角度是无法管控的。从纵向观察,由抽象带来的分层描述了程序最一般的结构。比如,软件低层的基础设施隐藏了实现的细节,向上层的功能应用提供了透明的抽象接口。因此,层在程序的不同组成模块建立了抽象屏障,在接口不变的情况下,低层代码的改变不会影响上层代码的逻辑和行为。众所周知,在互联网工业界,软硬件建立在一个经典的分层模型基础之上,即开放式系统互联通信参考模型(Open Systems Interconnection model)和相关的 TCP/IP 协议簇(TCP/IP Protocol Suite)。若没有定义在该模型上的由硬件到软件的层次分明的协议标准,不同网络厂商的设备及各种 Client/Server 之间就没有共同语言,互联互通更无从谈起,今天互联网的繁荣局面也只能在科幻的想象中存在。


层的抽象提高了程序结构设计的模块化,与此同时,也造就了软件工程师的角色与分工,不同角色的工程师工作在程序不同的层上:我们作为一家生产网络交换机嵌入式操作系统的软件公司,Linux 系统工程师和 ASIC/SDK 系统工程师工作在最底层,负责外围设备的驱动程序及交换芯片的统一的配置控制接口;中间层的协议栈工程师开发面向用户的网络功能;最上层的应用工程师提供特定应用场景的解决方案。混迹于职场许多年,就我所知,其他公司大概也有类似的根据层的工程师角色的划分。比如互联网公司中工程师常见的角色有前端工程师,后端工程师和算法工程师。


那么,测试工程师是否也工作在程序的某一层呢?恐怕很多测试工程师都不曾仔细思考过这个问题。测试不过就是测试,即使自动化测试也不生产包含在发布产品中的代码,更别提从来不用写代码的手工测试了。测试工程师莫非是跳出三界外,不在五行中,天不收,地不管的与程序无涉的特别的另类?!实则大谬不然,测试工程师包括做手工测试的测试工程师必须且只能工作在程序的某层上。否则,测试不过是开发的附庸和配角,焉能不委屈?!就敝公司而言,自动化测试的脚本验证的是产品的网络功能,调用的是 CLI (Command Line Interface)的命令接口;而应用工程师做的很多项目也是基于系统的 CLI 实现的。因此,测试工程师和应用工程师工作的目标虽大相径庭,但工作的内容和方式却并没有多大区别,不过都是用 CLI 实现测试的用例或应用的功能。而做手工测试的测试工程师工作的对象也是 CLI,不同之处仅是以手工的方式完成自动化测试无法完成或不方便完成的测试用例。因此,我一直认为,从抽象的角度来看,无论是测试工程师和开发工程师都是程序员,重要的是,测试工程师应该用程序员的方法思考问题和解决问题,象程序员一样工作。我常常发现,测试工程师在向开发工程师报告 BUG 的同时,也忙于修改自己测试脚本的 BUG。谁说测试工程师不可以是程序员呢?!推而广之,上溯到公司的执行官乃至于政府的首脑和国家的元首,不都是工作在不同的层上的领导者吗?不相信吗?记得《天龙八部》中有这样一个情节:萧峰帮助辽帝耶律洪基平判后,赐爵楚王,官封南院大王,勾兑军国大事。“萧峰虽然从来没做过官,但他久为丐帮帮主,统率群豪,自有一番威严。带着丐帮豪杰和契丹大豪,其间也无甚差别。……一切均井井有条。”丐帮帮主是民间协会的领袖,南院大王是政府机构的官职,显然是不同的两个层,相差甚远。但是以萧峰的领导力,“自有一番威严”,无论是哪个岗位,乔帮主还是萧大王,“其间也无甚差别”。这可是扯的太远了。


没有比较就没有伤害,而有差异才会有比较。假如大家认同测试工程师和开发工程师都是程序员,那么,测试工程师和开发工程师之间就很自然地谈不到高低的差别。本来嘛,程序的层就是层,无论是上层还是下层,只是抽象级别的不同,并没有什么贵贱之分。说归说,而事实上,不仅有些开发工程师常常矫情地自别于测试工程师,不同角色的开发工程师之间相轻的情况也屡见不鲜。在互联网公司,广泛地流传着这样一种说法,算法工程师最有优越感,比之前端工程师,后端工程师更有优越感。反过来讲,前端工程师想做后端工程师,后端工程师想做算法工程师。人性不过如此,在虚荣心的召唤下,这种优越感往往建立在虚幻的感觉和想象之上,自认为所工作的层具有更高的技术门槛。信有之乎?系统工程师似乎比应用工程师更有优越感。可笑可悲可叹可厌可鄙的是,竟有工程师为了自己“优越”的地位,抱残守缺,象母鸡护小鸡一样紧紧地守卫着自己的那一亩三分地儿,绝不允许他人染指。宛如多疑的皇帝,一夕数惊,日夜不安的担心别人知道了自己的那点儿微末小技儿,被取而代之。既然有技术含量这样难以逾越的壁垒,还有什么可惊可怕的呢?可见,所谓的技术门槛这玩意儿并不是什么可侍的阿物儿。我常常戏称这样的井底之蛙为“小”程序员。


包括测试工程师在内的程序员的工作是彻底的脑力劳动。最高境界的修炼内化于基于数据和逻辑的即计算机科学特有的计算思维方法,包括抽象、分析、推理、递归等;最厉害的绝招外化于解决问题的能力和技巧,如简化、分而治之、转换成已知、由具体到一般、或由一般到具体、或由一般到具体且由具体到一般分进合击等等。程序员的修养钟情于不吝于动脑筋的测试工程师和开发工程师,在设计,架构,编码和测试的研发实践中不断地升华。这就是我眼中的程序员,不区分角色,测试工程师,开发工程师和架构师,就共同的方法和技巧而言,他们都是抽象意义上的“大”写的程序员。从一般的眼光看,架构师似乎更高明一点点儿,其实,人人都可以是架构师。编码不可能不涉及架构,同样地,测试不可能不涉及架构。你象架构师一样写代码和做测试,那就是架构师,我愿意用一个三段论(syllogism)的句式总结如下:程序员即是架构师;测试工程师和开发工程师都是程序员;所以测试工程师和开发工程师都是架构师。因此,江湖中传说有一种工程师叫做全栈工程师(Full Stack Developer),十八般武艺,样样精通。从前端到后端,从系统到应用,从低层到高层,全都拿得起,放得下。写得了代码,做得了架构,干得了测试。上天入地,无所不能,宛如见首不见尾的神龙。问君何能尔?根固而木长,源深而流远,超然物外,心远地自偏,无招胜有招。而那些汲汲于一孔江山的“小”程序员的愚在于伐根以求木茂,塞源而欲流长,奚可焉?!


当然,测试工程师不一定非要精于编程之道,但必须熟稔程序员的的思维方法和解决问题的技巧,否则,只是只想只会根据开发工程师的指令亦步亦趋,甘心做个不动脑筋的操作员,如何担当得起测试工程师的职任?测试常常强调不留死角地覆盖功能的方方面面,更要求测试工程师能够从不同的角度思考问题,针对代码可能的罩门和软肋,检查合法输入,非法输入和边界输入的各种情况。鄙公司的用户,无论是数据中心网络还是企业网络,对我们研发的交换机网络操作系统的性能和稳定性的要求近乎苛刻,部署在生产网络的系统必须 7X24 小时无差错不宕机。应对这种挑战并非易事,我们必须系统地管控产品生产链的每个环节,包括需求、设计、架构、开发和测试。比如,测试用例必须系统地覆盖功能的每一个子功能点,请参考我的博客文章“用系统的方法做系统软件”。我们从事的是专业性很强的网络行业,测试工程师必须成为领域的知识专家,才有可能做到系统地测试。


朱兰博士认为,质量是产品或服务的适用性(Fitness for Use)。因此,测试工程师常常需要验证用户典型的应用案例,以确保产品适用于特定的应用场景。在此过程中,测试工程师有机会学习面向用户的广阔的应用空间,这才是实打实的实锤实战经验,更需要时间的积累。不夸张地说,开发工程师正对着“小桥流水人家”浅唱低吟的时候,测试工程师已经昂首阔步向着星辰大海启航了。因此,和开发工程师相比较,测试工程师对程序底层的深度的理解虽然有所不及,但对产品应用的宽度的把握却远远过之。假设不论编码的基本能力,对于某个特定的工业领域,正是这种宽度和深度定义了工程师团队的技术实力和技术能力,也是量度和其他工程师团队距离的最好的度规(Metric)。


诚然,研发过程中有效的组织(Well Organized)和良好的纪律(Well Deciplined)是质量的基本保证。毕竟,产品的质量取决于包含在程序中的每一行代码,而代码是开发工程师生产的,也是测试工程师验证的对象。因此,归根结底,有什么样的工程师,就有什么样的产品,好的产品质量是程序员当然包括测试工程师以自己的聪明才智创造(干)出来的。虚比浮夸,乞灵于管理流程的救赎,就好像马车跑的慢,不是打马而去打车,吾期期以为不可!

作者简介

贾彦民,目前就职于 PICA8。本科与研究生就读于重庆大学,2007 年获中国科学院软件研究所计算机软件与理论博士学位。爱读书,喜欢爬山与摄影(历史、文学、数学)。


2019-06-14 08:0010485

评论

发布
暂无评论
发现更多内容

2022中国化妆品行业发展趋势洞察

易观分析

化妆品行业

Hoo 交易所虎符研究院 ∣ 如何对NFT进行估值

区块链前沿News

NFT 虎符 Hoo 虎符交易所 虎符研究院

阿里云资深专家李国强:云原生的一些趋势和新方向

阿里巴巴云原生

阿里云 容器 微服务 云原生 趋势

系统学习 TypeScript(四)——变量声明的初步学习

编程三昧

typescript 前端 2月月更

这么写简历,offer拿到手软,从业5年的软件测试工程师手把手教你写出满分简历

程序员暴龙

软件测试 简历优化 简历 就业 软件测试工程师

关于SaaS的内容营销策略(15/100)

hackstoic

营销 SaaS平台

架构实战营模块八作业

Jude

架构实战营

梦幻联动!金蝶&华为云面向大企业发布数据库联合解决方案

华为云开发者联盟

数据库 华为云 数据管理 GaussDB(for openGauss) 金蝶

建木持续集成平台v2.2.3发布

Jianmu

DevOps CI/CD 开源项目

存储高性能、传输如闪电,焱融科技携手瑞云科技给你带来不一样的体验

焱融科技

云计算 分布式 云原生 高性能 文件存储

权威可信 | 华为云云测通过中国电子技术标准院软件测试工具能力评价

华为云开发者联盟

软件测试 测试 华为云 测试工具 华为云云测

资本热衷的垂直SaaS,如何能大有作为?

ToB行业头条

详解基于机器学习的恶意代码检测技术

华为云开发者联盟

机器学习 深度学习 静态分析 恶意代码 恶意代码检测

异步请求积压可视化|如何 1 分钟内快速定位函数计算积压问题

阿里巴巴云原生

阿里云 Serverless 云原生 函数计算 FC

几纳米间风云:手机摄影的制高点争夺战

脑极体

视频图像色彩增强的主要方法与落地实践

声网

Dev for Dev 视频技术 色彩增强

java商城源码(servlet,springboot,html,vue,uniapp,小程序,android)一套任意组合

清风

计算机毕业设计 java商城 java商城源码 商城毕业设计源码

国内外好用的OKR管理工具有哪些?

爱吃小舅的鱼

要做需求管理?看这篇就够了。

石云升

产品经理 需求管理 需求分析 2月月更

如何在 Vue 中使用 Chart.js - 手把手教你搭可视化数据图表

蒋川

Vue Vue 3

掌握这20个JS技巧,做一个不加班的前端人

华为云开发者联盟

JavaScript 数组 箭头函数 逻辑运算符 计数器对象

网络安全kali渗透学习 web渗透入门 Metasploit基本使用方法

学神来啦

如何防止Arp攻击

喀拉峻

网络安全

Vue Router 手把手教你搭 Vue3 路由 - 卡拉云

蒋川

Vue Vue 3 vue cli

亿级数据量场景下,如何优化数据库分页查询方法

华为云开发者联盟

MySQL 缓存 查询 数据表 分页查询

微服务用户为什么要用云原生网关

阿里巴巴云原生

阿里云 Kubernetes 微服务 云原生网关

安全开采数据“富矿”:隐私计算基建的融合与进击

脑极体

模块八作业

whoami

「架构实战营」

最好用的 7 款 Vue admin 后台管理系统测评 - 卡拉云

蒋川

Vue Vue 3 vue cli

学生管理系统详细架构设计

Geek_8d5fe5

架构实战营

网络安全必学渗透测试流程

网络安全学海

黑客 网络安全 信息安全 渗透测试 安全漏洞

青眼看测试_文化 & 方法_贾彦民_InfoQ精选文章