51Testing软件测试论坛

标题: 也是一道面试题:C/C++ 单元测试用例的设计 [打印本页]

作者: minz32    时间: 2004-7-1 15:38
标题: 也是一道面试题:C/C++ 单元测试用例的设计
大家知道printf这个函数吧。

问题就是如何测试这个函数。
作者: lhtia    时间: 2004-7-18 19:19
我也想知道,我最近一直在想如何测试一个没有返回值的函数,如:

public void  foo(){
System.out.println("This is foo method");
}
作者: testing    时间: 2004-7-18 22:09
现把你的printf的函数源码给出来,否则如何做单元测试?单元测试如果没有代码,测试是很难保证全面的。
作者: lhtia    时间: 2004-7-19 05:49
站长帮我吧,我想测一个返回值是void的函数,因为没有期望值可以做比较,所以无法预知里面的代码运行时有没有bug,能不能教我一种方法怎么去测试这种函数。
作者: lhtia    时间: 2004-7-19 05:59
给个具体的例子吧,要测试下面一个函数,该怎么测试:

//用户的一个帐户将要透支,就从该用户的其它帐户把不够的钱转移到这个帐户里
public void performOverdraftProtection(Account account,  float withdrawalAmount)  throws InsufficientBalanceException {
        float transferAmountNeeded
            = withdrawalAmount - account.getAvailableBalance();
        Customer customer = account.getCustomer();
        Collection overdraftAccounts
            = customer.getOverdraftAccounts();
        for (Iterator iter = overdraftAccounts.iterator();
             iter.hasNext(); ) {
            Account overdraftAccount = (Account)iter.next();
            if (overdraftAccount == account) {
                continue;
            }
            if (transferAmountNeeded <
                overdraftAccount.getAvailableBalance()) {
                overdraftAccount.debit(transferAmountNeeded);
                account.credit(transferAmountNeeded);
                return;
            }
        }
        throw new InsufficientBalanceException(
                               "Insufficient funds in overdraft accounts");
    }

[ Last edited by lhtia on 2004-7-19 at 06:00 ]
作者: testing    时间: 2004-7-19 13:40
这个函数本身就存在问题。
1、没有对函数的参数float withdrawalAmount参数合法性检查,如果参数非法,函数应该返回某个特定的返回值
2、float transferAmountNeeded
            = withdrawalAmount - account.getAvailableBalance();
上面的代码中,没有对transferAmountNeeded的合法性检查,如果得到的是负数,该函数应该返回某个特定的返回值
3、 if (transferAmountNeeded <
                overdraftAccount.getAvailableBalance()) {
                overdraftAccount.debit(transferAmountNeeded);
                account.credit(transferAmountNeeded);
                return;
            }
按照编程规范,if与else必须要配套使用,在if和else中必然会有返回值

如果上述三个地方做了正确的处理,该函数应该是有返回值的。
作者: lhtia    时间: 2004-7-19 20:04
谢谢站长详细的解答,太感谢了。

这个函数本身是存在一些问题,不过,这个函数是没有返回值的,它的功能在于,如果能找到这么一个帐户能把钱转移到将要透支的那个帐户里,那么就实现:
                overdraftAccount.debit(transferAmountNeeded);
                account.credit(transferAmountNeeded);
如果找不到这么一个帐户,就意味着将要透支的那个帐户就不能取那些钱了,这时就:throw new InsufficientBalanceException(
                               "Insufficient funds in overdraft accounts");

所以这个单元功能实现在于改变全局变量,或抛出一个Exception。现在我的问题是,如何把这两种可能与期望值对照起来,告诉测试员是不是一致,有没有bug。

如果函数有返回值的话,那就好办了,直接在测试驱动里调用这个函数,把结果与期望值比较就可以了。但是要测试void函数,该怎么去确定期望值呢,如上述的,如果抛出了Exception,那测试驱动里如何编代码去确定这个期望值,又如何比较呢。。。

我写的有点多了,不知道有没有解释明白。
作者: testing    时间: 2004-7-19 22:26
看来只能通过添加测试代码的方式了。
可以定义一个全局变量 int g_iExceptionFlag = TRUE;
然后在 InsufficientBalanceException("Insufficient funds in overdraft accounts");的处理中,增加代码g_iExceptionFlag = FALSE;然后,通过判断g_iExceptionFlag 如果等于TRUE,那么就测试通过,如果等于FALSE则测试不通过。

