`
- 浏览:
9953 次
-
转自:http://blog.csdn.net/hitlion2008/article/details/7252339
前言:
这篇文章是基于Android系统定制和维护而写的,所以里面的内容与Android相关也就是说系统是Android,语言是Java,特点就是没有明确的需求行为规格定义,只有代码,很多行为也比较诡异,代码架构不是很完美,崩溃,异常比较常见(RuntimeExceptions)。虽然是基于Android的,但是方法是通用的。
什么是Bug
首先要明白什么是Bug,这点可能不同的人(测试和开发)有不同的理解,不同的公司也会有不同的标准。但是通俗的来讲,Bug就是指未预期的行为(unexpected behaviors),比如系统崩溃(Crashes),发生异常(Exceptions),或功能失常(Malfunctions),比如说点击了保存,但实际上没有保存,点击了发送却没有发送成功。
那什么又是预期行为(Expected behaviors)呢?预期行为通常是指需求说明书中规定的行为,但是很多系统(比如Android)完全没有需求或规格说明书,所以更多的时候判断的标准就是常识和经验,或与其他软件系统进行对比。比如说虽然没有需求规格书,但是通常意义上保存应该能把文件或用户所编辑的内容写进磁盘文件,如果没有成功,那行就可以认定为Bug。所以说Bug也是受主观因素影响的。
与Bug打交道的人
软件的理想情况是程序员所写的程序(算法)都是正常的,但是有理论证明这是不可能的,没有任何一个算法是完全正确的,另外只要是人就是犯错误。所以现代大多数的软件都这样来保证它的正确性,开发人员交给测试人员软件,测试人员来保证它的质量,通过测试Bug,当软件的Bug在一定的允许的范围内(小于10个)就可以认定软件已达到预期了,能正常工作并且可以发布。
在这一过程中涉及三组人:一个是开发人员,一个是测试人员,另外就是管理层。很多大公司的开发人员与测试人员都分属不同的部门。开发人员负责开发出可测试的软件版本,测试人员对软件进行测试,测试出Bug后提交给开发人员,开发人员再解决Bug。通常他们都有来自管理层的压力和绩效考核的压力,也就是说管理层对测试人员说:你要尽可能多的提交Bug,无论用什么方法,或者你每天必须提交3个Bug;另外测试人员的绩效也与其所提交的Bug数量直接相关。管理层也会对开发人员说:你要在Milestone前把所有的Bug都解掉,上个星期的Bug怎么还没解掉,你想不想干了?另外开发人员的绩效也会与Bug数量有关,如果有Open的Bug会扣新水或奖金等。
这样一来,原本比较简单清纯的关系变的就有些复杂了,无论是测试人员还是开发人员会把人的本性加进来,把政治和功利也带了进来,像测试提交了不是Bug的Bug,或是开发人员强行关闭Bug都是常有的事儿。因此,测试与开发人员便有些战争:
开发:你这不是Bug,这个行为就是这样设计的?
测试:但是这样设计很不合理!
开发:那这个要去找UX设计的人?对于行为的修改我们不能做主
测试:我不管那么多,我只管测试
开发:#%^@&$...
....
测试:你为会么关我的Bug
开发:因为它无法复现
测试:但当时我的确是遇到了
开发:那你再复现出来吧
测试:@#$%^...
Bug的常见分类
如前所说Bug就是未预期的行为。所以Bug常见的类型有:崩溃(Crashes),异常(Exceptions),功能失常(Malfunctions),差劲的用户体验(Bad user experiences),未实现的行为和功能。
Bug的复现机率
这个是特别是值得注意的,首先Bug描述上面写的复现机率只是测试人员在当时的现场Bug出现的机率,另外这个也是比较主观的,比如试了三次出一次,有的人认为是必现的,也有的人认为是有一半机率(Above 50%)。
但是经过这几年解Bug总结的经验发现,真正的随机出现的Bug只有与线程时序有关的逻辑才会有。其他的随机Bug并不是随机,只可能是测试不太清楚操作步骤和所有的数据或当时的环境现场。
如何解决Bug
1.弄清楚Bug究竟是什么样的问题
拿到Bug后,不要着急去复现,首先要弄明白Bug究竟涉及到哪些行为,哪些操作,当时的现场和环境是什么样的,用了什么样的数据,操作到哪一步出现了问题等等。因为测试人员对Bug的描述是很主观的,可能不太清楚,所以就要与测试人员进行沟通,弄明白这些问题:
当时的配置,环境,现场是什么样子的?
涉及到哪些行为?
进行了什么样的操作?
操作到哪一步出现了问题?
出现了什么问题?
如果说是功能失常,或差劲的用户体验或未实现的行为,那么测试所期待的行为又是什么样子的?
测试人员有没有附上日志,截屏或其他调试信息。
2.如果Bug是崩溃或异常
先不要忙着去复现,因为对于崩溃和异常,日志当中肯定会有崩溃和异常的直接相关信息,通常这就能定位出问题,比如对于Java语言来说如果出现未Handle的异常,那么日志中肯定会有异常相关的信息调用栈等。所以通过日志文件就可以定位出问题出现的源代码。这样就多了一个线索,因为你可以通过源代码来推测是什么导致了这个异常,可能做了什么操作,环境现场发生了什么变化等,通常来讲这比测试人员提供的信息更有参考性。
3.如果是差劲的用户体验或是未实现的功能
这个要与测试人员进行沟通,甚至是与管理层和设计者进行沟通,如何修改行为或如何实现行为,并且什么时候进行修改等,通常这个开发人员是没有决定权的。
4.尝试复现Bug
这个步骤也是很有必要的,因为即使你修复了Bug,也是需要复现Bug来进行验证以保证你真正的修复了。所以,如果无法复现Bug那么就说不清是因为一直都没有复现还是被你修复了。
如前所述,如果你完全掌握了Bug所发生的条件,相关的操作步骤,那么复现Bug应该很容易,相关的操作步骤应该Bug描述都会有,但是Bug的相关条件(环境,配置,上下文和数据)这些东西可能要去挖掘才能知道,因为测试可能没有注意,也可能忘记添加到Bug描述中去,所以为什么第一步是弄清楚问题。
如果是真正的随机问题,那肯定是与线程时序相关的,对于这类问题,发生的原因通常是线程应用不当,产生的Bug也相当的隐蔽。对于这类问题的复现方法是,找到相关的代码逻辑和线程,进行人为的干预,以加大问题出现的机率,比如可以用Thread.sleep()来阻塞线程,以让其以某种特定的时序来运行,以加大Bug复现的机率。
另外,如果难以完全复制Bug出现的条件,比如特定数据或特定的条件等,也可以通过修改代码来实现,比如某一逻辑只有当对象为空的时候才会进,但是99%的情况下它都不为空,且没有合数据让它为空,那么就在代码中直接用空的对象,以复现Bug。
5.迭代:猜测问题并定位问题
这一步的目的就是定位出问题究竟出现在哪一个源文件,哪一行或哪一逻辑中。当然,这一步要建立在Bug能复现的基础上。
定位问题也有很多方法,比如设断点调试,添加日志,一个很常用的方法是加上Thread.dumpStack(),以了解函数的逻辑调用关系。这个主要与软件的类型和开发环境有关,很多软件系统无法进行实时的调试。所以添加日志文件是最通用的方式。
6.迭代:修复问题并进行验证
如果定位出问题了,就可以进行修复,有些问题可能容易修复,有些问题可能比较复杂,这要视具体的软件和具体的问题而定。还有可能是,特别是那些没有需求规格的软件,会发现代码本来就是这样子工作的,这时就要与管理层和测试和设计者讨论这到底算不算Bug且要不要修复。当然最悲剧的就是发现引发这个Bug的原因是系统的架构设计不合理导致的,这个时候就只能用其他方法而不是修改整体架构设计了,当然这个是前期设计造的孽,是否要改要看管理层了和时间预算允许不允许了。
这也是一个迭代过程,进行修复和验证,直到Bug被完美的修复。也就是说Bug被修复,所做的修改最小,且不会引发其他的Bug。
7.提交CodeReview并进行CodeReview
像开发一样,解Bug也是开发周期的一个部分,所以为了质量最好还是要进行CodeReview。
Review的目的就是让修改达到最小,且不会引发其他问题。为什么让修改最小,因为你改的越多,产生的影响也就越多,如果没有足够的单元测试来验证,那么引发其他问题的可能性就越大,所以对于修复Bug来讲,修改越少越好,改动的代码越少越好,修改的文件越少越好。(当然,最理想的情况是不用修改代码也能把Bug给解了^_^)。
8.提交Patch和关闭Bug
这个是解Bug的最后一步,但是也要小心,特别是对于公司所用的开发工具和版本管理工具不熟悉的人,一定要小心,因为即使你的Patch已达到最优化,但是如果在Checkin代码时发生了问题,那就是悲剧中的悲剧,如果引起了Build error那就等着挨骂吧!
要注意的是把所有的改动都提交到版本控制中去,为了以防万一,在提交之后最好再从版本中拉出来编译验证,一是看是否有Build error(通常是由于提交不全导致的),二是看是否有漏提交(结果就是Bug没有解掉)。
总结
在《The Practice of Programming》(《程序设计实践》)有一句关于解Bug的话说的很好:Debugging involves backwards reasoning, like solving murder mysteries. Something impossible occurred, and the only solid information is that it really did occur.(解Bug/调试需要逆向推理,就像侦破离奇的谋杀案。貌似不可能的事情发生了,而且唯一确定的线索是它的确发生了)。仔细品味这句话,解决Bug的过程的确是这样。我们拿到是就是Bug---一个结果,不断的尝试寻找线索,推敲去寻找它的原因,找到了原因了后再想办法修复它,我们是二十一世纪的福尔摩斯,我们是软件工业中的柯南。回头再看那些解决掉的神奇的Bug,与福尔摩斯破案后的感觉类似,也有相当的成就感和自豪感。
后记:
关于解Bug有一本经典的书《The Science of Debugging》(《程序调试思想与实践》),这本书写的相当的实在,内容以Bug为主题,覆盖了解Bug所需要的所有话题,内容详实,完全是作者几十年作为Debugger的总结。在我看来这本应该与《代码大全》之类的平起平坐。感兴趣的朋友不妨读一读。
[size=medium][/size]
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
微软在软件测试领域有着丰富的经验和成熟的方法论。其中第一类测试是按照严格的步骤来进行的,主要包括以下几个方面: 1. **需求和设计评审**: - 测试人员与开发团队紧密合作,在需求和设计阶段就开始介入,确保...
该模式将页面对象抽象成一个独立的模块,用于存储页面的元素和操作,实现测试用例的解耦合。 四、自动化测试的实现过程 本文中,我们使用 Selenium 实现了自动化测试,主要包括以下步骤: * 环境搭建:安装 ...
创作背景:当前的数学教育环境下,更强调的是数学素养的提升,本程序提供了一个免费的数学益智小游戏的学习和训练平台,旨在提升...V1.1.2 优化了已知bug,修复UI V1.2.0 更新系统算法,修复了随机盘面可能无解的问题
- **排序算法**:在某些情况下可能需要对棋局进行评估,此时排序算法(如快速排序)可以帮助我们快速找出最优解。 ##### 2.3 设计模式 在软件工程领域,设计模式是一种被反复使用、多数人知晓的、经过分类编目的、...
发掘问题的关键在于识别那些导致困扰或不满的异常现象,无论是软件中的bug、硬件的故障还是流程上的瓶颈。通过全员参与的脑力激荡,鼓励团队成员提出他们遇到的问题,无论大小,以确保无遗漏。 第二步:选定题目 从...
3. **测试与调试**:确保应用程序的功能正确性,优化性能,并修复任何潜在的bug。 4. **部署与维护**:将应用程序发布到服务器,供用户访问,并持续监控其性能,进行必要的更新和维护。 ### ActionScript语法 ...
他强调了测试在敏捷开发中的重要作用,提出了一种敏捷测试方法论,支持了快速迭代和持续交付。 #### 题目:软件自动化测试系统的研究与实现 陈哲的论文介绍了软件自动化测试系统的研究与实现。他设计了一套自动化...
28. **理解指针概念**:掌握指针的基本用法,包括指向与解引用操作。 29. **避免内存泄漏**:学会管理动态分配的内存,防止内存泄漏发生。 30. **熟悉文件操作**:掌握文件的打开、读取、写入等基本操作。 31. **...
4. **博弈论**:一些题目涉及到玩家之间的策略选择,如题目1425交叉配对、1148游戏、1161钓鱼等,这些需要理解博弈论的基本概念并构建相应的算法模型。 5. **组合数学与概率**:例如题目1092自我数、1192特性不是...
- 再者,保持软件更新,以获得最新的功能和修复的bug。 - 最后,合理使用下载工具,避免过度下载导致账号受限或服务器压力过大。 总的来说,"读秀下载器"是一款针对"读秀"平台定制的高效工具,它简化了文献获取步骤...
- **1192 It's Not a Bug, It's a Feature!**: 特征识别问题,需要对输入数据进行有效的解析与处理。 - **1196 Fast Food**: 快餐配送问题,涉及图论中的最短路径算法。 - **1107 Fat Mouse and Cheese**: 贪婪的...
1. **软件开发**:开发人员可以利用Merge对比代码差异,定位bug,以及解决合并冲突,提高代码质量。 2. **文档编辑**:编辑团队在协作过程中,通过Merge可以方便地比较不同版本的文档,找出并整合更改内容。 3. **...
mkdir data 下载原始数据集 , , ,然后将其解压缩到以下目录下ABMT/examples/data├── dukemtmc-reid│ └── DukeMTMC-reID├── market1501└── msmt17 └── MSMT17_V1(or MSMT17_V2)安装HMR进行网格...
电梯问题在IT行业中通常涉及到自动化...每个环节都需要专业知识和实践经验,而分析过程可能涵盖了从硬件故障诊断到软件bug修复,再到系统优化的全过程。通过持续的分析和测试,可以不断提升电梯系统的效率和安全性。
2. **解压文件**: 使用解压缩软件(如WinRAR或WinZip)打开下载的压缩包,提取出其中的安装文件。 3. **运行安装程序**: 双击解压后的安装文件,按照提示完成安装过程。通常会有一个向导引导用户进行安装,包括选择...
所以我读了一些[Noam Brown](https://noambrown.github.io/)的工作,他确实在限制下注的德州扑克中,从博弈论的角度严格证明的得到了数学最优解(纳什均衡),并且在可接受的时间内做了实现,《Science》封面大神。...
6. **数学应用**:许多Codeforces问题涉及到数学概念,如数论、组合数学、概率论等。参赛者需要利用数学知识来简化问题,建立模型,并设计算法。 7. **调试与测试**:"a.out"通常是编译后的可执行文件,参赛者会...
3. **流程优化与推动**:通过引入敏捷开发方法论或其他最佳实践,持续改进开发和测试流程,提高整个团队的工作效率。 #### 四、如何获得认可 1. **效果显著**:通过实施上述措施,必须能够带来实实在在的质量和...
从需求入手,逐步细化到系统架构、数据库、界面和功能模块设计,再到实际开发和测试,最后探讨系统的部署与长期维护策略。 2.1 系统需求分析 系统需求分析包括功能需求和非功能需求。功能需求涵盖用户注册登录、...