《软件测试的艺术》读书笔记(第三章)

第三章:代码检查、走查与评审

前言:
多年以来,软件界的大多数人都持有这样一个想法,即编写程序仅仅是为了提供给机器执行,并不是给人们阅读的,软件测试的唯一方法就是在计算机上执行它。20世纪70年代早期,一些程序员最先意识到阅读代码对于构成完善的软件测试和调试手段的价值,通过他们的努力,原有的观念开始发生变化。
今天,并不是所有的软件测试人员都要阅读代码,但是研读程序代码作为测试工作的一部分,这个观点已经得到了广泛认同。
因此,我们在基于计算机的测试技术之上提出了人工测试技术

[3] [1] 代码检查

代码检走查以及可用性测试是三种主要的人工测试方法。这些测试方法可以应用在软件开发的任何阶段,包括一个应用程序编码基本结束或者每一个模块(单元)编码结束之后。

所谓代码检查就是以组为单位阅读代码,然后进行以下两条活动:

  1. 由程序编码人员逐条讲述程序的逻辑结构。在讲述过程中,小组的其他成员应提问题、判断是否存在错误。在讲述过程中,很可能是程序编码人员本人而不是其他小组成员发现大部分错误。换句话说,对着大家大声朗读程序,这种简单的做法看起来是一个非常有效的错误检查方法。
  2. 参考常见的错误编码列表分析程序(错误列表将在下一节中介绍)。

代码检查的衍生功效

  1. 程序员通常会得到编程风格、算法选择及编程技术等方面的反馈信息。
  2. 其他参与者也可以通过接触程序员的错误和编程风格而同样受益匪浅。
  3. 代码检查能够尽可能早的返现程序中脆弱的部分。

[3] [2] 用于代码检查的错误列表

代码检查过程的一个重要部分就是对照一份错误列表,来检查程序是否存在常见错误。

该错误列表很大程度上是独立于编程语言的,也就是说,大多数错误都可能出现在任意语言编写的程序中。

[3] [2] [1] 数据引用错误

  1. **是否有引用的变量未赋值或未初始化?**这可能是最常见的编程错误,在各种环境中都可能发生。在引用每个数据项(如变量、数组元素、结构中的域)时,应试图非正式地“证明”该数据项在当前位置具有确定的值。
  2. 对于所有的数组引用,是否每一个下标的值都在相应维规定的界限内?
  3. 对于所有的数组引用,是否每一个下标的值都是整数? 虽然在某些语言中这不是错误,但这样做是危险的。
  4. 对于所有的通过指针或引用变量的引用,当前引用的内存单元是否分配? 这就是所谓的“虚调用”(dangling reference)错误。当指针的生命周期大于所引用内存单元的生命周期时,错误就会发生。当指针引用了过程中的一个局部变量,而指针的值又被赋给了一个输出参数或一个全局变量,过程返回(释放了所引用的内存单元)结束,然后程序试图使用指针时,这种错误就会发生。与前面检查错误的方法类似,应试图非正式地“证明”,对于每个使用指针值的引用,引用的内存单元都存在。
  5. 如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区域中的数据值是否具有正确的属性?
  6. 变量值的类型或属性是否与编译器所预期的一致? 当C、C++程序将某个记录读到内存中,并使用一个结构来引用它时,由于记录的物理表示与结构表示存在差异,这种情况就可能发生。
  7. 在使用的计算机上,当内存分配的单元小于内存可寻址的单元大小时,是否存在直接或间接地寻址错误? 例如,某些条件下,定长的位串不必以字节边界为起点,但是地址又总是只想字节边界的。如果程序计算一个位串的地址,稍后又通过该地址引用这个位串,可能会指向错误的内存位置。将一个位串参数传递给一个子程序时,也可能发生这种情况。

    位串:由若干位组合起来形成位串,位串就是1和0的字串。

  8. 当使用指针或引用变量时,被引用的内存属性是否与编译器所预期的一致? 这种错误的一个例子是,当一个指向某数据结构的C++指针,被赋值给另外的数据结构的地址 。
  9. 假如一个数据结构在多个过程或子程序中被引用,那么每个过程或子程序对给结构的定义是否相同?
  10. 如果字符串由索引,当对数组进行索引或下标引用,字符串的边界取值是否有一个“仅差一个”(off-by-one)的错误。

    off-by-one:大小差一错误是一类常见的程序设计错误,例如长度为5的数组中不应该出现a[5]

  11. 对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足?

