白盒测试 互联网大厂服务端测试流程

爱学习的饲养员 · 2024年09月13日 · 最后由 rongtsai123 回复于 2024年09月18日 · 4924 次阅读

大家好,我是一名服务端测试开发工程师,今天给大家讲一下服务端的测试步骤。

测试步骤概述

  • code review
  • 部署测试环境
  • 接口测试
  • 白盒测试

code review

通过 code review 可以发现 5 类错误,分别是语法错误,边界行为错误,经验错误,算法错误,部分算法错误。

1. 语法错误

这类语法错误,如果使用 IDE 环境,大多就能够直接发现,也有部分语法错误在编译阶段时会通过,而在运行阶段才能发现错误。下面有 3 个语法错误的例子:

1.1 参数少传(以下函数需要传入 2 个参数)

func test(a int,b int)(c int){
    return a+b
}

test(1)  //少传了1个参数

1.2 数组索引越界(以下数组最大索引为 2)

var arr =[3]int{1,2,3}
fmt.Println(arr[3])

1.3 未初始化数组直接使用(引发空指针异常)


//错误写法:未初始化map直接赋值
var a map[string]string
a["123"]="123"

//正确写法:
var a map[string]string
a= make(map[string]string)  //给map初始化
a["123"]="123"

2 边界行为错误

在执行代码过程中,因为边界条件,导致程序崩溃或者超时。比如经典的除 0 错误,以下代码若 b 取值为 0,那么函数就会抛出异常。

func test(a int, b int)(c int){
    c=a/b
    return c
}

3 经验错误

通过程序编写的过往经验进行判断错误。
下面的 if 语句少了一个=号,变成了赋值语句,这样 if 判断就永远返回为 true 了,这样输入非 3 的任何数字,也无法走到 else 里面的逻辑了。

func test(a int)(){

    if(a=3){
        fmt.Println("hello world")
    }else{
        fmt.Println("come on")
    }
}

4 算法错误

指当前设计的功能与预期完全不符合 比如设计一个抽奖的算法,当有 1000 人进行抽奖时,会触发大奖,但实际上 1000 人已抽奖时并没有触发大奖,这就与预期完全不符合。

5 部分算法错误

指当前设计的功能与预期部分符合,但一些特殊场景下会出现不符合的情况。

如以下的加法函数,如果数字 a 或者 b 已经超出了 int 的最大范围,则不会返回预期的结果。

func add(a int,b int)(c int){
    return a+b
}

部署测试环境

测试环境可以是一台物理机(虚拟机),也可以是一个容器。在一台物理机上分割出许多容器,说到容器,你第一时间可能会想到 docker。容器比物理机更节约空间。在互联网大厂,为了充分利用服务器的资源并适配自己公司的环境,目前都有自己的容器化解决方案。

在测试环境当中,我们需要安装一些必要的软件,比如 mysql,redis,nginx,hhvm 等。有了这些软件,我们服务端上的代码才能正常运行和进行请求转发。

完成以上步骤后,我们可以利用 git 去拉取代码,拉取代码后,需要在测试环境上部署好我们的测试代码,然后就可以开始接口测试和白盒测试了。

附上一张 git 命令速查表

接口测试

到了第三步接口测试,这一步我们可以根据研发提供的接口文档,传入指定的参数到 postman 当中调用接口,看一下返回值当中的每个字段是否符合预期。

白盒测试

在白盒测试当中,有三种覆盖率统计方式:

  • 行覆盖(语句覆盖):度量该代码行是否被测试到,这里要求最低的覆盖率标准
  • 判定覆盖(分支覆盖):度量程序当中每个判定的分支被测试到
  • 条件覆盖:度量判定中的每个条件的取值至少满足一次

如果接口测试没有问题,这并不以为着服务端测试就结束了,我们通常情况下还会进行白盒测试,特别是针对代码当中的 if 语句,循环语句。至少要做到判定覆盖或条件覆盖。

下面举一个例子 if(m>0 && n>0) 做行覆盖时,只需要执行到这条语句就行;做判定覆盖时,需要覆盖到该"m>0 && n>0" 为 true 和 false 各一次;做条件覆盖时,需要"m>0" 取 true 和 false 各一次 ,同时要"n>0" 取 true 和 false 各一次。

可见条件覆盖比判定覆盖更加严格。在测试时间允许的情况下,最好能做到条件覆盖。

下面再举两个我在实际工作当中的测试的代码示例:
例子:嵌套 if

if(!empty($a["white_list"])&&!empty($name)){
    $namelist=explode(',',$a["white_list"]);
    if(!in_array($name,$namelist)){
        echo "not in list";
    }
}

可以看到这是两个嵌套 if 的结构,如果要做到条件覆盖,我们需要设计一共 4*2 个测试 case,即 真真真,真真假,真假真,真假假,假真真,假真假,假假真,假假假。

语句1
if($a=="" && ($b !=0 || $b != 1));
语句2
if($a=="" && ($b !=0 && $b != 1));

