一种单元测试方法及其装置的制作方法

文档序号:6609959阅读:217来源:国知局
专利名称:一种单元测试方法及其装置的制作方法
技术领域
本发明涉及软件测试技术,特别是涉及一种单元测试方法及其装置。
技术背景单元测试是软件开发中质量保证的重要环节。单元测试包括以下几个过程1) 、根据被测试模块设计相应的测试模块,测试模块包括测试逻辑和测 试接口,测试逻辑需要构造被测试模块的环境变量,设计测试用例,其中桩函 数是最主要的一种环境变量;而测试接口则是某一个测试的入口 ;2) 、修改被测试模块,使被测试模块可以引用测试模块中的桩函数,通 常采用额外全局变量或者宏判别是否引用桩函数还是原来功能函数;3) 、编译修改过的被测试模块和测试模块,生成可执行目标运行文件;4) 、运行目标可执行文件,启动测试模块;测试模块通过不同的环境变 量组合(测试逻辑负责实现),完成对被测试模块的测试;5) 、发布最后版本时,去掉测试模块,修改被测试模块,去除不必要的 针对测试的相关修改,重新编译生成可执行文件。在上述过程中,需要两次修改被测试模块,第一次修改被测试模块是为了 实现与测试模块的关联,传统的方法是使用宏开关或控制变量,最后在测试完 毕后,需要再次修改被测试模块,去除冗余的代码,这样带来一些弊端1) 、采用静态打桩或编译期打桩,原有被测试模块被修改,发布版本又 需要修改回来,单元测试结果的可信性、准确性都受到一定程度影响;2) 、被测试模块的测试代码和实际发布代码混合在一起,给代码版本管 理带来不便。发明内容本发明所要解决的技术问题在于提供一种单元测试方法及其装置,用于在不修改测试代码时减小测试版本和发布版本的差异。为了实现上述目的,本发明提供了一种单元测试方法,用于实现对软件系 统的单元测试,所述软件系统包括被测试模块,包括步骤一,根据所述被测试模块设计生成相应的测试模块,并对所述被测试 模块、所述测试模块进行编译生成一执行文件;步骤二,运行所述执行文件,通过动态打桩完成所述被测试模块与所述测 试模块的挂接,执行测试;步骤三,修改编译策略,去除对所述测试模块的编译,生成发布版本。 所述的单元测试方法,其中,所述步骤二中,由所述测试模块的桩函数进行动态打桩完成所述被测试模块与所述测试模块的挂接。所述的单元测试方法,其中,所述步骤二中,所述桩函数根据一相应描述符的信息控制所述被测试模块与所述测试模块之间的跳转条件和相互联系,所述描述符的信息包括跳转前后序言代码、控制数据。所述的单元测试方法,其中,所述步骤二中,还包括在动态打桩时将所 述跳转前后序言代码、所述控制数据保存至所述描述符的歩骤。所述的单元测试方法,其中,所述步骤二中,还包括在进行动态打桩之 前,由被测试函数调用原功能函数,并将原功能函数的第一条指令替换为跳转 指令,跳转至所述桩函数的序言中的步骤。所述的单元测试方法,其中,所述步骤二中,由所述跳转前后序言代码完 成所述原功能函数向所述桩函数的序言的跳转。所述的单元测试方法,其中,所述步骤二中,还包括由所述桩函数的序 言通过调用一条件函数判断是执行所述桩函数还是返回至所述原功能函数继续执行的步骤,若所述条件函数返回TRUE,则执行所述桩函数,否则返回至所述原功能函数继续执行。所述的单元测试方法,其中,所述步骤二中,由所述条件函数根据由所述 桩函数的路径控制函数得到的路径参数判断是执行所述桩函数还是返回至所 述原功能函数继续执行。所述的单元测试方法,其中,所述步骤二中,还包括在所述执行测试完 成后,删除打桩的步骤。为了实现上述目的,本发明提供了一种单元测试装置,用于实现对软件系统的单元测试,所述软件系统包括被测试模块,该装置包括一生成编译模块,根据所述被测试模块生成相应的测试模块,并对所述被测试模块、所述测试模块进行编译生成一执行文件;一动态打桩模块,用于运行所述执行文件,通过动态打桩完成所述被测试模块与所述测试模块的挂接,执行测试;及一版本生成模块,用于修改编译策略,去除对所述测试模块的编译,生成 发布版本。相比于现有测试方法和装置,本发明的主要优点在于1) 、保持待测试代码的完整性运行期间代码调用更换,不用因为名称问题而修改待测试的代码;保持测 试代码的完整性;尽量减小测试版本和发布版本的行为的差异性。2) 、测试代码集中管理测试代码全部集中在一起,测试代码的去留简单易行,测试代码便于统一 管理,版本具有更好的可控性。3) 、使集成测试更容易所有单元的单元测试代码可以同时存在,在系统运行期间,可以根据需要 有选择的进行部分或者全部单元的测试,使集成测试变得方便灵活。4) 、增强单元测试理论的实践可用性实现了动态打桩功能后,可以将动态打桩工具集成到自动化测试环境,使 得单元测试更加便于使用。


