想做软件测试工程师,这7件事你必须先知道

news2024/11/16 21:55:42

目录

一、“开发者测试” 就是“开发者来测试”

二、没有什么测试不可以“自动化测试”

三、开发者测试”利在当下“,”赢得未来“

四、TDD不是必须先写测试代码

五、UT覆盖率100%真的很不好

六、用测试来驱动架构和代码质量

七、从“我要写测试依赖代码”到“我要写测试依赖代码”

总结:


一、“开发者测试” 就是“开发者来测试”

开发者测试是现代软件工程中非常重要的一环,敏捷开发、主干开发这些先进的项目管理方法和流程都基于完善的开发者测试。当每个月甚至每周都要交付一个版本时,不可能投入大量的测试工程师来进行大规模的系统级别测试,这时候就需要把整个测试金字塔中的绝大部分测试通过自动化来完成。

我们今天谈开发者测试,什么是“开发者测试”? 我司有清晰的开发与测试之分。写代码归开发攻城狮,测试归测试攻城狮,大部分情况下双方处于“红蓝对峙”状态。这与我10多年前的研发团队状况非常相似。而现在的软件工程,专职的“测试攻城狮”非常少,很多公司开发测试比例大于10:1,甚至一些部门没有测试攻城狮一说。 而测试攻城狮的角色不再是手动跑测试用例的“苦力”,而是管理产品的测试系统,对产品测试进行规划、分析归纳功能测试思维导图、设计测试用例及带领研发团队进行测试工作,更像一位“测试专家/测试教练”。举个简单的例子,我之前做的产品是在线视频会议协作产品。我们每天的线上例会就是用自己做的产品,而且会使用自己开发的新功能测试站点来开“站会”。除了花少量的时间做dialy update,然后就是测试专家带领团队(包括PO、架构师、SM、Dev)按照计划来进行集中(半个小时)的测试。所以说“开发者测试”就是“开发者来测试”,而我们传统的众多测试工程师面临三种出路:成长、转型、淘汰。“测试专家”在项目中的话语权也很高,我之前的公司使用主干开发,有个“一进一出”的评审,团队的这种类型的“测试专家”有一票否决权。甚至在公司有PE级别的测试专家(相当于我司20-21级的技术专家)。

  • 一进:对于一个功能是否能够进入release branch,在release branch打开feature toggle进行发布级别的测试。
  • 一出:在engineer release时,该功能质量合格,允许feature toggle进入产线。

二、没有什么测试不可以“自动化测试”

回到测试金字塔,从测试的"开发成本"、“执行成本”、“测试覆盖率”、“问题定位”四个维度来看,基于代码级别的白盒测试是及其重要的。

  • 开发成本: 实现测试用例的成本。
  • 执行成本:运行一次测试用例的成本。
  • 测试覆盖率:我们通常所说的line coverage和branch coverage
  • 问题定位:测试出现问题,定位问题的效率

通过测试金字塔及其四个测试维度评估,我们可以得出:

  • 尽可能地多做Low Level Test :因为他们的执行速度相较于上层的几个测试类型来说快很多且相对稳定,可以一天多次执行。一般来说,LLT灰做到持续集成构建任务中去,甚至在MR中执行,保障进入代码仓库的代码质量。
  • 在自动化保障的情况下,执行一定规模的IT、ST、UI Test:因为他们的执行速度较慢,环境依赖较多,测试先对不稳定。通常在夜里执行一次,阶段性的检查代码质量,反馈代码问题。
  • 尽可能地少做大规模的手动测试:因为他们的执行速度相较LLT且不够稳定,人力成本较高,也无法做到一天多次执行,每次执行都要等很久才能获得反馈结果。但是,他们更贴近真实用户场景,所以要确保一定周期内或者关键节点时间执行以下这几个测试以确保软件质量。