[3] [2] [2] 数据声明错误

  1. 是否所有的变量都进行了明确的声明? 虽然没有明确声明不一定是错误,但通常却是麻烦的源头。举例来说,如果一个程序的子程序接受一个数组参数,却为将参数定义为数组,对该数组的引用会被解释为一个函数调用,导致计算机试图将此数组当作程序执行。另外,如果某个变量在一个内部过程或程序块中没有明确声明,是否可以理解为该变量在这个程序块中被共有?
  2. 如果变量所有的属性在声明中没有明确说明,那么默认的属性能否被正确理解? 举例来说,在Java语言中,程序接收到的没有正确声明的默认属性往往是导致意外发生的源头。
  3. 如果变量在声明语句中被初始化,那么它的初始化是否正确? 在很多语言中,数组和字符串的初始化比较复杂,因此也称为容易出错的地方。
  4. 是否每个变量都被赋予了正确的长度和数据类型?
  5. 变量的初始化是否与其存储空间的类型一致?
  6. 是否存在相似名称的变量? 这种情况不一定是错误,但应该被视为警告,这些名称可能会在程序中发生混淆。

[3] [2] [3] 运算错误

  1. 是否存在不一致的数据类型(如非算术类型)的变量间的运算?
  2. 是否具有混合模式的运算? 例如,将浮点变量与一个整型变量做加法运算。这种情况并不一定是错误,但应该谨慎使用,确保程序语言的转换规则能被被正确理解。
  3. 是否有相同数据类型、不同字长变量间的运算?
  4. 赋值语句的目标变量间的数据类型是否小于右边表达式的数据类型和结果?
  5. 在表达式的运算中是否存在表达式间向上或向下溢出的情况? 也就是说,最终的结果看起来是个有效值,但中间结果对于编程语言的数据类型可能过大或过小。
  6. 除法运算中的除数是否可能为0?
  7. 如果计算机表达变量的基本方式是基于二进制的,你们运算结果是否不精确? 也就是说,在一个二进制计算机上,10*0.1很少会等于1.0 。
  8. 在特定场合,变量的值是否超出了有意义的范围?
  9. 对于包含一个以上操作符的表达式,赋值顺序和操作符的优先顺序是否正确?
  10. 整数的运算是是否有使用不当的情况,尤其是除法? 举例来说,如果i是一个整型变量,表达式2 * i / 2 == i 是否成立,取决于i是奇数还是偶数,或是先运算乘法还是先运算除法。

[3] [2] [4] 比较错误

  1. 是否有不同数据类型的变量之间的比较运算? 例如,将字符串与地址、日期或数字相比较?
  2. 是否有混合模式的比较运算,或不同长度的变量间的比较运算? 如果有,应确保程序能正常理解转换规则。
  3. 比较运算符是否正确? 程序员经常弄混淆“至多”、“至少”、“大于”、“不小于”、“小于”和“等于”等比较关系。
  4. 每个布尔表达式所叙述的内容是否都正确? 在编写涉及“与”、“或”、“非”的表达式时,程序员经常犯错。
  5. 布尔运算符的操作数是否是布尔类型的? 比较运算符和布尔运算符是否错误地混淆在一起
  6. 在二机制的计算机上,是否有用二进制表示的小数或浮点数的比较运算? 由于四舍五入,以及用二进制表示十进制的近似度,这往往是错误的根源。
  7. 对于那那些包含一个以上布尔运算符的表达式,赋值顺序以及运算符的优先顺序是否正确?
  8. 编译器计算布尔表达式的方式是否会对程序产生影响? 例如,语句if(x==0&&(x/y)>z) 对于有的编译器来说是可接受的,因为其认为一旦“与”运算符的一侧为false时,另一侧就不用计算,但是对于其他编译器来说,却可能引起一个被0除的错误。

[3] [2] [5] 控制流程错误

  1. 如果程序包含多条分支路径,比如有计算GO TO 语句,索隐变量的值是否会大于可能的分支数量? 例如,在语句中,i的取值是否总数1、2或3?

    GO TO(200,300,400),i

  2. 是否所有的循环最终都终止了? 应涉及一个非正式的证据或论据来证明每一个循环都会终止。
  3. 程序、模块或子程序是否最终都终止了?
  4. 由于时机情况没有满足循环的入口条件,循环体是否有可能从未执行?
  5. 如果循环同时由迭代变量和一个布尔条件所控制(如一个搜索循环),如果循环越界了,后果会如何?
  6. 是否存在“仅差一个”的错误,如迭代数量恰恰多一次或少一次?
  7. 如果编程语言中有语句组或代码块的概念(例如do-while()),是否每一组语句都有一个明确的while语句,并且do语句也与其相应的语句组对应?或者,是否每一个左括号对应一个右括号? 目前的大多数编译器都能是别这些不匹配的情况。
  8. 是否存在不能穷尽的判断?

