服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

测试左移-快速玩转Debug

日期: 来源:雷子说测试开发收集编辑:艾超


背 景


一段代码的问题产生阶段可以分为:编译期运行时

  • 编译期的代码可以由工具(idea、eclipse)在程序编码过程中提示错误,解决了语法上的标准问题

  • 运行时的代码在程序启动、运行过程中出现程序异常、逻辑异常的错误

当程序发生异常: 如返回结果不对、 没响应、抛异常、肉眼又发现不了的错误!通常这种情况我们就需要调试代码

学习的意义

QA同学通过学习debug,能够追踪代码的运行过程,快速熟悉代码实现和调用链路,扩展case的设计思路,同时从黑盒转向白盒,提高问题定位、精准case设计的能力。




玩 转 Debug


一、基本介绍

Debug视图

常用按钮

按钮

说明

备注

定位当前断点位置

用于不知道断点在哪的时候快速定位

步过:一行一行的向下运行代码,跳过方法


步入:一行一行的向下运行代码,不会走入系统类库的方法中,但是会走入自定义的方法中

自定义方法 add(),如果调用了会直接进入

强制步入:一行一行的向下运行代码,会走入系统类库的方法中,也会走入自定义的方法中

系统类库,例如.toString()

步出:跳出方法,回到调用处

和强制步入相反

回退断点:回退后可以重新观察错过的数据加载的信息

对于数据库已执行的的操作是无法回退的

运行至光标处:鼠标指在哪一行,就跳转到哪一行

用的比较少

计算表达式

使用表达式可以在断点调试阶段进行模拟操作

进入下一个断点

如果没有下一个断点,直接运行到结束

结束程序


查看当前所有断点数据


禁用所有断点


断点分类(常用断点)

1、行断点

最常用的断点方式,一般用于某个方法内部逻辑能预估的位置进行断点,可以忽略上文过程中的链路

2、方法断点

方法断点可直接作用在方法上面,如果不确定是哪个方法,可以直接断点到接口上,会自动找到对应的实现,要注意的是,接口上断点的标记是一个菱形

3、属性断点

是打在属性上的,我们无需再getter setter方法上打断点,在属性上打上断点,就会出现一个小眼睛的标志

小眼睛右键可进行设置断点的触发类型:修改和访问

日常开发或者定位赋值问题的时候,可以通过这个属性断点方式来排查

4、流断点

在使用lambda或者流操作时候,想要看见过程中做了些什么,可以通过流断点的方法,查看这个按钮即可展示视图,在每个过程中做了什么动作

二、断点设置

1、首先,我们找到需要断点的代码,根据上面断点分类,选择不同的断点类型,我们采用行断点,点击某行,进行断点标记

2、对于本地单元测试,我们可以直接点击绿色的三角箭头->选择debug运行模式

对于远程调试,我们可以选择idea右上角的小虫子,启动调试即可,和点击绿色三角箭头中的Debug Run效果一致
远程调试需要注意的要点:
  • 本地的代码必须和远程服务器运行的代码保持一致

  • 远程调试不要在生产环境进行,否则在断点未关闭的情况下,会造成服务阻塞,严重的造成线上问题

三、启动调试

我们以一个案例来演示学习Debug的意义

求1-10阶乘之和

1!+2!+3!+......+10! = 4037913

以下代码

在编译期:代码没有任何异常,但是运行结果和我们预期是不一致的,在没有日志的情况下,我们无法通过肉眼直接判断问题出在哪里,此时debug调试的作用就显现出来了

阶乘调试

1、首先,标记断点,启动调试

可以在变量区很清楚的看见目前变量的结果

2、使用【】按钮进行一步步执行

可以发现 i=1 的情况下,阶乘之和sum变量值是正确的,继续执行

3、继续【】调试,i=2的情况下,阶乘之和=3,结果也是正确的,继续执行

4、此时i=3执行,发现sum的值居然变成了15,正常的1!+2!+3!的阶乘之和应该是6此处就可以发现计算有问题,那么问题在哪呢,使用【】重新运行加载

观察i=3的情况下变量的变化

5、i=3的情况下,从图中可以看出S=2,计算2*1=2,J++再计算就是2*2=4,这里实际上就可以看出来问题,3的阶乘应该是1*2*3=6

而此处运算完结果是(2*1)+(2*2)+(2*3)=12,SUM=3,12+3=15

发现问题所在,long s =1 ,只在for循环外面定义了初始化的变量,每次都会累加而没有重置,每次计算s都是用累加的值进行计算,所以会出问题

6、知晓问题结果后,我们修改代码,增加s在循环体中的重置,重新debug运行

在i=3的时候,可以发现s变量的结果符合预期

7、释放代码,查看最终结果,和我们的预期值一致

此处也能够看出来debug调试在整个过程中排查问题、定位问题起到了关键的作用

四、调试技巧

高效debug

1、断点-【条件判断】

