【软件构造】第七章知识整理

健壮性和正确性

***健壮性:系统在不正常输入或不正常外部环境下仍能够表现正常的程度

***面向健壮性的编程

    处理未期望的行为和错误终止

    即使终止执行,也要准确/无歧义的向用户展示全面的错误信息

错误信息有助于进行debug

***编程原则:总是假定用户恶意、假定自己的代码可能失败

             把用户想象成白痴,可能输入任何东西

             封闭实现细节,限定用户的恶意行为

             考虑极端情况,没有不可能”

***正确性:程序按照spec加以执行的能力,是最重要的质量指标

***正确性VS健壮性

   正确性:永不给用户错误的结果,倾向于直接报错,直接结束

   健壮性:尽可能保持软件运行而不是总是退出,倾向于容错,程序内部已有容错机制

***对外的接口,倾向于健壮;对内的实现,倾向于正确

 

 

 

Throwable

一个异常类是从Throwable分离出来的类

 

 

 

Runtime异常、其他异常

Exception可分为两类:运行时异常 + 其他异常

***运行异常:由程序员在代码里处理不当造成

             如果在代码中提前进行验证,这些故障就可以避免

   e.g:可以通过检查数组的下标是否超过数组的长度以避免ArrayIndexOutOfBoundsException

         可以通过检查变量是否为空以避免NullPointerException

***其他异常:由外部原因造成

             即使在代码中提前加以验证,也无法完全避免失效发生。

 

 

 

Checked异常、Unchecked异常

***Unchecked exceptionError + RuntimeException

   不需要在编译的时候用try…catch等机制处理

   可以不处理,编译没问题,但执行时出现就导致程序失败

   类似于编程语言中的dynamictype checking

***Checked exceptionThrowable除去unchecked exception

   必须捕获并指定错误处理器handler,否则编译无法通过

   类似于编程语言中的static typechecking

Checked Exception Unchecked Exception区别

 

 

 

Checked异常的处理机制

用于exception的处理机制的五个关键字:trycatchfinallythrowsthrow

throws:声明“本方法可能会发生xxx异常”

throw:抛出xxx异常

trycatchfinally:捕获并处理xxx异常

***方法要在定义和spec中明确声明所抛出的全部checked exception,以便调用该方法的client加以处理

***处理异常时,尽量在自己这里处理,实在不行就往上传

***释放资源:

***清理现场:printStackTrace()

 

 

 

自定义异常类

如果JDK提供的exception类无法充分描述你的程序发生的错误,可以创建自己的异常

自定义异常类的编写:


自定义异常类的使用:

***在抛出异常的时候,将现场信息记入异常

   在异常处理时,利用这些信息给用户更有价值的帮助

 

 

 

断言的作用、应用场合

***断言:在开发阶段的代码中嵌入,检验某些“假设”是否成立。若成立,表明程序运行正常,否则表明存在错误。即是对代码中程序员所做假设的文档化,也不会影响运行时性能(在实际使用时,assertion 都会被disabled)

   e.g

***两种格式:①assert condition;   assert condition :message;

***为什么使用断言:

   ①记录和测试程序员的假设条件(如不变量是否符合条件)

   ②验证程序员是否理解正确

   ③快速发现错误

   ④增加程序的可信度

   ⑤假设将黑盒测试转换为白盒测试

   使用断言的主要目的是为了在开发阶段调试程序、尽快避免错误

***断言用在哪里?

   用于验证内部不变量/表示不变量/控制流不变量/方法的前置条件/方法的后置条件

***断言主要用于开发阶段,避免引入和帮助发现bug;实际运行阶段,不再使用断言

避免降低性能

程序之外的事,不受你控制,不要乱断言!!!

 

 

 

调试的基本过程和方法

***过程

reproduce:找到一种可靠且方便的可以根据需求重现问题的方法

diagnose:构建假设,并通过实验来测试它们,直到已确定错误的根源

fix:设计和实施解决问题的方法,并在此过程中保持软件的整体质量

reflect:通过该错误得到哪些教训?

***方法:假设-检验

***从最小的测试用例开始复现错误

 

 

 

黑盒测试用例的设计

***黑盒测试:对程序外部表现出来的行为的测试,用于检查代码的功能,不关心内部实现细节

***于等价类划分的测试:将被测函数的输入域划分为等价类,从等价类中导出测试用例。

针对每个输入数据需要满足的约束条件,划分等价类

每个等价类代表着对输入约束加以满足/违反的有效/无效数据的集合

等价类基于的假设:相似的输入,将会展示相似的行为。故可从每个等价类中选一个代表作为测试用例即可

***边界值分析方法是对等价类划分方法的补充,这是由于大量的错误发生在输入域的“边界”而非中央,因此在等价类划分时,将边界作为等价类之一加入考虑,此外还要考虑边界的两侧

 

 

 

以注释的形式撰写测试策略

测试策略(根据什么来选择测试用例)非常重要,需要在程序中显式记录下来

目的:在代码评审过程中,其他人可以理解你的测试,并评判你的测试是否足够充分

e.g

 

 

 

Junit测试用例写法

使用@Test表明测试一个方法

使用assertEquals()测试方法是否成功实现

Junit中的assertXXX()方法

***需要对每一个编写的方法编写测试用例

 

 

 

测试覆盖度

***笛卡尔积:全覆盖

   多个划分维度上的多个取值,要组合起来,每个组合都要有一个用例

***覆盖每个取值:最少1次即可

   每个维度的每个取值至少被1个测试用例覆盖一次即可

***笛卡尔积VS覆盖每个取值

   前者:测试完备,但用例数量多,测试代价高

   后者:测试用例少,代价低,但测试覆盖度未必高

***代码覆盖度:已有的测试用例有多大程度覆盖了被测程序

   代码覆盖度越低,测试越不充分但要做到很高的代码覆盖度,需要更多的测试用例,测试代价高

***分类:函数覆盖 + 语句覆盖 +分支覆盖 + 条件覆盖 + 路径覆盖

   测试效果:路径覆盖>分支覆盖>语句覆盖

   测试难度:路径覆盖>分支覆盖>语句覆盖

   路径数量巨大,难以全覆盖

实际当中,根据预先设定的覆盖度标准,逐步增加测试用例的数量,直到覆盖度达到标准(例如语句覆盖100%、路径覆盖90%)。

***工具:EclEmma

猜你喜欢

转载自blog.csdn.net/qq_41772794/article/details/80780127