IMPORTANCE 本章重点

什么是测试

白盒测试与黑盒测试

按阶段、分步骤测试

1. Software Testing

What is Testing

软件测试:为涉众提供有关被测试产品或服务的质量信息而进行的调查,是提高软件质量的重要手段,但是软件质量取决于设计而不是testing。 - 寻找bug,确认是否达到可用级别(用户需求) - 关注系统的某一侧面的质量特性

测试无法达到100%的无错误,never completely prove the absence of errors。

residual defect rates 残留缺陷率(bugs left over after the software has shipped)。对于大的系统来说,即使残留缺陷率很低,残留的bug也可能很多。 - 1-10 defects/kloc(1000 Lines of Code):Typical industry software - – 0.1-1 defects/kloc: High-quality validation.(Java Libraries) - 0.01-0.1 defects/kloc: The very best, safety-critical validation.(NASA, Praxis)

测试的目标与其他开发流程目标相反:to find errors(破坏、证错、“负能量”)

good testing: 能发现错误、不冗余、最佳特性、别太复杂也别太简单

Testing Level

  • Unit testing 单元测试:代码部分功能测试
  • Integration testing 集成测试:类、包、组件、子系统的组合执行
  • System testing 系统测试:完全集成的系统
  • Regression testing 回归测试:发现错误,改正后,前面的重新测试(自动化)
TestLevel

Static vs. Dynamic Testing

  1. 静态测试 Static testing:without actually executing programs, 靠眼睛看,隐式的静态程序分析,review、walkthroughs、inspections
  2. 动态测试 Dynamic testing:给定测试用例执行

Testing vs. Debugging

  1. 测试:发现是否存在错误 (errors)
  2. 调试:识别错误根源,消除错误 (causes of errors)

White-box vs. black-box testing

  1. 白盒测试:对程序内部代码结构的测试,程序执行情况,by seeing the source code
  2. 黑盒测试:对程序外部表现出来的行为的测试。just input and output,程序完成之前可以确定,用于检查代码的功能,不关心内部实现细节
WhiteVSBlack-box-testing

2. Test Case

测试用例:输入+执行条件+期望结果

E.g. test cases: {2,4}, {0,0}, {-2,4} for program y=x^2

3. Test-First Programming

TDD Test-driven development:先写spec -> 再写符合spec的测试用例 -> 写代码执行测试、有问题再改、再执行测试用例,直到通过它

Testing First Saves a lot of time.避免将缺陷插入代码然后,减少检测到缺陷代码并删除缺陷的时间量

4. Unit Testing(单元测试)

针对软件的最小单元模型开展测试,隔离各个模块(the software component or module),容易定位错误和调试。

5. Automated Unit Testing with JUnit

annotation: @Test

assertion methods like assertEquals, assertTrue, and assertFalse.


6. black-box Testing

only from the specification, not the implementation of the function

黑盒测试用例根据规约、要求、设计参数来形成的。

用尽可能少的测试用例,尽快运行,并尽可能大的发现程序的错误。

6.1 Choosing Test Cases by Partitioning 划分

Equivalence Partitioning 等价类划分

  • 被测函数的输入域划分为等价类,从等价类中导出测试用例(衍生)
  • 如果一组对象可以通过对称、传递和自反的关系链接,则存在等价类。
  • 每个等价类代表着对输入约束加以满足/违反的有效/无效数据的集合

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

等价类划分所选用例要覆盖全部类,还要考虑一些特殊情况(边界值等): - 限定了数值范围:one valid and two invalid - 指明了特定的值:one valid and one invalid - 确定了一组数值:one valid and one invalid - 输入数据是Boolean:one valid and one invalid

EquivalencPartitioningExample

Include Boundaries in the Partition

Boundary Value Analysis (BVA) 边界测试

大量的错误发生在输入域的“边界”而非中央

边界值分析方法是对等价类划分方法的补充

在等价类划分时,将边界作为等价类之一加入考虑

笛卡尔积:全覆盖/覆盖每个取值:最少1次即可

BVAExample

以此为例:

  1. 笛卡尔积全覆盖:3 × 5 × 5 = 75 test cases, but some combinations are impossible, such as a<b, a=0, b=0(多维度多取值,组合每个维度都要有取值,但是并非所有组合情况都可能)
  2. Cover each part 覆盖每个取值最少1次即可:每个维度的每个取值至少被1个测试用例覆盖一次即可,如下。
BVAExampleAnswer

笛卡尔积全覆盖测试完备,但用例数量多,测试代价高;后者方法测试用例少,代价低,但测试覆盖度未必高。Often we strike some compromise between these two extremes,两个极端之间做出一些妥协(出于谨慎、受白盒测试和代码覆盖工具的影响)。

7 White-box Testing

白盒测试要考虑内部实现细节,开发人员去实现,尽量走全代码

根据程序执行路径设计测试用例,只测试实现功能(不能测试缺失功能),不是根据需求选择的测试用例。

白盒测试可以在 unit, integration and system levels 执行,一般较早执行。

BlackBoxTest

独立/基本路径测试:对程序所有执行路径进行等价类划分,找出有代表性的最简单的路径(例如循环只需执行1次),设计测试用例使每一条基本路径被至少覆盖1次

8 Coverage of Testing

Code coverage 代码覆盖度:已有的测试用例有多大程度覆盖了被测程序(百分比衡量覆盖度)

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

测试效果(难度):路径覆盖>分支覆盖>语句覆盖(条件覆盖和分支覆盖没有可比性)

最彻底的白盒测试是覆盖程序中的每一条路径(路径覆盖),但由于一般存在循环,路径数量巨大,难以全覆盖。

a code coverage tool EclEmma

实际中,根据预先设定的覆盖度标准,逐步增加测试用例的数量,直到覆盖度达到标准

9 Automated Testing and Regression Testing

Automated testing: 自动调用被测函数、自动判定测试结果、自动计算覆盖度。只是“测试用例的自动执行”,并非“自动生成测试用例”。A good testing framework, like JUnit, helps you build automated test suites, make it easy to run the tests, not create test cases.

Regression testing 回归测试:一旦程序被修改,重新执行之前的所有测试。

a test is good if it elicits a bug.

Automated regression testing 自动化回归测试(above 2 testing methods combined):一旦发现bug,要马上写一个可重现该bug的测试用例,并将其加入测试库

10 Documenting Your Testing Strategy

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

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