图1是本发明的桩函数调用关系及路径; 图2是本发明的单元测试流程图; 图3是本发明的bootstrap实现流程图; 图4是本发明的stub_prelude实现流程图; 图5是本发明的单元测试装置结构图。
具体实施方式
以下结合附图和具体实施例对本发明进行详细描述,但不作为对本发明的限定。下面以PowerPC CPU为例,详细说明本发明动态打桩的实现方法,如图1 所示,是本发明的桩函数调用关系及路径,图2描述了本发明的单元测试流程 图;在说明实现方法之前,先说明一下使用方法,使用时分几个步骤al)进行打桩,形式如下install一stub(B, stub—B, NULL);最后的参数NULL为条件函数—condition(),在执行桩函数之前,通过 —condition()函数来判断是执行桩函数stub—B()还是回到原功能函数B()继续执 行;a2)桩函数的路径控制函数path—ctrlCpath),通过路径参数jath,桩函数 stub—B()返回不同的值,同时缺省的—condition()函数可以根据此参数来判断是否返回原功能函数BO;a3)执行被测试函数A();a4)判断返回结果,确认测试结论;a5)删除打桩动作remov^stub(stub—B)。运行时动态函数替换的一般原则是,被测试函数AO调用原功能函数B0, 原功能函数B()的第一条指令被替换为跳转指令,跳转到桩函数stub一B()的序 言stub_prelude中,然后在序言stub_prelude中调用描述符中的信息 —conditional()判断是执行桩函数stub—B()还是继续执行原功能函数B(),如果 —conditional()返回TRUE(非0),那么继续运行桩函数代码,如果—conditional) 返回FALSE (0),那么fallback运行原功能函数B()的代码。增加—conditional() 主要是考虑到用户可能有一些特别的需求,希望在特定情况下(如jath()无法 控制的特殊情况),能够临时回避桩函数stub一B()而调用原功能函数B()。在install—stub()之后,被测试函数A()调用原功能函数B()的情况变化,见 图1所示。针对每个桩替换,都存在一个相应的描述符,在install—stub()时需要保存 如下信息到描述符bl) —orig函数地址(B地址),以便以后恢复指令;b2) —stub函数地址(stub—B地址),—stub函数地址之后将作为描述符数 组的关键字来使用;描述符数组是指所有测试模块的桩函数stub—B()的描述符组成的数组。 b3) —conditional函数地址,供桩函数调用; b4)创建这个桩函数stub—B()的进程owner ID;b5) prelude序言的bootstrap部分,包括栈分配,保存lr、 r3;然后装载 描述符结构地址到r3,并调用prdude();b6) fallback指令,包括被替换的指令(32bit),以及一条跳转到—orig + 4 的指令,因为如果需要执行原功能函数B(),那么就要跳回原功能函数B()的 代码段;fallback指令用于实现返回到原功能函数B()的跳转,不是从桩函数stub—B() 跳转至原功能函数B(),其通过条件判断后返回原功能函数B(),由序言代码 到原功能函数B的跳转,桩函数stub—BG没有执行;一orig是被替换的指令,在PowerPC中是一个32bit指令,该指令在构造 的fallback指令序列中已经被执行,所以继续原功能函数B()的执行就是执行 —orig指令的下一条指令,即一orig + 4;b7)初始路径设置,初始值为0。prelude—bootstrap()函数用于完成原功能函数B()至U stub_prelude调转的接 续,每个描述符结构中都包括这部分代码,具体作用是保存描述符本身、原功 能函数B()、桩函数stub一B()之间的对应关系,具体到PowerPC上来讲,就是 记录返回寄存器lr的内容,中间包括如下两个调转1、 原功能函数B()调转到prelude—bootstrap()函数,在调转中不影响原有 的lr, prdudej)ootstrap()函数记录lr,其实记录的是原有函数A()调用原功能 函数B()完成后应返回的地址;2、 从存在于描述符中的prelude—bootstrap()函数代码调转到stub_prelude, 这时候使用bl指令,也就是把描述符内部的一个地址装载到了 lr寄存器, stubjrelude执行时候,可以根据lr判断出当前使用的是哪个描述符。上述bl b7信息中,其中b5、 b6为跳转前后序言代码,其余为控制数据。 在对桩函数的调用关系及路径进行描述后,进一步地,本发明的单元测试 方法包括以下过程步骤201,根据被测试模块设计/设置相应的测试模块;步骤202,通过不修改被测试模块,对测试模块和被测试模块进行编译,生成执行文件;步骤203,运行执行文件,通过动态打桩完成被测试模块与测试模块的挂 接,执行测试;该步骤中,被测试模块与测试模块的挂接即是进行install—stub(B, stub—B, NULL)调用后,修改了被测试模块的功能函数的第一条指令为到测试模块的跳 转,测试模块的桩函数就可以被调用到。步骤204、修改编译策略,去掉对测试模块的编译,生成发布版本。与现有单元测试不同之处在于步骤202不修改被测试模块源代码,步骤 203执行测试时通过动态打桩完成被测试模块与测试模块的挂接。动态打桩是在运行期动态修改被测试模块,改变被测试模块与测试模块之 间的调用关系,使得被测试模块的函数在测试模块的测试策略驱动下根据不同 的环境变量返回不同的结果,从而验证被测试模块在不同的环境参数组合下, 返回结果是否正常,从而达到单元测试的目的。进一步地,根据上述内容,动态打桩包括以下几个主要部分cl)为了能够有效控制被测试模块和测试模块之间的跳转条件和相互联 系,针对每个测试模块中的桩函数stub—B()有对应的描述符,描述符包括跳转 前后序言代码及控制数据;c2)桩函数stub—B()根据路径控制函数传入的参数控制执行路径,针对非 测试的路径,会跳转到原功能函数B()的内容;c3)测试完毕后可以动态恢复对原功能函数B()的修改,保持测试前运行 代码的完整性。如图3所示,是本发明的bootstrap实现流程图,并结合图1、 2,由于替 换了原功能函数B()的第一条指令为b prelude指令,因此当执行到 prelude—bootstrap()函数的第一条指令时,除了 pc值,其他寄存器以及栈的情 况较被测试函数A()都没有变化,而被测试函数A()的调用信息也就丢失了, 因此,只能通过pc当前指令地址来取得桩函数的描述符的地址,即 prelude—bootstrap (PowerPC),该流程具体包括步骤301,开始;步骤302,分配栈桢,stwusp,-160(sp); 步骤303,保存r3, stwr3,32(sp);该步骤中,stwr3,32(sp诉于保存r3到堆栈,即保存lr (返回寄存器)的 内容;步骤304,保存lr, mflrr3, stw r3, 160(sp);该步骤中,mflrr3用于将lr调入r3; stwr3, 160(sp)用于保存r3到堆栈, 即保存lr (返回寄存器)的内容;步骤305,调用stub_prelude, bl stub_prelude; 该步骤中,bl stub_prelude用于调用stubj3relude()函数; 步骤306,结束。 该流程中,sp指栈指针寄存器。如图4所示,是本发明的stubjrdude实现流程图,并结合图1、 2,由于 桩函数的序言部分被分为两部分,而bootstrap实现流程已经做了一部分工作, 因此stubjrdude函数获得了一个参数(r3),指向当前描述符数据结构地址, stub_prelude的流程具体包括步骤401,开始;步骤402,保存其他工作寄存器到栈桢,包括描述符数据结构指针; 步骤403,判断一condition()是否为TRUE;若是,则调用桩函数,并结束;否则FALSE,恢复所有寄存器、sp,并跳转到fallback,恢复恢复执行原功能函数B(),结束。prelude代码是整个动态打桩的核心代码部分,按照上述完成序言代码的 编写,就可以实现动态打桩的功能。如图5所示,是本发明的单元测试装置结构图。该装置50用于实现对软 件系统10的单元测试,软件系统10包括被测试模块101;该装置50包括生成编译模块501,用于根据被测试模块101生成相应的测试模块102, 并对被测试模块101、测试模块102进行编译生成执行文件;动态打桩模块502,用于运行执行文件,通过动态打桩完成被测试模块101 与测试模块102的挂接,执行测试;版本生成模块503,用于修改编译策略,去除对测试模块101的编译,生 成发布版本。本发明方法是一种采用动态打桩的软件单元测试方法,适用于所有需要进 行单元测试的软件系统,尤其适用于采用过程语言的软件系统。采用本发明运行期动态打桩的单元测试方法,无需修改被测试代码,保持 了被测试代码的完整性,减小测试版本和发布版本的行为的差异性。当然,本发明还可有其他多种实施例,在不背离本发明精神及其实质的情 况下,熟悉本领域的技术人员当可根据本发明作出各种相应的改变和变形,但 这些相应的改变和变形都应属于本发明所附的权利要求的保护范围。
权利要求
1、一种单元测试方法,用于实现对软件系统的单元测试,所述软件系统包括被测试模块,其特征在于,包括步骤一,根据所述被测试模块设计生成相应的测试模块,并对所述被测试模块、所述测试模块进行编译生成一执行文件;步骤二,运行所述执行文件,通过动态打桩完成所述被测试模块与所述测试模块的挂接,执行测试;步骤三,修改编译策略,去除对所述测试模块的编译,生成发布版本。
2、 根据权利要求1所述的单元测试方法,其特征在于,所述步骤二中, 由所述测试模块的桩函数进行动态打桩完成所述被测试模块与所述测试模块 的挂接。
3、 根据权利要求2所述的单元测试方法,其特征在于,所述步骤二中, 所述桩函数根据一相应描述符的信息控制所述被测试模块与所述测试模块之 间的跳转条件和相互联系,所述描述符的信息包括跳转前后序言代码、控制 数据。
4、 根据权利要求3所述的单元测试方法,其特征在于,所述步骤二中,还包括在动态打桩时将所述跳转前后序言代码、所述控制数据保存至所述描述符的步骤。
5、 根据权利要求4所述的单元测试方法,其特征在于,所述步骤二中,还包括在进行动态打桩之前,由被测试函数调用原功能函数,并将原功能函 数的第一条指令替换为跳转指令,跳转至所述桩函数的序言中的步骤。
6、 根据权利要求5所述的单元测试方法,其特征在于,所述步骤二中, 由所述跳转前后序言代码完成所述原功能函数向所述桩函数的序言的跳转。
7、 根据权利要求5或6所述的单元测试方法,其特征在于,所述步骤二中,还包括由所述桩函数的序言通过调用一条件函数判断是执行所述桩函数还是返回至所述原功能函数继续执行的步骤,若所述条件函数返回TRUE,则 执行所述桩函数,否则返回至所述原功能函数继续执行。
8、 根据权利要求7所述的单元测试方法,其特征在于,所述步骤二中, 由所述条件函数根据由所述桩函数的路径控制函数得到的路径参数判断是执行所述桩函数还是返回至所述原功能函数继续执行。
9、 根据权利要求l、 2、 3、 4、 5、 6或8所述的单元测试方法,其特征在 于,所述步骤二中,还包括在所述执行测试完成后,删除打桩的步骤。
10、 一种单元测试装置,用于实现对软件系统的单元测试,所述软件系统包括被测试模块,其特征在于,该装置包括一生成编译模块,根据所述被测试模块生成相应的测试模块,并对所述被测试模块、所述测试模块进行编译生成一执行文件;一动态打桩模块,用于运行所述执行文件,通过动态打桩完成所述被测试 模块与所述测试模块的挂接,执行测试;及一版本生成模块,用于修改编译策略,去除对所述测试模块的编译,生成 发布版本。
全文摘要
本发明公开了一种单元测试方法及其装置,用于实现对软件系统的单元测试,所述软件系统包括被测试模块,其特征在于,该方法包括步骤一,根据所述被测试模块设计生成相应的测试模块,并对所述被测试模块、所述测试模块进行编译生成一执行文件;步骤二,运行所述执行文件,通过动态打桩完成所述被测试模块与所述测试模块的挂接,执行测试;及步骤三,修改编译策略,去除对所述测试模块的编译,生成发布版本。采用本发明保持待测试代码的完整性,减小测试版本和发布版本的行为的差异性,方便测试代码集中管理,使集成测试更容易,大大增强了单元测试理论的实践可用性。
文档编号G06F11/36GK101334753SQ200710117969
公开日2008年12月31日 申请日期2007年6月26日 优先权日2007年6月26日
发明者王云峰 申请人:中兴通讯股份有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1