[3] [2] [6] 接口错误

  1. 被调用模块接收到的形参(parameter)数量是否等于调用模块发送的实参(argument)数量? 另外,顺序是否正确?
  2. 实参的属性(如数据类型和大小)是否与相应形参的属性相匹配?
  3. 实参的量纲是否与对应形参的量纲相匹配? 举例来说,是否形参以度为单位而实参以弧度为单位。
  4. 此模块传递给彼模块的实参数量,是否等于彼模块期望的形参数量?
  5. 此模块传递给彼模块的实参的属性,是否与并模块相应形参的属性相匹配?
  6. 此模块传递给彼模块的实参的量纲,是否与并模块相应形参的量纲相匹配?
  7. 如果调用了内置函数,实参的数量、属性、顺序是否正确?
  8. 如果某个模块或类有多个入口点,是否引入了与当前入口点无关的形参?
  9. 是否有子程序改变了某个原本仅为输入值的形参?
  10. 如果存在全局变量,在所有引用它们的模块中,它们的定义和属性是否相同?
  11. 常数是否以实参形式传递过?

[3] [2] [7] 输入/输出错误

  1. 如果对文件明确声明过,其属性是否正确?
  2. 打开文件的语句中各项属性的设置是否正确?
  3. 格式规范是否与I/O语句中的信息相吻合?
  4. 是否有足够的可用内存空间,来保存程序将读取的文件?
  5. 是否所有的文件在使用之前都打开了?
  6. 是否所有的文件在使用之后都关闭了?
  7. 是否判断文件结束的条件,并正确处理?
  8. 对I/O出错情况处理是否正确?
  9. 任何打印或显示的文本信息中是否存在拼写或语法错误?
  10. 程序是否正确处理了类似于“File Not Found”这样的错误?

[3] [2] [8] 其他检查

  1. 如果编译器建立了一个标识符交叉引用列表,那么对该列表进行检查,查看是否有变量从未被引用过,或仅被引用过一次。
  2. 如果编译器建立了一个属性列表,那么对每个变量的属性进行检查,确保没有赋予过不希望的默认属性值。
  3. 如果程序编译通过了,但计算机提供了一个或多个“警告”或“提示”信息,应对此逐一进行认真检查。“警告”信息指出编译器对程序某些操作的正确性有所怀疑;所有这些疑问都应进行检查。“提示”信息可能会罗列出没有声明的变量,或者时不利于代码优化的用法。
  4. 程序或模块是否具有足够的鲁棒性?也就是说,它是否对其输入的合法性进行了检查?
  5. 程序是否遗漏了某个功能?

[3] [3] 其他人工测试方法

代码走查与代码检查很相似,代码走查是被指定的测试人员用一些简单的测试用例沿着代码逻辑走一遍,而其他人则在脑海中推演。

还有桌面检查、同行评审、可用性测试(一种黑盒测试,需要测试人员站在最终用户实用的角度来评估软件的可用性)。