现在很多公司已经迭代发布的周期越来越短,甚至做到了2周。手动测试显然无法适应这种开发模式,而把手动测试的用例通过各种技术方案自动化是唯一途径。代码层面,从底层业务代码到UI代码,只要架构设计合理,都是可以做UT。最顶层的UI交互测试,测试用例也是可以自动化运行(大部分UI框架都可以通过accessibility的接口进行UI自动化测试),试想连咱们手机硬件都可以自动化测试“摔手机”这种极端测试,软件有啥做不到?至少有些业界技术大牛公司的某些产品,从代码提交Merge Request,到产品上产线是可以以天来计算的。这种产品的测试是不会也不可能通过手工测试来完成的。

三、开发者测试”利在当下“,”赢得未来“

很多人都认为底层的开发者测试,花了大量的时间,写了大量的代码,然后来保证功能的正确性,但是每次代码功能或者结构的的变更都要修改测试代码。我手动调试和验证效率更高。的确通过UT,API测试来调试代码与自己手动运行调试区别不大,但是通过开发者测试对代码进行调试,从而保证当前项目迭代的质量;但是其更重要的作用不是这个。

我们在bug分类中有这样一些名词 : Build Regression Bug, Release Regression Bug。

  • Build Regression Bug : 开发中同样的功能在新版本出现一个bug,但是在之前的版本没有这个问题,我们叫做Build Regression Bug.
  • Release Regression Bug : 产线上同样的功能在新版本出现一个bug,但是在之前的版本没有这个问题,我们叫做Release Regression Bug.

我们每次commit到产品中的代码,没有人可以保证其100%不会出现问题,在敏捷开发的这种快速迭代下,不太可能进行全功能的手动测试,所以开发者测试,特别是底层的UT、API测试、集成测试,能够很容易的识别发现这类问题。所以说开发者测试”利在当下“,”赢得未来“。

四、TDD不是必须先写测试代码

对于TDD,大家的认知是先写测试代码,再在写实现代码,这个说法对也不对。概念上没错,但是如果严格这样做,效率未必最高,这也是TDD很难推广的原因之一。我们把编码实现分成3个部分:实现代码、测试代码、调试代码。按照TDD的概念时先写测试代码、然后编码,最后调试。我们通常在代码实现时,一开始不大可能考虑的非常清晰,把接口定义的完全准确,如果严格按照测试、编码、调试来做,测试代码要随着编码频繁修改。 当然这本身不是什么大问题,在实际执行过程中,很多人习惯先搭好代码框架、测试框架,然后在编码,测试。等测试完成后在进行调试。所以从华为灰度管理的角度上来说,只要单元测试在调试之前,都可以称作TDD开发模式。BTW,当然现在开始流行BDD,这里想说的是如果连我说的TDD都做不到的团队,就不要考虑BDD了。

(Behavior-Driven Development:BDD将TDD的一般技术和原理与领域驱动设计(DDD)的想法相结合。 BDD是一个设计活动,您可以根据预期行为逐步构建功能块。 BDD的重点是软件开发过程中使用的语言和交互。 行为驱动的开发人员使用他们的母语与领域驱动设计的语言相结合来描述他们的代码的目的和好处。 使用BDD的团队应该能够以用户故事的形式提供大量的“功能文档”,并增加可执行场景或示例。 BDD通常有助于领域专家理解实现而不是暴露代码级别测试。它通常以GWT格式定义:GIVEN WHEN&THEN。)

五、UT覆盖率100%真的很不好


于单元测试,我们都会关注一个指标“覆盖率”。不管模块、函数、行、分支覆盖率,必须要有一定比例的覆盖率。但是每一项你都做到了100%,那么会给你打“差评”。不是说你做到不好(这里不谈是不是用了正确的方式),而是成本和性价比问题。以最难达到的分支覆盖率(branch coverage),如果要做到100%的覆盖率,有些内存分配或者容错保护的分支都必须测试到,那么你的测试用例考虑要翻倍,但是并没有带来的相应价值。甚至一些代码条件分支在程序运行的生命周期内都没有被执行过。

  • 模块覆盖率:业务模块代码通过UT,架构模块代码通过IT;就从UT的覆盖率的角度上去看,不需要去测试架构代码。
  • 函数覆盖率:不要为一些无任何逻辑的代码去写UT。比如我们有些函数就是get/set一个属性,内部实现就用一个变量来赋值保存。这种函数写UT就是为了覆盖率而写,没有任何真正的意义。
  • 行覆盖率:通常来看平局80%上下的行覆盖率是一个合理的指标,有些可以为0%,而有些需要100%,如果全部代码都超过90%,其成本较高,效率较低,不建议这样做。
  • 分支覆盖率:越复杂的业务逻辑,越要写更多的测试用例来覆盖,而一些内存分配出错逻辑判断可以不需要测试。