我们再看下面这个例子,观察一下两个 if 的区别,可以看到语句 1,在变量 A 等于"" 的情况下,变量 b 无论取任何值,$b !=0 || $b != 1 返回的结果都是真。但语句 2 当中,$b !=0 && $b != 1,变量 b,如果取 1 或者 0 为假,取非 0 和非 1 的数为真。综上我们可以看出,语句 1 当中的 $b !=0 || $b != 1 无法做到条件限制,如果 if 的 body 部分是抛出异常,那么 b 取任何值,该程序都会抛出异常,这样程序就无法正常执行了。

总结

code review 其实是最先能暴露问题的环节,它要求测试人员需要有一定的代码能力才能发现问题。要想发现代码最深层次的问题,还是得进行白盒测试。

最佳回复

我更倾向于提测后功能验证前就 review,重点应该是先看代码变更影响范围,然后针对实际测试情况去针对性的看功能逻辑,对用例完整性也可以做到反补(review 更多的在前期工作,熟悉了持续迭代过程中耗费的时间会越来越小,覆盖率什么的华而不实,根本的目的在于对实现的理解以及整体的把控);还有一个是发布前检查变更是否符合预期有没有夹带私货,线上配置是否合理等等;

共收到 11 条回复 时间 点赞

有个点挺好奇的,就是 code review 这一步
除非是对开发的代码了如指掌,否则对应新增功能/新增项目进行 code review 时会不会耗时特别多?如第 1-第 4 步检查的错误,通过功能测试的边界值法、等价划分、错误推断的用例是可以进行快速验证。

但如果 code review,总感觉有点不实际,毕竟你得先去理解开发的想法、开发写代码的风格、以及引用了哪些封装的功能,这会比较耗时间。所以这一步一般是做完功能测试验证后的执行还是转测时你们测开这边直接就检查代码的?

还有第四步触发大奖的,应该大厂都是把抽奖功能单独封装成一个组件吧,然后中奖机制由不同的活动类型自己决定,抽奖组件只做概率、时间、奖品、和用户类型分类的设定。1000 人已抽奖时并没有触发大奖,这种是类型活动的设定,很多开发这里判断参与次数是否到额定值然后再发起一个抽奖请求,如果有问题,大概率是要看抽奖组件的概率配置或者抽奖组件是否判断当前角色身份异常等问题,不涉及到算法吧

白盒测试 是写单元测试用例实现的?

第一步,举例的这些容易发现的问题,都可以用静态分析工具来做,会很快

没点进来,以为是 ths,看了半天,一点都不是 ,整篇讲述的更多的是利用 code review,但实际上测试人员想要达到这种地步可想而知

我更倾向于提测后功能验证前就 review,重点应该是先看代码变更影响范围,然后针对实际测试情况去针对性的看功能逻辑,对用例完整性也可以做到反补(review 更多的在前期工作,熟悉了持续迭代过程中耗费的时间会越来越小,覆盖率什么的华而不实,根本的目的在于对实现的理解以及整体的把控);还有一个是发布前检查变更是否符合预期有没有夹带私货,线上配置是否合理等等;

耗时不会特别多,以我的经验看,CR 在执行测试之前,一个需求的代码 CR 典型时间是 1-2 个小时,但是需要这段时间保持高度的专注,并有以下作为前提:

  1. 对测试项目整体的服务架构有一些了解
  2. 对这个需求内容十分熟悉
  3. 对所使用的语言有些熟悉

要想发现比较多的问题,一般建议 CR 之前,先自己想一下如果你来实现这个需求,需要改哪些模块,怎么实现,难点在那里,然后再具体看对应实现跟你的想象做对比,查漏补缺。通常会发现一些实现逻辑不对、不全的问题。
至于偏语法、语言的错误类型,需要对使用的语言有比较高的熟悉度,知道常见易写错的点。当然,现在随着大模型普及,完全可以让 AI 做这一层的工作,实际上 AI 也能做的更好。
另外是对于经常合作的开发,应该了解他的能力和经常会写错的地方,CR 时要重点关注,这点在小公司比较普遍,大厂的研发通常不会犯很低级的错误。
CR 还会带来后续的好处,先 CR 之后,在实际测试阶段对于出现的问题定位会更加的高效,长期积累也可以提高自己的能力。

开发提测前可以对代码进行 diff 看下本次修改的逻辑,然后看下新增代码逻辑是否有问题,作为服务端测试对后台代码逻辑的掌握是基础,是肯定要熟悉代码逻辑的。至于担心拉长测试周期的问题,我觉得 CR 代码并不会增加很长的测试时间,如果对业务逻辑熟悉,CR 下新增的代码不会花很长时间,相反通过 CR 代码更容易发现一些单纯从功能层面发现不了的问题。

Bingoo 回复

单测一般是开发自测阶段写的,提测后测试人员可以通过接口测试结合覆盖率来 cover 各类测试场景是否被覆盖

berry 回复

对的

rihkddd 回复

点赞,这段写的很好,就是这个思路

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册