代码检查、走查与评审相关推荐

  1. 精读-软件测试的艺术之代码检查,走查与评审

    本文是关于精读书籍<软件测试的艺术>的一些学习笔记和分享 本书共有九章包括测试思想(心理,经济),代码检查,测试用例设计,模块测试,更高级别的测试,调试,极限测试和因特尔应用系统的测试. ...

  2. 计算机桌面等检查,计算机等级考试(国家)-桌面检查、代码检查、走查与评审...

    计算机等级考试(国家)-桌面检查.代码检查.走查与评审 (5页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 桌面检查.代码检查.走查与评审一 ...

  3. 《软件测试的艺术》第3章:代码检查、走查与评审

    <软件测试的艺术>: 软件开发人员通常不会考虑到的一种测试形式:人工测试.大多数人认为,因为程序是为了供机器执行而编写的,那么也应由机器来对程序进行测试.这种想法是有问题的.人工测试方法在 ...

  4. SonarQube4.4+Jenkins进行代码检查实例之一

    在最新的< 关于代码审查的几点建议>中再次提到了代码分析: 6.尽量使用静态代码分析工具以提高审查效率. 笔者之前也谈到过多次代码分析.代码检查,见: 关于代码评审的微博讨论汇集  #敏捷 ...

  5. 代码检查规则背景及总体介绍

    中秋小长假结束,放松过后的你准备好新一轮的学习了吗?端坐小板凳开始study吧! 今天为大家带来的课程是<代码检查规则背景及总体介绍>,将从代码检查的意义.代码检查场景及工具.代码检查规则 ...

  6. 静态代码检查工具简介

    静态代码检查工具简介 在 Java 软件开发过程中,开发团队往往要花费大量的时间和精力发现并修改代码缺陷.传统的代码复审.同行评审,通过人工方式来检查缺陷仍然是一件耗时耗力的事情.Java 静态代码分 ...

  7. DevOps系列之 —— 持续开发与集成(六)静态代码检查

    DevOps系列之 -- DevOps概览(一)软件产业和交付模式发展趋势 DevOps系列之 -- DevOps概览(二)新型软件技术及交付模式 DevOps系列之 -- DevOps概览(三)De ...

  8. 静态代码检查完成代码分析和SonarQuber的初探

    静态代码检查完成代码分析和SonarQuber的初探 静态代码检查就是静态测试的一种,因此我们先说说静态测试和动态测试都是什么,然后我们再来聊一聊静态代码检查. 先搞清动静的区别 静态测试是指不运行被 ...

  9. 静态代码检查完成代码分析

    静态代码检查完成代码分析 静态代码检查就是静态测试的一种,因此我们先说说静态测试和动态测试都是什么,然后我们再来聊一聊静态代码检查. 先搞清动静的区别 静态测试是指不运行被测程序本身,通过分析或检查源 ...

  10. webstrom代码检查

    如上图,webstorm代码出现波浪线代码检查提示的问题如何解决: 1 打开 2 搜索libraies 3 将没有选中的库选中 4 如果没有响应的库点击右边的download下载 5点击ok搞定

最新文章

  1. Cloudera Manager 常见异常
  2. PHP开发中常见的安全问题详解和解决方法
  3. 【编译原理】求一个句型短语、直接短语、句柄(一看就懂~!骗小狗)
  4. 在服务器托管中对流量和带宽进行限制
  5. 干货 | 神经网络与深度学习精选文章汇总
  6. LiveVideoStackCon深圳-AI无孔不入
  7. Luogu P2319 [HNOI2006]超级英雄
  8. form跳转php页面,form表单页面跳转方式提交练习
  9. ECshop二次开发从开始
  10. Arduino 通过双路L298N电机驱动模块控制麦克纳姆轮运动
  11. 卡耐基计算机专业课程,你以为卡耐基梅隆大学只有计算机专业厉害吗?
  12. 教你撸一个网页聊天室
  13. js 小写金额转大写
  14. 基于AlexNet网络的猫十二分类
  15. 阿里云Landing Zone系列--场景说明
  16. 视频+公众号是未来微信生态的一种新的运营方式!
  17. 题目54:百钱百鸡 一只公鸡值5元,一只母鸡值3元,而1元可买3只小鸡,用百元买百鸡。现有n元钱,想买n只鸡。问有多少种买法?(钱要用完)
  18. web部署到服务器显示404,WAR包部署到服务器的tomcat下404报错
  19. MyEclipse2017破解时 ACTIVATION_KEY为null
  20. 芯片PIC32MZ1024ECH100 (MCHP) -- 32位高性能单片机 up to 330 DMIPS

热门文章

  1. 单片机矩阵键盘扫描程序c语言,51单片机矩阵键盘扫描程序详解
  2. python物理模拟.pdf_用Python物理建模的第一本书终于来啦
  3. 蓝牙耳机测试软件apk_蓝牙5.0手机如何测试检测分辨?这款免费APP帮大忙
  4. java获取系统所有字体_java获取本机所有可用字体
  5. tomcat加载出现找不到web
  6. R语言数据分析之一-《R语言下载及读取excel导入excel》
  7. 西门子 STEP7 HMI生成步骤
  8. 【MySQL建表语句转PostgreSQL建表语句】MySQL建表语句转PostgreSQL建表语句
  9. autolayout教程Android,AndroidAutoLayout的简单阅读
  10. 《一天学懂深度学习》PPT翻译一