六、用测试来驱动架构和代码质量

这里谈测试驱动架构和代码质量,主要说的是让代码具备完善的可测试性,什么是代码的可测试性?简单的说就是类与类之间,模块与模块关系解耦,类与类,模块与模块通过接口编程。依赖的接口通过被动注入式传入,而不是主动获取式。对于程序正常运行时,所传入的接口参数是真实的业务对象,而做测试时,可以传入fake的模拟实现。当然不是所有的依赖模块都这样做,一些与业务无关的Utility Library,或者一些特定的数据对象实现,可以直接调用。

这里我们讲到了fake与mock,关于Test Doubles,基本上的概念如下,具体每种代表什么意义,大家可以自行上网搜索

  • 虚拟对象(dummy)
  • 存根(stub)
  • 间谍(spy)
  • 模拟对象(mock)
  • 伪对象(fake)

当前我司大家在做开发者测试时,基本上都在用Mock Object(实际上在用的过程中,很多是在用入参返回值控制的Stub)。抛开概念上的问题,虽然通过Mock的方式也是可以测试代码,但是实际上用Mock基本上意味着我们的代码关联性较强,模块显示依赖较重,模块移植性较差,特别是C语言编程这种问题特别多。以至于现在很多模块根本无法开展单元测试,更多的是在做集成测试。

为什么会出现这种情况? 我们的高级别的架构师更多的在考虑系统级别的架构设计,把系统模块,各个应用之间的关系梳理的非常清晰,通常情况下,高级别的架构师可以把系统模块或应用之间的关系设计的较为合理。然而到了具体的应用业务内部的设计与实现,交给了低级别的架构师来完成。实际上这些模块内部的代码量并不小,很多都是几十万行甚至上百万行的代码量。这时候架构师的水平决定了代码的Clean Code质量。我司目前代码上的问题很多不是系统架构的问题,而是具体业务实现中,缺少严格的要求和合理的架构设计。如果在应用级别有一套架构方案来规范,那么至少在模块的接口以及模块与模块之前的交互上也能达到和系统设计一样较为清晰合理。那么不确定的部分就时每个子模块内部几千上万行的代码部分。

之所以提出用测试驱动架构和代码质量,当给测试提出一个很高的标准时,大家不得不从架构上去解决测试的问题,当测试的问题解决时,Clean Code L3自然而然就达到了。

七、从“我要写测试依赖代码”到“我要写测试依赖代码”

这句话看着很奇怪,实际上是从根本上去解决单元测试的根本方法。 模块之间有依赖,不管是通过Mock还是Fake的方法,不管架构上如何合理,这种依赖是不能消除的,我们做到更多的是合理的设计让依赖与模块解耦。第一个“我要写测试依赖代码”,指的是当我实现我的模块时,我要写测试代码来测试。而然我要考的是如何写我的测试依赖。而第二个“我要写测试依赖代码”指的是,当我实现我的代码时,我要考虑的是依赖我的模块在测试时,对于我的依赖该怎么解决,"我要写测试依赖代码”(就是我说的fake对象与实现)来帮助依赖我的模块解决测试依赖问题。

  • 思维转变、测试驱动:开发一个模块,不要先考虑怎么测试自己,先考虑如果别人依赖我,我该怎么让别人更容易测试。模块的提供者,不止要提供模块代码,还要提供一个可复用的Faked对象(调用验证;返回值;参数验证;参数处理;功能模拟等)。
  • 模块代码的编写者实现自己的Fake实现,基本上大部分的代码是由模块编写者来完成,同时这是一个可复用的Fake实现。模块依赖方根据自己一些特殊的业务需求来添加自己的代码。基本上遵循80/20原则。
  • 架构上依赖解耦,通过注入依赖的方式进行接口编程。开发者测试使用Fake来实现依赖。
  • 当编写测试代码时,所有依赖的接口、依赖的实现都基本完成,更多的关注些测试用例而不是测试依赖。

