目录
1.软件测试
但即使是最好的测试,也无法达到100%的无错误,用残留缺陷率(软件发布后遗留下来的错误)每kloc(1000行代码)来衡量软件的质量:
测试的特征:
1.测试跟其他活动的目标相反:破坏、证错、“负能量”。
2.再好的测试也无法证明系统里不存在错误。
好的测试标准:1.能发现错误;2.不冗余;3.特性最佳;4.既不复杂也不简单。
1.1测试的种类
Unit testing (单元测试):指验证特定代码部分功能的测试,通常在功能级别。
Integration testing (集成测试):由多个程序员或编程团队创建的两个或多个类、包、组件、子系统的组合执行。
System testing (系统测试):测试一个完全集成的系统,以验证该系统满足其要求,并在其最终配置中执行该软件。
![](https://i-blog.csdnimg.cn/blog_migrate/aaa233b4dd3e2687e9b9195fdd8c239d.png)
1.2静态测试 vs 动态测试试静态测试 vs 动态测试
静态测试:进行静态测试时,并没有实际执行程序。所以,静态测试通常是隐式的,如校对,当编程工具/文本编辑器检查源代码结构或编译器(预编译器)时,检查语法和数据流作为静态程序分析。
动态测试:描述了代码动态行为的测试,它实际上使用给定的测试用例执行编程代码。动态测试可以在程序100%完成之前就开始了,以测试代码的特定部分,并应用于离散的函数或模块。
1.3测试 vs 调试
![](https://i-blog.csdnimg.cn/blog_migrate/9fd58bc01f4e6ecf617af21c9126321e.png)
1.4白盒测试 vs 黑盒测试
白盒测试:对程序内部代码结构的测试,是通过查看源代码来测试程序的内部结构或工作方式。
黑盒测试:对程序外部表现出来的行为的测试,将该软件视为一个“黑盒”,在不了解内部实现的情况下检查功能,而不看到源代码。
1.5为何软件测试较为困难?
1.不可能暴力穷举完所以可能的测试案例
2.单纯靠偶然测试是没有意义的
3.基于样本的统计数据对软件测试意义不大。比如工厂里测试一批产品合不合格,那就抽样检测,样品中不合格率小于百分之一则该批产品合格,但这对软件测试是没有意义的
4.对于离散的输入,软件行为差异巨大。 大多数正确,少数点出错
5.无统计分布规律可循
2.测试用例
什么是测试用例?
测试用例是一组测试输入、执行条件和预期结果。即,测试用例={测试输入+执行条件+预期结果}
好的测试用例的特征:
1.最可能发现错误;2.不重复、不冗余;3.最有效;4. 既不简单也不复杂
3.测试优先编程
测试优先编程:在编写代码之前先编写测试。
测试优先编程的特点:
1.尽早地、尽可能多地进行测试
2.不要让测试直到最后,因为最后有一大堆未经验证的代码。将测试留到结束只会使调试更长、更痛苦,因为bug可能出现在代码中的任何地方。
测试优先编程一般过程:
先写spec --> 再写符合spec的测试用例 --> 写代码、执行测试、有问题再改、再执行测试用例,直到通过它
4.黑盒测试(重点)
正如上所说,黑盒测试是一种软件测试的方法,它可以检查应用程序的功能,而不需要窥视其内部结构或工作原理。
它可以发现以下类型的错误:1.软件功能缺失或者错误;2.接口错误;3.数据结构或外部数据库访问中的错误;4.行为或者性能错误;5.初始化和终止错误。
黑盒测试的测试用例是围绕规范和要求构建的,即应用程序应该做什么。
测试用例通常来自于软件的外部描述,包括规范、要求和设计参数。此外,选择一组足够小、可以快速运行,但又足够大、可以验证程序的测试用例。
4.1 通过等价类划分选择测试用例
等价划分是一种测试方法,它将将被测函数的输入域划分为等价类, 从等价类中导出测试用例。针对每个输 入数据需要满足的约束条件,划分等价类。每个等价类代表着对输入约束加以满足/违反的有效 /无效数据的集合。
等价类背后的思想是将输入空间划分为相似的输入集合,在这些输入集上程序具有相似的行为,然后使用每个集合的一个代表。
通常等价类划分可以基于以下指导进行:
1.如果输入条件指定了一个范围,则定义一个有效的和两个无效的等价类。
2.如果输入条件需要特定的值,则定义一个有效和一个无效的等价类。
3.如果输入条件指定了集合的成员,则定义一个有效和一个无效的等价类。
4.如果输入条件为布尔值,则分别定义一个有效类和一个无效类。
例如,对于BigInteger中的multiply方法:我们应该把乘法看作是一个接受两个输入的函数:
所以我们有一个二维的输入空间,由所有的整数对(a,b)组成。 然后从正负的角度对二维空间进行等价类划分。
但是,我们需要考虑一些特殊情况:
1.a or b is 0, 1, or -1?
2.考虑输入的上限:很大的数是否仍正确?
所以,我们把上述考虑结合在一起,独立地从如下方面选择a和b:
---0
---正1
---负1
---小正整数
---小负整数
---大正整数
---大负整数
这将产生7*7=49分区,完全覆盖整数对的空间。
4.2在分区中包含边界
---0是正数和负数之间的边界
![](https://i-blog.csdnimg.cn/blog_migrate/c46c385cf9b85ead988d8933d325d75f.png)
– max : int × int → int
所以,从规范来看,将此函数划分为如下是有意义的:
---a<b
---a=b
---a>b
但是,这划分是基于a与b之间的关系的,a和b自身的输入域,输入边界没有考虑,因此,在如上基础上加入边界值分析,便可得到如下划分:因此,选择测试用例时应该覆盖以上不同方面,如:
– (1, 2) covers a < b, a > 0, b > 0
– (-1, -3) covers a > b, a < 0, b < 0
– (0, 0) covers a = b, a = 0, b = 0
– (Integer.MIN_VALUE, Integer.MAX_VALUE) covers a < b, a = minint, b = maxint
– (Integer.MAX_VALUE, Integer.MIN_VALUE) covers a > b, a = maxint, b = minint
2.Cover each part 覆盖每个取值:最少1次即可
5.白盒测试
![](https://i-blog.csdnimg.cn/blog_migrate/d903d4a39a4b4c14890abde4808ae659.png)
例如,对于整数列表元素的非递减排序 ,应根据不同的列表大小选择不同的排序方法:
使用白盒测试方法,我们可以从下面准则推导出一些测试用例:
–保证一个模块内的所有独立路径都至少执行过一次
–从真假的两面做出所有合乎逻辑的决定
–在其边界和操作范围内执行所有循环
–练习内部数据结构,以确保其有效性
有一种典型的白盒测试方法被称为“独立/基路径测试”:对程序所有执行路径进行等价类划 分,找出有代表性的最简单的路径(例如循环只需执行1次),设计测试 用例使每一条基本路径被至少覆盖1次。
6.代码覆盖度
测试应考虑到程序内部逻辑的测试用例的代码覆盖范围。
代码覆盖是一种用于描述特定测试套件运行时程序源代码执行程度的度量。简单地说就是已有的测试用例有多大程度覆盖了被测程序。
一个具有高代码覆盖率的程序, (通常用百 分比衡量覆盖度),在测试过程中执行了更多的源代码,这表明与一个代码覆盖率较低的程序相比,它包含未检测到的软件错误的可能性更低。
这里有五种常见的覆盖:
–函数覆盖:程序中的每个功能是否都被调用了?
–语句覆盖:每个语句是否都由某个测试用例运行?
–分支覆盖:对于程序中的每一个if or while or switch-case or for它们的正确的和错误的方向是 否都被某个测试用例采取?
–条件覆盖:对于if/while/for/switch-case每个条件,它们的正确的和错误的方向是 否都被 某 个测试用例采取?
–路径覆盖:是否有每个可能的分支组合——通过程序的每一个路径?
测试效果:路径覆盖>分支覆盖>语句覆盖
在工业中,100%的语句覆盖率是一个共同的目标,但即使是这样,也很少由于无法到达的防御代码(比如“永远不应该到达这里”的断言)而实现。
100%的分支覆盖是非常可取的,但是,不幸的是,100%的路径覆盖是不可行的,需要指数大小的测试套件来实现。
为什么路径覆盖需要指数级测试套件呢?
这是由于程序往往包含循环,几乎不可能执行每一条路径,所有我们只能尽量确保覆盖率尽可能高。
例如:
7.记录测试用例策略
如下,这样能使代码逻辑清晰,便于阅读理解和发现一些缺陷。
![](https://i-blog.csdnimg.cn/blog_migrate/bead5cda17042d8ccec2132edf5b38ab.png)