软件测试:
测试是确保程序正确性和健壮性的最普遍的手段:
1. 设计测试用例
2. 用 JUnit 写测试用例
3. 自动化测试过程
以发现错误为目的(并不是证明一个程序正确),并验证是否适合使用,即使是最好的测试,也无法达到100%无错误。好的测试有以下特点:能发现错误、不冗余、不太复杂也不太简单等。
测试等级(level)
1. 单元测试:针对方法和类进行的测试
2. 集成测试:针对外部接口进行的测试,每个单元测试完了之后合在一起对大单元测试
3. 系统测试:对整个完整系统的测试
4. 验收测试:客户端的测试
5. 回归测试:改之前测试发现的bug时可能会引入新的bug,所以在改完之后必须将之前的测试用
静态测试与动态测试:
静态测试:静态测试在不实际执行程序的情况下执行。静态测试通常是隐式的,如校对,加上编程工具/文本编辑器检查源代码结构或编译器(预编译器)检查语法和数据流作为静态程序分析。
—评审、演练或检查被称为静态测试。
动态测试:动态测试描述了对代码动态行为的测试,它实际上是用一组给定的测试用例执行已编程的代码。动态测试可以在程序100%完成之前开始,以便测试特定的代码部分,并应用于离散的功能或模块。
测试与调试:
测试目的是发现是否存在错误,而调试是识别错误根源进而消除错误。
黑盒测试 vs 白盒测试:
白盒测试:对程序内部代码结构的测试。
黑盒测试:对程序外部表现出来的行为的测试。
测试用例:
测试用例:输入+执行条件+期望结果
测试优先的编程:
顾名思义就是先设计好测试,再进行编程,程序通过测试用例即正确 。
不要把测试留到最后,当您有一大堆未经验证的代码时。把测试留到最后只会让调试变得更长、更痛苦,因为bug可能在代码中的任何地方。
流程:
先写 spec(规约)。
再写符合规约的测试用例。
写代码、执行测试、有问题再改、再执行测试用例,直到通过它。
规约: 描述了函数的输入和输出行为。它给出了参数的类型和任何附加的约束(例如,sqrt的参数必须是非负的)。它还给出了返回值的类型以及返回值与输入的关系。在代码中,规约由方法签名和上面描述其功能的注释组成。
单元测试:
使用JUnit进行自动化单元测试:
JUnit是一个被广泛采用的Java单元测试框架。JUnit在测试驱动开发的开发中非常重要,它是被统称为xUnit的单元测试框架家族中的一员。
JUnit 测试用例:
在每个测试方法前面使用@Test标注指明,单元测试方法通常包含一个或多个对被测试模块的调用,然后使用断言方法(如assertEquals, assertTrue和assertFalse)检查结果。
例,Math.max()在JUnit上实现:
一个测试类可以包含任意数量的@Test方法,当你用JUnit运行测试类时,这些方法是独立运行的。测试方法间互不影响。
黑盒测试:
用于检查代码的功能,不关注内部实现细节。
黑盒测试尝试查找以下类型的错误:
1. 功能不正确或缺失
2. 接口错误
3. 数据结构错误或外部数据库访问错误
4. 行为或性能错误
5. 初始化和终止错误
黑盒测试的测试用例:
1. 围绕是否符合规约建立的,测试用例一般来自于软件的外部描述,包括规格、要求和设计参数
2. 黑盒测试测不到代码界面
3. 用尽可能少的测试用例将尽可能所有测试功能都测到
等价类划分:
如果一组对象间存在对称、传递和自反的关系,则认为是等价类。
基于等价类划分的测试:将被测函数的输入域划分为等价类,从等价类中导出测试用例(每个等价类里面选一个),针对约束条件划分等价类。
一般每个等价类的划分都是针对输入条件满足/不满足的数据集合。通常,输入条件要么是一个特定的数值、一个值范围、一组相关值,要么是一个布尔条件。
基于的假设:相似的输入,将会展示相似的行为。故可从每个等价类中选一个代表作为测试用例即可。可以降低测试用例的数量。
边界值分析:
很多错误发生在输出域的边界而非中央。通过对边缘位置的值进行分析,是对等价类划分方法的补充。
覆盖分区的两个极端:
(Full Cartesian product)笛卡尔积,全覆盖。多个划分维度上的多个取值,要组合起来,每个组合都要有一个用例。测试完备但测试用例数量多,测试代价高。
(Cover each part)覆盖每个取值,最少一次即可。每个维度的每个取值至少被1个测试用例覆 盖一次即可。测试用例少代价低,但测试覆盖度未必高。
白盒测试:
白盒测试(White-box Testing),基于软件的内部结构或代码来设计测试用例。测试是基于代码的,因此白盒测试能够发现代码中的错误,如逻辑错误、运行时错误等。同时,由于测试基于代码,可以在开发早期发现潜在的错误。