总结:

感谢每一个认真阅读我文章的人!!!

我个人整理了我这几年软件测试生涯整理的一些技术资料,包含:电子书,简历模块,各种工作模板,面试宝典,自学项目等。欢迎大家点击下方名片免费领取,千万不要错过哦。

   Python自动化测试学习交流群:全套自动化测试面试简历学习资料获取点击链接加入群聊【python自动化测试交流】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DhOSZDNS-qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=198408628

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在iPad上轻松做笔记和绘画,西圣Pencil上手

触控笔是一种提高工作学习效率的方便工具,尤其是和平板搭配使用。但是iPad的Apple Pencil价格昂贵,不适合学生等经济条件有限的用户,所以他们需要寻找一些性价比高的国产替代品。我最近用了一支国产的电容触控笔,叫做西圣Pencil触…

[C++] C++11新特性分析介绍(1): 列表初始化、右值引用、完美转发、移动语义...

文章目录 [toc] C11介绍统一的列表初始化 {}initializer_list新的声明autodecltypenullptr 范围for智能指针STL 新容器**右值引用 ****容器中 另外的右值引用 **万能引用与完美转发 ****新的类功能新默认成员函数强制生成默认函数的关键字 default禁止生成默认函数的关键字 del…

【网络安全】带你了解什么是【黑客】

文章目录 背景定义分类白帽黑客(White Hat Hacker)黑帽黑客(Black Hat Hacker)灰帽黑客(Gray Hat Hacker) 黑客文化伦理问题黑客常用的攻击手段黑客攻击用户的常用策略有以下这些:防御黑客攻击的…

[Android 13]Binder系列--获取服务

获取服务 hongxi.zhu 2023-7-8 一、客户端发起获取服务 以SurfaceFlinger进程中获取InputFlinger服务为例 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger"…

Redis+IDEA极速了解和实现单机锁和分布式锁

单机下&#xff1a; 只适用于单机环境下&#xff08;单个JVM&#xff09;&#xff0c;多个客户端访问同一个服务器 1.synchronized package com.cloud.SR.controller;import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.cor…

跟我一起从零开始学python(六)数据库编程:MongoDB数据库

前言 回顾之前讲了python语法编程 &#xff0c;必修入门基础和网络编程&#xff0c;多线程/多进程/协程等方面的内容&#xff0c;昨天和今天讲到了数据库编程篇MySQL&#xff0c;Redis今天第三篇MongoDB篇&#xff0c;前面没看的也不用往前翻&#xff0c;系列文已经整理好了&a…

多线程与并发编程【线程对象锁、死锁及解决方案、线程并发协作、生产者与消费者模式】(四)-全面详解(学习总结---从入门到深化)

目录 使用Class作为线程对象锁 使用自定义对象作为线程对象锁 死锁及解决方案 线程并发协作(生产者/消费者模式) 实现生产者与消费者模式 使用Class作为线程对象锁 语法结构&#xff1a; synchronized(XX.class){//同步代码} 或 synchronized public static void access…

【大语言模型】LLM应用程序的新兴体系结构

LLM应用程序的新兴体系结构 LLM应用栈设计模式&#xff1a;In-context learningData Preprocessing/EmbeddingPrompt Construction/RetrievalPrompt Execution/Inference What about agents?展望参考资料 大型语言模型是构建软件的强大新基元。但由于它们非常新颖且与常规计算…

css写法、颜色显示方式

一、什么是css 二、css的几种写法 1、行内样式 css写在标签的style属性上&#xff0c;优先级非常高&#xff0c;但是有多个标签具有相同样式代码重复高 2、页面样式 此时写在head&#xff08;不可见&#xff09;中&#xff0c;用style标签 3、外联样式 css样式也可以导入 一…

C++primer(第五版)第十六章(模板与泛型编程)

