题目11.1
译文:
找出下列代码的错误:
unsigned int i; for (i = 100; i <= 0; --i) printf(“%d\n”, i);
解答11.1
显然,i=100,i<=100. 循环一次也不会执行,所以要改为i>=0,但要注意到i是无符号整型,所以存在i>=0, 所以这样改将会进入死循环,没有结束的标记,所以要将改为i>0, 程序打印1-100的数,即
unsigned int i; for (i = 100; i > 0; --i) printf(“%d\n”, i);
当然也可以改掉i的类型:
int i; for (i = 100; i >= 0; --i) printf(“%d\n”, i);
题目11.2
译文:
有一个应用程序,运行起来后会崩溃,给你源代码,你在调试器中运行了10次, 发现10次崩溃的地方都不一样。程序是单线程的,只使用了C标准库。 试分析导致程序崩溃的原因可能是什么?你怎么去测试这些原因?
解答11.2
这个问题很大程度上取决于应用程序的类型,当然了, 我们还是可以给出一些导致随机崩溃的常见的原因。
崩溃的原因还可能是由于程序依赖于其它应用程序或是外部模块所导致的。 比如应用程序依赖于系统的某些属性,而它们又被其它应用程序所修改, 那么就有可能导致程序的随机崩溃。与硬件交互得多的应用程序更可能产生这类错误。
在面试中,我们应该问面试官,这个程序是什么类型的,用途是什么? 这些信息将帮助你找到问题所在(或是面试官所期望的答案)。比如说,web服务器崩溃的原因更可能是由于内存泄漏, 而底层应用程序崩溃的原因就更可能是由于系统依赖。
题目11.3
译文:
在象棋游戏中,我们有以下的一个函数:boolean canMoveTo(int x, int y)。 x,y是棋盘的坐标,该函数返回棋子是否能移到到那个位置。 解释一下你将如何测试这个函数?
解答11.3
有两个基本的测试类型是我们要做的:验证输入输出的有效性及功能性测试。
输入输出的有效性
我们需要验证输入输出以保证它们是有效的值,这意味着我们需要:
检查输入是否在棋盘内: 给函数传入负值。 给函数传入大于宽度的x值 给函数传入大于高度的y值 根据具体的实现,以上情况要么返回false,要么抛出异常。
检查输出是否合法(本题目不需要,因为输出是true或者false,无所谓合不合法。)
功能性测试
理论上来说,我们应该去测试象棋棋盘的所有可能布局,但由于这个数量太大了, 这样做根本不现实。因此,我们只去测试这其中比较具有代表性的一些情况。 象棋中有6种棋子(国际象棋:王,后,车,象,马,兵),我们按照以下算法做测试:
取出6种棋子中的一个a 除了a的棋子中,取出一个b 在方向集合中取出一个方向d 用棋子a创建一个棋盘布局(放在棋盘所有可能的地方) 将b放在方向d上的一个位置 尝试移动,并检查返回值
题目11.4
译文:
在不使用测试工具的情况下,你如何去测试一个网页的负载能力?
解答11.4
负载测试的一些主要指标包括:
题目说不能使用测试工具,那么我们可以自己写程序针对以上指标来模拟测试。 比如我们可以写一个多线程的程序来模拟成千上万的用户同时访问这个网页。 对于每个线程,我们再去单独测量网页的响应时间,数据IO等。
将程序模拟测试收集到的数据与可接受的数值进行对比,然后对结果进行分析。
题目11.5
译文:
How would you test a pen?
解答11.5
你怎么去测试一支笔?这个问题非常开放,越是开放的问题,我们就越应该给它加上限制。 于是你应该不断地问面试官问题来确定你到底要测试的是一只怎样的笔。 让我们通过以下的模拟对话来学习回答这类题目的技巧:
这样一来,面试者就得到了一个与一开始的问题完全不同的问题了,更加的具体, 因而更容易入手。可以进行的测试有:
等等……
题目11.6
译文:
在一个分布式银行系统中,你如何测试一台ATM机?
解答11.6
老样子,还是需要弄清楚问题的限制是什么。以下是你可以问的问题:
注意:一个好的测试人员会确保他了解测试对象的方方面面。
以下是一些测试取款功能的测试用例: