Notes of testing and debugging

今天复习了MIT计算机导论的lecture7,关于测试和调试的概念有了一些基本了解,记录下来怕忘记。

测试基础

  1. The most important thing to say about testing is that its purpose is to show that bugs exist, not to show that a program is bug-free.

  2. The key to testing is finding a collection of inputs, called a test suite, that has a high likelihood of revealing bugs, yet does not take too long to run.
    Test suites based on exploring paths through the code called glass-box testing. based on exploring paths through the specification(说明书) called black-box testing.

  3. in black-box testing, we must consider two kinds of conditions

  • typical conditions through the specification
  • boundary conditions
  1. in glass-box testing, the test suite is path-conmplete, there are a few rules of thumb thatare usually worth following:
    2.1 Exercise both branches of all if statements.
    2.2 Make sure that each except clause is executed.
    For each for loop, have test cases in which
    2.3 The loop is not entered (e.g., if the loop is iterating over theelements of a list, make sure that it is tested on the empty list)
    2.4 The body of the loop is executed exactly once, and
    The body of the loop is executed more than once.

2.5 For each while loop,

  • Look at the same kinds of cases as when dealing with for loops,and
  • Include test cases corresponding to all possible ways of exiting the loop. For example, for a loop starting with
    while len(L) > 0 and not L[i] == efind cases where the loop exits because len(L) is greater than
    zero and cases where it exits because L[i] == e.

2.6 For recursive functions, include test cases that cause the function toreturn with no recursive calls, exactly one recursive call, and more thanone recursive call.

测试过程

  1. 单元测试(unit test)
  2. 集成测试(integration test)
  3. 反复上述过程多次
    一个有用的方法是建立一段测试驱动(test driver),即一段用来测试的代码

调试

我们可以把调试看作一个检索问题,如果某段代码错误,我们需要找出一个解释,到底是哪个部分造成代码产生了不符合我们预期的结果,我们通常使用二分检索和打印语句来完成这一过程。
具体步骤是,如果某段代码错误,我们在这段代码的中间位置放一个打印语句,若是打印语句不符合预期,那我们知道这段代码在打印语句之前就产生了错误,那我们就关注打印语句之前的那一部分,在这部分的中间放一个打印语句,运行观察代码,反之,则观察打印语句之后的部分,如此循环往复,直到调试成功。

一个常犯却不易被发现的错误--aliasing bug

如下列代码
def isPal(x):

assert type(x) == list
temp = x
temp.reverse
if temp == x:
    return True
else:
return False

def silly(n):

result = []
for i in range(n):
    elem = raw_input('Enter element: ')
    result.append(elem)
if isPal(result):
    print('Yes')
else:
    print('No')

在这段代码中,有两个错误,当我们要调用一个列表的方法时,形式应该是a.reverse(), 若没有(),我们只会得到reverse这个函数,不能使列表转向。还有一个错误就是当我们执行到 if isPal(result) 语句时,我们假设result = [1, 2, 3], result 这个变量指向列表对象[1, 2, 3],当后来执行到 temp = x(temp = result)时,temp同样指向列表对象[1, 2, 3],当一个对象有多个引用的时候,并且引用有不同的名称,我们称这个对象有别名(aliase),因此当temp被转向时,x同样被转向,因为他们两个指向同一个对象,这种情况很容易发生别名错误,不过只发生在可变对象。改好的代码如下
def isPal(x):

assert type(x) == list
temp = x[:]
temp.reverse.()
if temp == x:
    return True
else:
return False

def silly(n):

result = []
for i in range(n):
    elem = raw_input('Enter element: ')
    result.append(elem)
if isPal(result):
    print('Yes')
else:
    print('No')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 失眠和撞鬼一样 | 千万别说自己没有,也千万别说自己是专家 一、 喝什么茶? 不知道一切?如同不知道如何下嘴...
    造府秋香阅读 3,587评论 1 2
  • 悲观锁介绍(百科):悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)...
    Hello_DH阅读 2,635评论 0 0
  • 记得无论是在哪个求学阶段,班上总会有那么几个“坏坏”的男孩。成绩垫底、常被老师批评、顽劣闹腾、爱招惹班上的女孩……...
    lulufly阅读 4,996评论 0 0
  • 我喜欢,搬几把椅子, 和你一起坐在屋前,像这样的阳光底下。 我喜欢,在阳光底下,洗头发洗鞋子。 我喜欢,在阳光底下...
    小乐心阅读 1,904评论 0 0
  • 阶层固化,寒门难再出贵子,你努力的天花板只是别人的起点,这样的话题最近两年成为热点。我们是否以为只有中国如此? 1...
    武松打虎老马说股阅读 3,251评论 5 1