16.1定义模板 关于模板,第一个要提的点就是,这个字念mu模板而不是mo(一开始打字就发现拼音错了,突然觉得自己要会小学深造一下). 模板就是将一个特定场合使用的东西变成可以在多个场合使用的东西. 16.1.1函数模板 template<typename T> bool bijiao(T &a,T &…

了解 IPNS:我们可以使用 4EVERLAND IPNS Manager 做什么?

关键词&#xff1a;4EVERLAND、IPNS、4EVERLAND IPNS 管理器、去中心化内容 IPNS 是星际名称系统的缩写&#xff0c;是一个允许我们在 IPFS&#xff08;星际文件系统&#xff09;内创建可变指针以及名称和地址内容的系统。IPFS 使用内容标识符 (CID) 作为唯一文件标识符&#…

Photoshop制作Alphas(没有显卡好痛苦,两个MAYA交替弄)

做个选区&#xff0c;选白色 擦除背景 在把背景填充上白色

【PyGIS】GDAL及Rasterio多线程转换NC格式文件为TIFF

汇总 【GIS】使用cdsapi下载ERA5和ERA5_land逐小时数据 NC格式介绍 说明 NC文件读取使用netCDF4,NC文件转换为TIF使用rasterio或者GDAL。 一些细节: 格点数据转换为TIFF文件时候,计算六参数时候,应该要考虑,格点数据存储的坐标属于栅格中心点的位置,转换为TIFF时候,…

Java----使用eureka进行注册连接(微服务简单实现)

当采用微服务架构时&#xff0c;各个业务流程被逐一分解&#xff0c;虽说是分解&#xff0c;但还是要进行连接的&#xff0c;最简单的就是使用http请求&#xff0c;将他们联系起来&#xff0c;通过给容器注入restTemplate&#xff0c;然后使用内置的方法进行请求&#xff0c;但…

基于Javaweb实现ATM机系统开发实战(四)用户修改删除功能实现

我们点一下修改&#xff0c;发现页面进行了跳转&#xff0c;跳转到了/toUpdate&#xff0c;并传递了用户的卡号。 我们可以先查看一下用户列表展示界面的前端代码&#xff1a;userlist.jsp&#xff0c;可以看到前端代码中做了跳转的动作&#xff0c;我们需要在后端中完成相应的…

VectorCAST单元测试参数配置

一、打开 VectorCAST 通常情况下&#xff0c;技术人员会配置一个脚本文件&#xff08;.bat、.cmd&#xff09;&#xff0c;用户可以通过这个脚本文件来启动 VectorCAST。使用脚本文件启动 VectorCAST&#xff0c;可以在启动时设置好编译器相关的环境变量&#xff0c;方便 Vecto…

企业毛利高,进项抵扣少,增值税高,怎么办?

企业毛利高&#xff0c;进项抵扣少&#xff0c;增值税高&#xff0c;怎么办&#xff1f; 《税筹顾问》专注于园区招商、企业税务筹划&#xff0c;合理合规助力企业节税&#xff01; 金税四期的出现&#xff0c;让很多企业都陷入了税负重的不利局面。当然了在此环境之下&#x…

回溯法总结

文章目录 回溯法如何理解回溯法 回溯算法模板框架如下&#xff1a;树枝去重树层去重回溯法去重什么时候去重&#xff1f;树层去重数组used[i-1]&#xff1a;回溯函数的参数startIndex&#xff1a;回溯函数的参数用Set的对象uset&#xff1a;局部变量例题 其它细节对于组合问题&…

测试开发知识图谱

目录 前言&#xff1a; 1 测试方法与理论 2 Shell脚本相关 3 数据库相关 4 git 代码管理 5 Python 编程语言与测试框架 6 Web 自动化测试 7 移动端 app 自动化测试 8 常用开源测试平台 9 客户端专项测试 10 服务端接口测试 11 服务端接口自动化测试 12 服务端性能…

国产CAN收发器XL1050可替代NXP的TJA1050T,性能参数基本一致

CAN收发器是CAN控制器和物理总线之间的接口&#xff0c;在工控等需要CAN通信的应用场合是必要的&#xff0c;工程师通常采用NXP、TI等品牌的&#xff0c;TJA1050T是常见型号之一。XL1050是信路达一款CAN收发器&#xff0c;本文讨论信路达的XL1050 替代NXP的TJA1050T的可行性。 …