不知是否合适,仅供参考。
作者: lhtia    时间: 2004-7-20 05:12
多谢站长了,看样子有时候还是不得不添加一些代码来帮助测试。
作者: testing    时间: 2004-7-20 09:56
测试过程中,添加测试代码是很常见的事情,不过要注意添加的测试代码要可控,否则会影响测试效果。
作者: jackytong    时间: 2004-7-30 08:36
1、如果transferAmountNeeded算出来为负数, 那么overdraftAccount.debit(transferAmountNeeded);时, 会不会把当前帐户的钱转移到其他的帐户?
2、如果一个帐户要透支50元, 而其他的6个帐号每个只有10元, 那么钱就没有办法透支了?--》是否跟需求相符合呢?
3、overdraftAccount.debit(transferAmountNeeded);
     account.credit(transferAmountNeeded);
     如果第一句执行通过,而第二句执行错误的时候,会不会一个帐号的钱被靠除,而被透支帐号的钱又没有加入呢?--》不知事务处理是怎么处理的?
4、输入的帐号不存在呢?
5、可以用winrunner自动化的测试工具, 通过数据库的对比来验证代码的执行是否正常?
作者: 天网    时间: 2004-8-5 17:34
你首先要求面试官:请给出printf函数的详细设计文档,否则我没法设计用例。就这么简单。
作者: skinapi    时间: 2004-8-5 22:26
呵呵,这个回答够狠。
我会先问面试官是做黑盒还是白盒。:)
作者: fzx    时间: 2004-12-3 11:46
标题: To:lhtia
除非是特别小的功能,可以返回Viod。只要是稍有规模的代码都应该有执行状态的标志,看看微软MFC的设计就很清楚了。这是设计和开发人员的问题了,呵呵。

如果是通过异常处理来表示程序的执行状态,你可以适度的扩大测试范围,把异常处理作为一种输出与Void函数合并成一个黑盒子,我觉得会很有效。
作者: illusion    时间: 2005-10-19 10:35
标题: To lhtia
呵呵,好像晚了点,不过希望能对其他人有帮助,我正好做过类似的junit测试,
抛开这个方法存在的问题,
首先要先设定一个用户,写多个测试方法使他的账户里存在不同的情况,
1.如果是正常系的测试,就要调用完这个方法后,比较这个用户账户里剩下的钱数,是不是等于原钱数-透支钱数,这个就不用写了吧?
2.这个如果是异常系的测试,可以捕获异常,得到抛出的异常字符串来比较,具体如下:
public void testMethod{
  //此处声明测试类的对象  eg;   
   try{
         eg.performOverdraftProtection(Account account,  float withdrawalAmount);
         fail();
        }catch(Exceptinon ex){
        String str = ex.getMessage();
        assertEquals("Insufficient funds in overdraft accounts",str);
       }
}
作者: rany    时间: 2006-2-19 22:23
只有看的份
作者: luxuabc    时间: 2006-2-22 21:52
受益非浅啊:)
作者: 小布1983    时间: 2006-2-27 17:43
是不是疯了,测试Printf函数就那么简单的么,起码测试几千个用例,我同事侧过的,光这个就测了一周多,这面试题出的够绝的
作者: songfun    时间: 2006-3-8 09:11
呵呵,有点意思,学习学习。

面试官要真考我这个,我可答不上来
作者: walker_lai    时间: 2006-9-3 14:00
看看
作者: viviv_wang    时间: 2006-9-16 15:29
怎么没有下文?有高手来给个全面点的答案吗?
作者: testcat    时间: 2006-9-18 15:29
发觉自己是多么的渺小.
作者: viviv_wang    时间: 2006-9-26 14:19
testing站长:
int g_iExceptionFlag = TRUE;
是不是应该将int 改成bool,
另外你提到的在哪个异常后面增加g_iExceptionFlag = flase;
那不是改动了开发的程序吗?
这样是可以得到返回g_iExceptionFlag 的值来判断,感觉不是太好啊。




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2