在这个示例中,如果要进行比较全面的调试,输入至少要考虑以下可能: 我们在编写这个函数的实现代码前,首先建立调试驱动,以例边编码边执行调试。 假设界面和要调用这个函数的其他代码都已完成。在函数的入口处插入断点,以调试方式运行工程,在界面中选择要生成文档的工程目录,点击"生成文档",程序中断时就可以调试了。这种方式相信所有程序员都很熟悉,并且很多人都会认为这种方式最省时,但实际上,这种方式只是开头省时,当你试图把各个可能输入都调试一遍,就会发现它很费时:可能输入通常分散分布于输入源中(这里的输入源是代码文件),如果要比较全面地调试,通常要整理输入源,否则几乎不可能全面地调试,也就是说,要全面地调试,仍然要费时间整理输入,并不能完全依赖自然输入; 要针对某种输入进行调试,例如要调试参数带有缺省值的情形,一般通过反复跟踪直到想要的输入出现,或者设置条件断点拦截所需要输入,反复跟踪当然费时不少,设置条件断点也是要花时间的,并且有时无法满足需要 ,很多时候,要针对特殊输入进行调试都是很大费时的; 由于是公共输入源,输入数据很难管理,尤其是条件断点更不可能无限期地保存,以后需要再次调试时可能要做很多重复工作。 自然驱动的更主要问题是不全面,开发人员常常会将思维局限于现有的输入源,导致一些可能输入根本就没有考虑到,在本例中,很可能只是试一下解析一两个文件,检查得到的结果是否正确,如果文件中没有 带数组的参数,那这种输入很可能就被忽略掉。这种不全面,导致代码功能不齐,健壮性差,后期测试和维护成本居高不下,甚至导致项目的失败,因此,这是看起来高效,实际上很低效的方式,读者可以在看完后面两种方式的介绍后,自 已尝试并对比一下,可以拿任何有一定复杂度的代码编写来对比,不局限于这里所举的例子。 专门驱动离单元测试只有一步之遥了,只要在驱动代码中添加判断预期输出的语句就构成了完整的测试代码,因此,在实际工作中,采用专门驱动最好是边编码边测试,并使用测试代码作为调试驱动。下面是为函数CExFunction::ParseOneParameter ()编写的调试驱动代码: {CExFunction* pObj = new CExFunction(); CTokenList iList; CTokenReader reader; reader.ReadTokenList(iList, "int i"); PARAMETER* ret = pObj->ParseOneParameter(iList) ; ASSERT( ret->type == "int" ); ASSERT( ret->name == "i" ); reader.ClearTokenList(iList); delete pParam; delete pObj;}
上面的代码其实是一个测试用例的完整代码,测试代码通常都是很简单的,功能无非是使被测试的代码得于执行,被测试代码通常都涉及到外部数据,如参数、成员变量、全局变量什么的,这些数据当然要设定初始值,例如,上面的测试用例是将字符串"int i"经过CTokenReader对象的ReadTokenList方法转换成CToken对象指针的列表作为参数iList的输入。 在实际工作中,函数的输入输出常常不是简单的数据类型,而是某些对象甚至是对象的集合,本例中,输入的数据就是CToken对象指针的列表。这种情况下,一般借助现有的代码来生成数据,通常,这些"现在代码"都是存在的,因为即使不做测试,也总有代码要调用该函数的,调用代码本来就需要生成相应的数据。本例中,CTokenReader::ReadTokenList()函数就是把字符串转换为CToken对象指针的列表。
|
正在阅读:高效开发与彻底测试高效开发与彻底测试
2006-11-10 09:23
出处:
责任编辑:lizhe
键盘也能翻页,试试“← →”键