》》健壮性和正确性
健壮性:系统在不正常输入或不正常外部环境下仍能够表现正常的程度,处理未期望的行为和错误终止。即使终止执行,也要准确/无歧义的向用户展示全面的错误信息。
正确性:按照spec加以执行的能力。用户输入错误时,直接结束
一般来说,对外的接口,倾向于健壮性;对内部的实现,倾向于正确性
测量健壮性和正确性的方法:
——外部观察角度:Mean time between failures (MTBF,平均失效间隔时间):描述了可修复系统的两次故障之间的预期时间,而平均故障时间(MTTF)表示不可修复系统的预期故障时间。
——内部观察角度:残余缺陷率:每千行代码中遗留的bug的数量
》》错误和异常处理
Throwable 类是 Java 语言中所有错误或异常的父类。继承的类:extends Object。实现的接口:implements Serializable。
内部错误(error):程序员通常无能为力,一旦发生,想办法让程序优雅的结束
Error的类型:
——用户输入错误
例如:用户要求连接到语法错误的URL,网络层会投诉。
——设备错误
例如:硬件并不总是做你想做的。输出器被关闭
——物理限制
例如:磁盘可能被填满,可能耗尽了可用内存
异常(Exception):你自己程序导致的问题,可以捕获、可以处理。使我们可以处理的东西,可以有异常处理程序,若找不到异常处理程序那么整个系统就完全退出。
除了Runtime异常,其他的异常都是checked。checked的异常如果可能存在,必须要做出异常处理,否则程序就会报错
——Declaring exceptions (throws) 声明“本方法可能会发生XX异常”,写在方法一开始,有throws没有try/catch
——Throwing an exception (throw) 抛出XX异常
——Catching an exception (try, catch, finally) 捕获并处理XX异常
checked异常的处理机制:
——抛出:声明是throws,抛出时throw
——捕获(try/catch):try出现异常,忽略后面代码直接进入catch;无异常不进入catch;若catch中没有匹配的异常处理,程序退出;若子类重写了父类方法,父类方法没有抛出异常,子类应自己处理全部异常而不再传播;子类从父类继承的方法不能增加或更改异常
——处理:不能代替简单的测试,尽量苛刻、不过分细化、将正常处理与异常处理分开、利用好层次结构、早抛出晚捕获、避免不必要的检查
——清理现场、释放资源(finally):finally中语句不论有无异常都执行,一定会执行除了finally语句块中有异常、或者程序所在线程死亡、或者程序提前exit结束。
unchecked异常:不需要try-catch,你无法解决
关于他们两种:Checked exception应该让客户端从中得到丰富的信息。 要想让代码更加易读,倾向于用unchecked exception来处理程序中的错误
一般自定义异常都是extends Exception,如果unchecked的话继承RuntimeException
》》断言和防御式编程
断言:在开发阶段的代码中嵌入,检验某些“假设”是否成立。若成立,表明程序运行正常,否则表明存在错误(在实际运行时不会影响性能)
例子:
断言主要用来处理绝对不可能发生的情况,比如指针为空 、子程序开始执行(结束)时,文件或流处于打开(关闭)状态、子程序开始执行(结束)时,文件或流的读写位置处于开头(结尾)
》》Debug
识别程序的错误,然后消除错误。
——Debug是测试的后续步骤:测试发现问题,debug消除问题;当防御式编程和测试都无法挡住bug时,我们就必须进行debug了;
——Debug的目的:寻求错误的根源并消除它;(Debug占用了大量的时间)
》》Test
发现程序中的错误 提高程序正确性的信心。
程序正确确认的基本方法:
1.形式化推理
2.代码评审
3.测试
静态测试:静态测试通常是隐式的,作为校对,加上编程工具/文本编辑器检查源代码结构或编译器(预编译器)检查语法和数据流作为静态程序分析。
动态测试:描述了代码的动态行为的测试,它实际上是用一组给定的测试用例来执行编程的代码。
白盒测试:对程序内部代码的测试
黑盒测试:对程序外部表现出来行为的测试
——等价划分 :将程序可能的输入进行分类划分为不同集合包括不合法数据,基于等价类划分的测试:将被测函数的输入域划分为等价类,从等价类中导出测试用例。(比如正数,0,负数)
等价类划分可有两种不同的情况:有效等价类和无效等价类。
若一组对象自反、对称、传递,则为等价类
可产生相似结果的输入集合中的一个可代替整个集合
同理,对输出也可以划分等价类
极端:每个分区只有一个测试用例,覆盖所有分区
——边界值分析方法 :边界值分析法是对输入输出的边界值进行测试一种黑盒测试方法,是对等价类分析法的补充。
错误通常隐藏在边界中,如一位偏移、边界值需单独处理等
找到有效数据和无效数据的分界点(最大值、最小值),对该分界点以及两边的值分别单独进行测试。
等价类划分法可以挑选等价类范围内任意一个数据作为代表,而边界值分析法要求每个边界值都要作为测试条件。
》》以注释的方式编写测试策略
例子:
》》JUnit测试用例写法:Junit单元测试是依据 注释中@Test 之前的方法编写的;JUnit测试经常调用多次方法,使用 assertEqual || assertTrue || assertFalse 来检查结果;@Before:准备测试、完成初始化,每个测试方法前执行一次;@After:清理现场,每个测试方法后执行一次
例子:
public class Calculator {
public int evaluate(String expression) {
int sum = 0;
for (String summand: expression.split("\\+"))
sum += Integer.valueOf(summand);
return sum;
}
}
---------------------------------------
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class CalculatorTest {
@Test
public void evaluatesExpression() {
Calculator calculator = new Calculator();
int sum = calculator.evaluate("1+2+3");
assertEquals(6, sum);
}
}