在代码中,经常会遇见for循环,但是循环集合可能会很大,一步步的调试到我们想要的那个下标值,执行起来非常麻烦,那么这个时候就可以运用条件判断进行断点

例如在阶乘运算中,我不想一步步的执行很多遍才进入有问题的i==3,那么我可以在for循环的循环体中进行断点,通过右键断点,设置i的条件,在满足条件时,才停在断点处,否则直接运行。如下

从图中可以很明显看出来直接debug的时候,i执行到了第三次后,才进行断点拦截,前面的都会直接执行不拦截,并且断点标记多了一个?号标记

2、断点-【表达式计算】

个人认为是idea调试里面最好用的功能,计算表达式有两个作用,都是在运行时作用

  • 查看表达式的值

  • 设置表达式的值

设置表达式的值

当前debug下,list=0,所以这个输出永远不会打印

使用表达式计算,执行list.add后,返回结果是true,同时能看见size长度变更为1

这个时候再次向下执行,即可进入for循环的循环体中进行打印

查看表达式的值

在一些复杂逻辑中,编码者会将多行代码调整为一行,提高了简洁性,但是降低了可读性,这个时候就可以使用表达式,将计算拆分出来一个个查看,可以更好的理解这一行代码表达的意思和计算的逻辑




定 位 问 题


1、在程序运行日志中,有log抛出异常,通常你可以不需要任何思考,将错误拷贝后在代码中搜索,如有多个同样的,可以根据参数和日志打印内容进行筛选

2、没有日志情况下怎么办,不知道入口处,那就只能通过抓包等手段获取请求的接口,然后在idea中查找对应的接口,在实现类的入口处进行断点;对代码有一定的阅读能力的测试,可以进行简单走读判断代码主体逻辑再进行断点标记,缩小范围

3、 在无法判断异常位置,并且代码逻辑又多的情况下,我们还可以通过多行断点标记的方式,直接配合按钮,运行会直接跳入下一个断点中,上一个断点到下一个断点中间的代码都不会步入,如下

通过该方式,可以进行代码分块的情况下快速定位问题点




总 结


Debug能力是定位问题的一个手段,能够给QA同学带来更多的实践经验

  • 提高我们对业务逻辑和数据交互流程有更清晰的认知

  • 了解基本原理和使用,拓宽设计case的思路

  • 将代码学习融入到日常工作中,理论结合实践,能够快速提高自己的代码能力




相关阅读

  • 11个JavaScript 单行代码技巧

  • 编辑整理 | 杨小爱 我们每个 JavaScript 程序员都应该学习使用 JavaScript 单行代码技巧来提高生产力,因此,今天这篇文章,我们将分享一些可以在日常开发生活中使用的单行代码技
  • 【每日一练】107—一款好玩的注册登录UI效果

  • 文 | 杨小爱写在前面注册登录的组件,在前面也分享过一些,今天我们再来看一个注册登录的UI样式效果,截图如下:为了能方便看到鼠标效果,我录了一个GIF的动图,如下:看完了实现后的效果
  • 这 7 种表现最直观的评估一个程序的水平

  • 作者 | Lokajit Tikayatray;策划 | 李俊辰;来源 | InfoQ知道这些表现,你才能在自己的程序员职业生涯中不犯相同的错误。软件行业的工作经验和你从事这个行业的工作年限直接相关
  • 学习一下 nowinandroid 的构建脚本

  • 前言nowinandroid 项目是谷歌开源的示例项目,它遵循 Android 设计和开发的最佳实践,并旨在成为开发人员的有用参考这个项目在架构演进,模块化方案,单元测试,Jetpack Compose,启动
  • Compose 动画艺术探索之瞅下 Compose 的动画

  • 本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!文章起因本篇文章为我新专栏《Compose开发艺术探索》的第一篇文章,那么为什么要写这个专

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • 测试左移-快速玩转Debug

  • 背 景一段代码的问题产生阶段可以分为:编译期和运行时编译期的代码可以由工具(idea、eclipse)在程序编码过程中提示错误,解决了语法上的标准问题运行时的代码在程序启动、运行过
  • 【测试开发】python系列教程:Python 运算符

  • 上一篇【测试开发】python系列教程:Python注释和解释器本次分享运算符。什么是运算符?举个简单的例子:>>> 4+59>>>例子中,4 和 5 被称为操作数,+ 称为运算符。Python 语言支持以
  • 【测试开发】python系列教程:数字

  • 上一篇【测试开发】python系列教程:Python 运算符本次分享数字。正文 Python 数字数据类型用于存储数值。 数据类型是不允许改变的,这就意味着如果改变数
  • 【测试开发】python系列教程:列表

  • 上一篇 【测试开发】python系列教程:字符串本次分享列表正文 序列是 Python 中最基本的数据结构。如何定义呢>>> listone=[1,2,3]>>> listone[1, 2, 3]>>> li