Lecture 7 Debugging
- Testing methods: ways of trying code on examples to determine if running correctly
- Debugging methods: ways of fixing a program that you know does not work as intended
1. when should we test and debug
a. when designing code
- 将程序片段化,可以独立debug
- 用文字描述module的一些限制值、输入输出值等
- 记录假设情况
做testing之前,首先要确保没有syntax errors 或 static semantic errors;另外,还需准备好一些预计得到的结果,(如几组对应的输入输出值)
2. testing
- Goal:show that bugs exist (hard to prove code is bug free)
- Test suites
将多个测试输入值分类,每个分类中的任意一个值都可以代表全组的正确性,并且确保每一种分类都有最少一个值可用来做测试
3. partition-隔断、分割
partitioning 分为三大类,一为依据其自带的属性分割;二为随机测试;三为使用heuristics(启发式)。
heuristics又分为两种:黑盒测试与白盒测试
4. black-box testing–功能测试
将details of implementation 与 use of implementation隔离开来进行测试。
如下例子说明了如何在需要test求平方根的公式时进行partition(typical&extremes):
# a way to think about black-box testing is to look at both: #
- The possible paths through the specification.
- The possible boundary cases.
#黑盒测试-测试方法列举#
5. Glass-box testing–结构测试
- use code directly
- path-complete的意思是: Because we know how the function we are testing is defined, we can use this definition to figure out how many different paths through the code exist
examples:
除了保证path complete之外,也需要测试boundary cases。
#Useful Rules when glass-box testing#
白盒测试-测试用例示范:
def maxOfThree(a,b,c) :
"""
a, b, and c are numbers
returns: the maximum of a, b, and c
"""
if a > b:
bigger = a
else:
bigger = b
if c > bigger:
bigger = c
return bigger
Recall from the lecture that a path-complete glass box test suite would find test cases that go through every possible path in the code. In this case, that means finding all possibilities for the conditional tests a > b and c > bigger. So, we end up with four possible paths that correspond to Test Suite A:
Case 1: a > b and c > bigger - this corresponds to test maxOfThree(2, -10, 100).
Case 2: a > b and c <= bigger - this corresponds to test maxOfThree(6, 1, 5)
Case 3: a <= b and c > bigger - this corresponds to test maxOfThree(7, 9, 10).
Case 4: a <= b and c <= bigger - this corresponds to test maxOfThree(0, 40, 20)
6. conducting tests
unit testing ---- algorithm bugs
integration testing ---- interaction bugs
7. test drivers and stubs – 驱动模块与桩模块
转载一位博主针对drivers和stubs的解释:
作者:SZn_Xin
来源:优快云
原文:https://blog.youkuaiyun.com/u010392022/article/details/75097792
传统的单元测试包括了驱动模块(driver) 和桩模块(stub)。驱动模块的目的很单纯,就是为了访问类库的属性和方法,来检测类库的功能是否正确;
【驱动模块】
驱动模块是用来模拟被测试模块的上一级模块,相当于被测模块的主程序。它接收数据,将相关数据传送给被测模块,启用被测模块,并打印出相应的结果。
驱动模块(Driver)可以通过模拟一系列用户操作行为,比如选择用户界面上的某一个选项或者按下某个按钮等,自动调用被测试模块中的函数。驱动模块(Driver)设置,使对模块的测试不必与用户界面真正交互。
【桩模块】
桩模块是指模拟被测试的模块所调用的模块,而不是软件产品的组成的部分。主模块作为驱动模块,与之直接相连的模块用桩模块代替。在集成测试前要为被测模块编制一些模拟其下级模块功能的“替身”模块,以代替被测模块的接口,接受或传递被测模块的数据,这些专供测试用的“假”模块称为被测模块的桩模块。
如果被测试的单元模块需要调用其他模块中的功能或者函数(method),我们就应该设计一个和被调用模块名称相同的桩模块来模拟被调用模块。这个桩模块本身不执行任何功能仅在被调用时返回静态值来模拟被调用模块的行为。举例说明:如果被测试单元中需要调用另一个模块customer的函数 getCustomerAddress(customerID: Integer),这个函数应该查询数据库后返回某一个客户的地址。我们设计的同名桩模块(Stub)中的同名函数并没有真正对数据库进行查询而仅模拟了这个行为,直接返回了一个静态的地址例如"123 Newton Street"。桩模块的设置使得单元测试的进行成为一个相对独立且简单的过程。
【总结】
桩模块的使命除了使得程序能够编译通过之外,还需要模拟返回被代替的模块的各种可能返回值(什么时候返回什么值需要根据测试用例的情况来决定)。
驱动模块的使命就是根据测试用例的设计去调用被测试模块,并且判断被测试模块的返回值是否与测试用例的预期结果相符
8. the procedure of a good testing practice
- start with unit testing
- move to integration testing
- after code is corrected, be sure to do regression testing:
–check that program still passes all the tests it used to pass
9. Runtime bugs
10. debugging的方法
【debugging as search】:
11. some pragmatic hints