計(jì)算機(jī)程序的測試方法及裝置的制造方法
【專利摘要】本申請公開了測試方法,包括:創(chuàng)建中間函數(shù)和至少一個測試用例,其中,每一測試用例包括與至少一個被測函數(shù)對應(yīng)的至少一個基于類的模擬函數(shù);在被測計(jì)算機(jī)程序中注入與至少一個被測函數(shù)相關(guān)的跳轉(zhuǎn)指令;當(dāng)運(yùn)行測試用例時,生成該測試用例中模擬函數(shù)所屬類的對象指針;當(dāng)一被測函數(shù)被調(diào)用時,通過執(zhí)行與該被測函數(shù)相關(guān)的所述跳轉(zhuǎn)指令而調(diào)用中間函數(shù);當(dāng)中間函數(shù)被調(diào)用時,通過執(zhí)行中間函數(shù),確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其所屬類的對象指針并調(diào)用該模擬函數(shù);當(dāng)模擬函數(shù)被調(diào)用時,與被測函數(shù)之間進(jìn)行交互,獲得被測函數(shù)的返回值;基于返回值確定測試結(jié)果。本申請還公開了相應(yīng)的測試裝置。采用該方法和裝置能夠提高測試性能。
【專利說明】
計(jì)算機(jī)程序的測試方法及裝置
技術(shù)領(lǐng)域
[0001] 本申請涉及信息技術(shù)(IT)領(lǐng)域,尤其涉及計(jì)算機(jī)程序的測試方法及裝置。
【背景技術(shù)】
[0002] 在軟件開發(fā)過程中,需要對編寫的計(jì)算機(jī)程序邏輯進(jìn)行測試。在一些情況下,會使 用諸如Mock等測試工具來模擬計(jì)算機(jī)程序準(zhǔn)備應(yīng)用的環(huán)境中真實(shí)對象的行為,通過模擬這 種真實(shí)對象的行為來與被測計(jì)算機(jī)程序進(jìn)行交互,進(jìn)而能判斷計(jì)算機(jī)程序的邏輯是否正 確。這種測試工具主要是用來模擬那些在應(yīng)用環(huán)境中不容易構(gòu)造(如HttpServletRequest 必須在Servlet容器中才能構(gòu)造出來)或者比較復(fù)雜的對象(如JDBC中的ResultSet對象)。
[0003] 但是,目前這類測試工具具有一定的局限性,只能針對計(jì)算機(jī)程序中類的虛函數(shù) 進(jìn)行模擬操作(如Mock操作)。
【發(fā)明內(nèi)容】
[0004] 本申請?zhí)岢隽艘环N計(jì)算機(jī)程序的測試方法,包括:創(chuàng)建中間函數(shù)和至少一個測試 用例,其中,每一測試用例包括與至少一個被測函數(shù)對應(yīng)的至少一個基于類的模擬函數(shù);在 被測計(jì)算機(jī)程序中注入與至少一個被測函數(shù)相關(guān)的跳轉(zhuǎn)指令;當(dāng)運(yùn)行一測試用例時,生成 該測試用例中模擬函數(shù)所屬類的對象指針;當(dāng)至少一個被測函數(shù)中的任一者被調(diào)用時,通 過執(zhí)行與該被測函數(shù)相關(guān)的跳轉(zhuǎn)指令而調(diào)用中間函數(shù);當(dāng)中間函數(shù)被調(diào)用時,通過執(zhí)行中 間函數(shù),確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其所屬類的對象指針并調(diào)用對應(yīng)的模擬 函數(shù);當(dāng)模擬函數(shù)被調(diào)用時,通過執(zhí)行模擬函數(shù),與被測函數(shù)之間進(jìn)行交互,并獲得被測函 數(shù)的返回值;基于返回值確定測試結(jié)果。
[0005] 本申請還提出了一種計(jì)算機(jī)程序的測試裝置,包括:配置模塊,創(chuàng)建中間函數(shù)和至 少一個測試用例,其中,每一測試用例包括與至少一個被測函數(shù)對應(yīng)的至少一個基于類的 模擬函數(shù);在被測計(jì)算機(jī)程序中注入與至少一個被測函數(shù)相關(guān)的跳轉(zhuǎn)指令;測試用例模塊, 包括至少一個測試用例;當(dāng)運(yùn)行一測試用例時,生成該測試用例中模擬函數(shù)所屬類的對象 指針;跳轉(zhuǎn)模塊,當(dāng)至少一個被測函數(shù)中的任一者被調(diào)用時,通過執(zhí)行與該被測函數(shù)相關(guān)的 跳轉(zhuǎn)指令而調(diào)用中間函數(shù);中間函數(shù)模塊,包括中間函數(shù);當(dāng)中間函數(shù)被調(diào)用時,通過執(zhí)行 中間函數(shù),確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其所屬類的對象指針并調(diào)用對應(yīng)的模 擬函數(shù);測試用例模塊,當(dāng)模擬函數(shù)被調(diào)用時,通過執(zhí)行模擬函數(shù),與被測函數(shù)之間進(jìn)行交 互,并獲得被測函數(shù)的返回值;測試結(jié)果模塊,基于返回值確定測試結(jié)果。
[0006] 采用上述本申請?zhí)峁┑姆椒ê脱b置,能利用中間函數(shù)來獲得被測函數(shù)對應(yīng)的模擬 函數(shù)的地址和對象指針進(jìn)而能夠調(diào)用該模擬函數(shù),而模擬函數(shù)不必繼承自任何其它類,也 就是說,本測試方案能夠利用模擬函數(shù)對各類被測函數(shù)進(jìn)行測試,提高了測試的性能。
【附圖說明】
[0007] 為了更清楚地說明本發(fā)明實(shí)施例或現(xiàn)有技術(shù)中的技術(shù)方案,下面將對實(shí)施例或現(xiàn) 有技術(shù)描述中所需要使用的附圖作簡單地介紹,顯而易見地,下面描述中的附圖僅僅是本 發(fā)明的一些實(shí)施例,對于本領(lǐng)域普通技術(shù)人員來講,在不付出創(chuàng)造性勞動性的前提下,還可 以根據(jù)這些附圖獲得其他的附圖。
[0008] 圖1為本申請一實(shí)例的方法流程圖;
[0009] 圖2為本申請一實(shí)例的中間函數(shù)的處理流程圖;
[0010] 圖3為本申請一實(shí)例的中間函數(shù)的處理流程圖;
[0011]圖4A~4B為本申請實(shí)例的實(shí)現(xiàn)框圖;
[0012]圖5為本申請一實(shí)例的裝置結(jié)構(gòu)圖。
【具體實(shí)施方式】
[0013] 下面將結(jié)合本發(fā)明實(shí)施例中的附圖,對本發(fā)明實(shí)施例中的技術(shù)方案進(jìn)行清楚、完 整地描述,顯然,所描述的實(shí)施例僅是本發(fā)明一部分實(shí)施例,而不是全部的實(shí)施例?;诒?發(fā)明中的實(shí)施例,本領(lǐng)域普通技術(shù)人員在沒有做出創(chuàng)造性勞動前提下所獲得的所有其他實(shí) 施例,都屬于本發(fā)明保護(hù)的范圍。
[0014] 為了描述上的簡潔和直觀,下文通過描述若干代表性的實(shí)施例來對本發(fā)明的方案 進(jìn)行闡述。實(shí)施例中大量的細(xì)節(jié)僅用于幫助理解本發(fā)明的方案。但是很明顯,本發(fā)明的技術(shù) 方案實(shí)現(xiàn)時可以不局限于這些細(xì)節(jié)。為了避免不必要地模糊了本發(fā)明的方案,一些實(shí)施方 式?jīng)]有進(jìn)行細(xì)致地描述,而是僅給出了框架。下文中,"包括"是指"包括但不限于","根 據(jù)……"是指"至少根據(jù)……,但不限于僅根據(jù)……"。下文中沒有特別指出一個成分的數(shù)量 時,意味著該成分可以是一個也可以是多個,或可理解為至少一個。
[0015] 本申請?zhí)岢隽艘环N計(jì)算機(jī)程序的測試方法,該方法可應(yīng)用于各種計(jì)算設(shè)備,比如: 手機(jī)、平板等各種手持設(shè)備、可穿戴設(shè)備、PC機(jī)等。這些計(jì)算設(shè)備可基于各種操作系統(tǒng)平臺, 比如:諸如Windows等的X86系統(tǒng),或者諸如Linux、安卓(Android)等的ARM系統(tǒng)。
[0016] 如圖1所示,該方法包括如下步驟:
[0017] 步驟101:創(chuàng)建中間函數(shù)和至少一個測試用例,其中,每一測試用例包括與至少一 個被測函數(shù)對應(yīng)的至少一個基于類的模擬函數(shù)。
[0018] 這里,如果使用的測試工具是Mock工具(如GoogleMock等),所述模擬函數(shù)為Mock 函數(shù),該Mock函數(shù)為Mock類的成員函數(shù)。
[0019] 在一些實(shí)例中,會實(shí)現(xiàn)一個Mock類,在該Mock類之下會聲明至少一個Mock函數(shù),每 個Mock函數(shù)對應(yīng)一個被測函數(shù),用于與對應(yīng)的Mock函數(shù)進(jìn)行Mock操作,而該Mock類不必繼 承自任何其它類。然而,在使用現(xiàn)有的Mock工具時,Mock類必須繼承自被測程序中某個虛基 類的虛方法,在被測程序調(diào)用該虛基類的該虛方法時才會調(diào)用到Mock類的實(shí)現(xiàn)中(某個 Mock函數(shù))。其中,在創(chuàng)建測試用例時,會聲明Mock類的對象,這樣測試用例運(yùn)行時會生成 Mock類的對象指針(如this指針)。
[0020] 步驟102:在被測計(jì)算機(jī)程序中注入與至少一個被測函數(shù)相關(guān)的跳轉(zhuǎn)指令。這里, 被測計(jì)算機(jī)程序中包括用于實(shí)現(xiàn)各種功能邏輯的至少一個被測函數(shù)。
[0021] 在一些實(shí)例中,所注入的跳轉(zhuǎn)指令可以是鉤子(Hook)函數(shù),目的是為了在調(diào)用某 被測函數(shù)時,Hook到另外一個函數(shù)。
[0022] 上述步驟是預(yù)先的處理,當(dāng)開始針對該被測計(jì)算機(jī)程序中的某個或某些被測函數(shù) 進(jìn)行測試時,會運(yùn)行對應(yīng)的測試用例,這樣,該方法還包括以下步驟:
[0023] 步驟103:當(dāng)運(yùn)行一測試用例時,生成該測試用例中各模擬函數(shù)所屬類的對象指 針。
[0024] 步驟104:當(dāng)上述任一被測函數(shù)被調(diào)用時,通過執(zhí)行與該被測函數(shù)相關(guān)的跳轉(zhuǎn)指令 而調(diào)用上述中間函數(shù)。
[0025]在一些實(shí)例中,當(dāng)一被測函數(shù)被調(diào)用時,通過上述的跳轉(zhuǎn)指令可以Hook到步驟101 中創(chuàng)建的中間函數(shù)。
[0026] 步驟105:通過執(zhí)行該中間函數(shù),確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其所屬 類的對象指針并調(diào)用該模擬函數(shù)。這里,中間函數(shù)可以由匯編程序?qū)崿F(xiàn)。
[0027] 這里,當(dāng)要對一被測函數(shù)進(jìn)行測試時,會調(diào)用該被測函數(shù),同時會運(yùn)行相應(yīng)的測試 實(shí)例(其包括該被測函數(shù)對應(yīng)的模擬函數(shù)),所以,本步驟中,中間函數(shù)能夠確定對應(yīng)的模擬 函數(shù)的地址及其對象指針。
[0028] 步驟106:當(dāng)該被測函數(shù)對應(yīng)的模擬函數(shù)被調(diào)用時,該模擬函數(shù)與該被測函數(shù)之間 進(jìn)行交互,并獲得該被測函數(shù)的返回值,即進(jìn)行模擬操作(比如:Mock操作)。
[0029] 步驟107:基于步驟106中獲得的返回值確定測試結(jié)果。這里,基于被測函數(shù)的返回 值,可以確定Mock操作中傳給被測函數(shù)的參數(shù)值對被測函數(shù)的影響,進(jìn)而能夠確定被測函 數(shù)的邏輯是否有問題以及有何種問題,即得到測試結(jié)果。
[0030] 在上述實(shí)例中,模擬函數(shù)所屬的類不必繼承自任何其它類,通過跳轉(zhuǎn)指令能夠調(diào) 用到中間函數(shù)來獲取模擬函數(shù)所屬類的對象指針進(jìn)而調(diào)用模擬函數(shù),從而可以針對各種被 測函數(shù)進(jìn)行測試,具有更廣泛的適應(yīng)性,改善了測試效率及性能。
[0031] 在一些實(shí)例中,上述步驟101中,測試用例還包括至少一個參數(shù)準(zhǔn)備函數(shù),用于獲 取該測試用例中各模擬函數(shù)所需的參數(shù)。此時,上述步驟103中,當(dāng)運(yùn)行一測試用例時,進(jìn)一 步通過執(zhí)行其中的參數(shù)準(zhǔn)備函數(shù)來獲取其中各模擬函數(shù)所需的參數(shù);上述步驟105中,當(dāng)中 間函數(shù)被調(diào)用后,可進(jìn)一步通過該中間函數(shù)的執(zhí)行讀取此參數(shù)準(zhǔn)備函數(shù)獲取的該被測函數(shù) 對應(yīng)的模擬函數(shù)所需的參數(shù),以供調(diào)用該模擬函數(shù)之用。這里,參數(shù)準(zhǔn)備函數(shù)中會聲明針對 哪個模擬函數(shù),也就是說是準(zhǔn)備哪個模擬函數(shù)所需的參數(shù)。
[0032]在一些實(shí)例中,考慮針對不同類型的模擬函數(shù),參數(shù)準(zhǔn)備的處理會有不同,上述步 驟101中,可以進(jìn)一步根據(jù)模擬函數(shù)的類型創(chuàng)建相應(yīng)類型的參數(shù)準(zhǔn)備函數(shù),測試用例中包括 的參數(shù)準(zhǔn)備函數(shù)與其中模擬函數(shù)的類型相應(yīng)。也就是說,會創(chuàng)建多個類型的參數(shù)準(zhǔn)備函數(shù)。 在創(chuàng)建測試用例時,根據(jù)其中模擬函數(shù)的類型而采用相應(yīng)類型的參數(shù)準(zhǔn)備函數(shù)。
[0033]在一些實(shí)例中,所述模擬函數(shù)的類型為其調(diào)用約定的類型。這里,函數(shù)調(diào)用約定主 要約束了兩點(diǎn):參數(shù)傳遞順序、調(diào)用堆棧由誰(調(diào)用函數(shù)或被調(diào)用函數(shù))清理。比如:可以有 以下幾種類型:
[0034] Dcdecl方式的函數(shù),其調(diào)用約定為:所有參數(shù)從右到左依次入棧,這些參數(shù)由調(diào) 用者清除,稱為手動清棧。具體所示:調(diào)用方的函數(shù)調(diào)用_>被調(diào)用函數(shù)的執(zhí)行_>被調(diào)用函數(shù) 的結(jié)果返回_>調(diào)用方清除調(diào)整堆棧。
[0035] 2)stdcall方式的函數(shù),其調(diào)用約定為:所有參數(shù)從右到左依次入棧,如果是調(diào)用 類成員的話,最后一個入棧的是this指針。具體所示:調(diào)用方的函數(shù)調(diào)用_>被調(diào)用函數(shù)的執(zhí) 行_>被調(diào)用方清除調(diào)整堆棧_>被調(diào)用函數(shù)的結(jié)果返回。
[0036] 3)thiscall方式的函數(shù),其調(diào)用約定為:把this指針放在特定寄存器中,該寄存器 由編譯器決定。VC使用ecx,Borland的C++編譯器使用eax。返回方式和stdcall方式相當(dāng)。
[0037] 在一些實(shí)例中,可以給出以下表格中列出的四種參數(shù)準(zhǔn)備函數(shù)。
[0038]
[0039] 在一些實(shí)例中,通過執(zhí)行中間函數(shù)來確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其 所屬類的對象指針的處理,具體包括:
[0040] 1)找到調(diào)用該被測函數(shù)的指令的下一條指令的地址;通過該下一條指令的地址找 到該被測函數(shù)的地址。
[0041] 2)根據(jù)該被測函數(shù)的地址確定對應(yīng)的模擬函數(shù)的地址和對象指針。
[0042] 其中,上述參數(shù)準(zhǔn)備函數(shù)獲取的所述參數(shù)、所確定的模擬函數(shù)的地址和對象指針 被放入堆棧。
[0043] 進(jìn)一步的,在堆棧中保存該模擬函數(shù)的返回值,并做棧平衡。
[0044] 這里,上述地址、參數(shù)和對象指針可以從堆棧中讀取到。堆棧是計(jì)算機(jī)為程序開辟 的一塊內(nèi)存區(qū)域。其中,棧(stack)用來保存狀態(tài)數(shù)據(jù),其訪問順序是后進(jìn)先出(LIF0)。例 如:過程或函數(shù)的地址,參數(shù),有時候還包括局部變量;堆(heap)用來保存那些在運(yùn)行時才 知道其存在與大小的數(shù)據(jù);程序能夠從堆中分配內(nèi)存給這些元素;在用完之后,應(yīng)該釋放掉 這些內(nèi)存。
[0045] 在一些實(shí)例,該方法的測試環(huán)境基于X86系統(tǒng),可進(jìn)一步包括如下處理:
[0046] 將所確定的對象指針傳入預(yù)設(shè)的用于傳遞對象指針的寄存器,并根據(jù)該被測函數(shù) 對應(yīng)的模擬函數(shù)所需的參數(shù)的個數(shù)做堆棧調(diào)整,以使能夠基于該寄存器和當(dāng)前堆棧調(diào)用該 模擬函數(shù)并能讀取到該模擬函數(shù)所需的參數(shù)。這里,所謂當(dāng)前對象指針指的是當(dāng)前要調(diào)用 的程序的對象指針。上述確定的對象指針被傳入ECX寄存器。比如,在Windows系統(tǒng)中默認(rèn)將 this指針保存在ECX寄存器中,這樣,中間函數(shù)可以通過ECX寄存器讀取到當(dāng)前要調(diào)用的模 擬函數(shù)的this指針進(jìn)而能夠調(diào)用該模擬函數(shù)。
[0047] 在一些實(shí)例中,該方法的測試環(huán)境基于ARM系統(tǒng)(Linux系統(tǒng)、安卓系統(tǒng))??蛇M(jìn)一步 包括如下處理:
[0048] 1)將該模擬函數(shù)所需的參數(shù)傳入預(yù)設(shè)的用于傳遞函數(shù)參數(shù)的寄存器組(比如:R1 ~R3寄存器,共三個寄存器);其中,如果所需的參數(shù)的個數(shù)多于該寄存器組的寄存器數(shù)量, 則將所需參數(shù)中未能傳入該寄存器組的參數(shù)放入堆棧并作堆棧調(diào)整。
[0049] 2)將該對象指針傳入用于傳遞對象指針的寄存器(比如:R0寄存器)。
[0050] 3)將該模擬函數(shù)的地址傳入預(yù)設(shè)的用于保存當(dāng)前要跳轉(zhuǎn)的函數(shù)地址的寄存器(比 如:PC寄存器)。
[0051]圖2示出了本申請一基于X86系統(tǒng)的中間函數(shù)的處理流程圖。如圖2所示,當(dāng)中間函 數(shù)被調(diào)用時,執(zhí)行如下步驟:
[0052]步驟201~202:將當(dāng)前環(huán)境寄存器的參數(shù)壓棧,預(yù)留16字節(jié)??臻g用于存儲中間 變量。
[0053] 步驟203:確定當(dāng)前被測函數(shù)對應(yīng)的Mock函數(shù)(一種模擬函數(shù)),獲得該Mock函數(shù)的 對象指針(即this指針)并傳入ECX寄存器。
[0054]這里,考慮到可能同時存在多個函數(shù)被Mock (即同時有多個被測函數(shù)),此時中間 函數(shù)需要通過某種方法來計(jì)算得到應(yīng)該使用哪個Mock對象的this指針作為當(dāng)前被測函數(shù) 對應(yīng)的Mock函數(shù)的this指針。而要計(jì)算應(yīng)該使用哪個Mock對象的this指針,則需要知道被 測代碼原本要調(diào)用的是哪個函數(shù)(這個函數(shù)唯一對應(yīng)到一個Mock類的某個成員函數(shù))。由于 call指令會將call指令的下一條指令的地址(call指令執(zhí)行時EIP寄存器的值)push到棧上 (這是為了當(dāng)函數(shù)返回時知道從哪里繼續(xù)執(zhí)行),所以可以通過該信息(即call指令的下一 條指令的地址)作為key(對于ARM系統(tǒng),該信息為LR寄存器中的信息),記錄要調(diào)用的被測函 數(shù)和對應(yīng)的Mock函數(shù)的this指針。
[0055]步驟204:獲得該Mock函數(shù)的地址及其所需的參數(shù)并放入堆棧。
[0056]步驟205:根據(jù)該Mock函數(shù)所需的參數(shù)的個數(shù)做堆棧調(diào)整,以使調(diào)用該Mock函數(shù)時 能讀取到其所需的參數(shù)。
[0057] 步驟206:基于this指針、該Mock函數(shù)的地址和所需的參數(shù)調(diào)用該Mock函數(shù)。
[0058]步驟207:保存該Mock函數(shù)的返回值,做棧平衡并恢復(fù)寄存器。
[0059]圖3示出了本申請一基于ARM系統(tǒng)的中間函數(shù)的處理流程圖。如圖3所示,當(dāng)中間函 數(shù)被調(diào)用時,執(zhí)行如下步驟:
[0060] 步驟301~302:將當(dāng)前環(huán)境寄存器(R0-R12寄存器)的參數(shù)壓棧,預(yù)留20字節(jié)???間用于存儲中間變量。
[0061 ] 步驟303 :確定當(dāng)前被測函數(shù)對應(yīng)的Mock函數(shù),獲得該Mock函數(shù)的對象指針(BP this指針)、該Mock函數(shù)的地址和所需的參數(shù),并將其放入堆棧。
[0062]步驟304:判斷該被測函數(shù)是否為對象函數(shù)(即該被測函數(shù)是否有this指針),如果 是,則執(zhí)行步驟305;否則執(zhí)行步驟308。
[0063]步驟305:判斷該Mock函數(shù)所需的參數(shù)個數(shù)是否小于3,如果是,則執(zhí)行步驟306;否 則執(zhí)行步驟307。這里,用R0~R3寄存器來傳遞函數(shù)參數(shù)和this指針,其中,R0寄存器用于傳 遞this指針。
[0064]步驟306:從堆棧中讀取參數(shù)并放入R1~R3寄存器,將該Mock函數(shù)的this指針傳入 R0寄存器,之后執(zhí)行步驟311。
[0065]步驟307:從堆棧中讀取參數(shù)并放入R1~R3寄存器,將該Mock函數(shù)的this指針傳入 R0寄存器,調(diào)整堆棧,將所需的參數(shù)中還未放入寄存器的參數(shù)(即剩余參數(shù))壓棧,之后執(zhí)行 步驟311。
[0066] 步驟308:判斷該Mock函數(shù)所需的參數(shù)個數(shù)是否小于4,如果是,則執(zhí)行步驟309;否 則執(zhí)行步驟310。
[0067]步驟309:從堆棧中讀取參數(shù)(不包含之前壓棧的R0的參數(shù))并放入R1~R3寄存器, 將該Mock函數(shù)的this指針傳入R0寄存器,之后執(zhí)行步驟311。
[0068]步驟310:從堆棧中讀取參數(shù)(不包含之前壓棧的R0的參數(shù))并放入R1~R3寄存器, 將該Mock函數(shù)的this指針傳入R0寄存器,調(diào)整堆棧,將所需的參數(shù)中還未放入寄存器的參 數(shù)(即剩余參數(shù))壓棧。
[0069] 步驟311:將當(dāng)前要跳轉(zhuǎn)的函數(shù)地址(即步驟303確定的該Mock函數(shù)的地址)傳入PC 寄存器。
[0070] 步驟312:基于PC寄存器中的函數(shù)地址、R0~R3寄存器(或者進(jìn)一步包括堆棧)中該 Mock函數(shù)的thi s指針及所需的參數(shù),調(diào)用該Mock函數(shù)。
[0071] 步驟313:保存該Mock函數(shù)的返回值,并向調(diào)用被測函數(shù)的調(diào)用函數(shù)返回返回值, 做棧平衡和寄存器恢復(fù)。這里,對于ARM系統(tǒng)而言,是由調(diào)用原函數(shù)(即本申請的被測函數(shù)) 的調(diào)用函數(shù)跳轉(zhuǎn)到中間函數(shù)的,因此,中間函數(shù)需要向此調(diào)用函數(shù)返回返回值。
[0072]圖4A和4B分別示出了本申請?zhí)峁┑臏y試方法應(yīng)用于X86系統(tǒng)和ARM系統(tǒng)的實(shí)現(xiàn)框 圖。如圖4A和4B所示,被測程序(也稱為被測代碼)包括多個被測函數(shù)(被測函數(shù)1~被測函 數(shù)n),測試實(shí)例包括多個Mock函數(shù)(Mock函數(shù)1~Mock函數(shù)n)以及參數(shù)準(zhǔn)備函數(shù)。這里,測試 實(shí)例可能有多個,每一測試實(shí)例中的參數(shù)準(zhǔn)備函數(shù)也可能有多個。
[0073]如圖4A所示的X86系統(tǒng)的實(shí)現(xiàn)中,被測函數(shù)被注入了跳轉(zhuǎn)指令,當(dāng)被測函數(shù)1被調(diào) 用函數(shù)調(diào)用時,被測函數(shù)1基于此跳轉(zhuǎn)指令而調(diào)用中間函數(shù)(也稱為Hook到中間函數(shù)),之后 被測函數(shù)1向調(diào)用函數(shù)返回返回值。之后,中間函數(shù)基于前述的各種方法,確定該被測函數(shù)1 對應(yīng)的Mock函數(shù)1的對象指針和地址,通過測試實(shí)例中的參數(shù)準(zhǔn)備函數(shù)獲得了Mock函數(shù)1所 需的參數(shù),進(jìn)而能夠調(diào)用Mock函數(shù)1,使得Mock函數(shù)1與被測函數(shù)1進(jìn)行Mock操作并得到被測 函數(shù)1的返回值?;诒粶y函數(shù)1的各種返回值可以得到測試結(jié)果。
[0074]圖4B所示的ARM系統(tǒng)的實(shí)現(xiàn)與圖4A類似,區(qū)別主要在于對于中間函數(shù)的調(diào)用。在 ARM系統(tǒng)的實(shí)現(xiàn)中,調(diào)用被測函數(shù)的調(diào)用指令的跳轉(zhuǎn)地址被修改成中間函數(shù)的地址,當(dāng)被測 函數(shù)1被調(diào)用函數(shù)調(diào)用時,調(diào)用函數(shù)會基于該調(diào)用指令的跳轉(zhuǎn)地址而調(diào)用中間函數(shù),之后, 中間函數(shù)向調(diào)用函數(shù)返回返回值。
[0075]以下給出一個程序?qū)嵗?,其中包?被測函數(shù)、Mock類以及測試用例,其中,Mock類 中聲明了Mock函數(shù),測試用例中聲明了Mock類對象、對應(yīng)的Mock函數(shù)及其參數(shù)準(zhǔn)備函數(shù)、 Mock操作。
[0077]基于上述各方法實(shí)例,本申請還提出了一種計(jì)算機(jī)程序的測試裝置,如圖5所示, 該裝置包括配置模塊501、測試用例模塊502、跳轉(zhuǎn)模塊503、中間函數(shù)模塊504和測試結(jié)果模 塊505。
[0078]在一些實(shí)例中,各模塊的功能如下:
[0079] 配置模塊501創(chuàng)建中間函數(shù)和至少一個測試用例,其中,每一測試用例包括與至少 一個被測函數(shù)對應(yīng)的至少一個基于類的模擬函數(shù);在被測計(jì)算機(jī)程序中注入與至少一個被 測函數(shù)相關(guān)的跳轉(zhuǎn)指令。
[0080] 測試用例模塊502,包括上述至少一個測試用例;當(dāng)運(yùn)行一測試用例時,生成其中 模擬函數(shù)所屬類的對象指針。
[0081] 跳轉(zhuǎn)模塊503,述至少一個被測函數(shù)中的任一者被調(diào)用時,通過執(zhí)行與該被測函數(shù) 相關(guān)的跳轉(zhuǎn)指令而調(diào)用中間函數(shù)。
[0082]中間函數(shù)模塊504,包括上述中間函數(shù);當(dāng)此中間函數(shù)被調(diào)用時,通過執(zhí)行此中間 函數(shù),確定上述被調(diào)用的被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其所屬類的對象指針并調(diào)用該 對應(yīng)的模擬函數(shù)。
[0083]測試用例模塊502,當(dāng)上述模擬函數(shù)被調(diào)用時,通過執(zhí)行此模擬函數(shù),與被測函數(shù) 之間進(jìn)行交互,并獲得該被測函數(shù)的返回值。
[0084]測試結(jié)果模塊505,基于測試用例模塊502獲得的返回值確定測試結(jié)果。
[0085] 在一些實(shí)例中,上述測試用例進(jìn)一步包括至少一個參數(shù)準(zhǔn)備函數(shù),用于獲取該測 試用例中各模擬函數(shù)所需的參數(shù)。測試用例模塊502,當(dāng)運(yùn)行一測試用例時,進(jìn)一步通過執(zhí) 行其中的參數(shù)準(zhǔn)備函數(shù)來獲取其中模擬函數(shù)所需的參數(shù)。中間函數(shù)模塊504,進(jìn)一步通過執(zhí) 行上述中間函數(shù),進(jìn)一步讀取上述參數(shù)準(zhǔn)備函數(shù)獲取的該被測函數(shù)對應(yīng)的模擬函數(shù)所需的 參數(shù)。
[0086]在一些實(shí)例中,中間函數(shù)模塊504確定模擬函數(shù)地址和對象指針的方法為:找到調(diào) 用該被測函數(shù)的指令的下一條指令的地址,通過此下一條指令的地址找到該被測函數(shù)的地 址,并根據(jù)該被測函數(shù)的地址確定對應(yīng)的模擬函數(shù)的地址和對象指針。
[0087] 上述各個模塊實(shí)現(xiàn)各種功能的具體方法及原理在前文均有描述,這里不再贅述。 上述各個模塊可能位于一臺計(jì)算設(shè)備,也可能分布在多個計(jì)算設(shè)備中。
[0088] 另外,在本申請各個實(shí)例中的裝置及各模塊可以集成在一個處理單元中,也可以 是各個模塊單獨(dú)物理存在,也可以兩個或兩個以上裝置或模塊集成在一個單元中。上述集 成的單元既可以采用硬件的形式實(shí)現(xiàn),也可以采用軟件功能單元的形式實(shí)現(xiàn)。
[0089] 在一實(shí)施例中,上述的測試裝置可運(yùn)行在任一用于媒體推送控制的計(jì)算設(shè)備中, 并加載在該計(jì)算設(shè)備的存儲器中。如圖5所示,該計(jì)算設(shè)備除了包括上述控制裝置中的各個 模塊,還可包括:存儲器511、處理器513、總線512、端口 514。處理器513和存儲器511通過總 線512互聯(lián)。處理器513可通過端口 514接收和發(fā)送數(shù)據(jù)以實(shí)現(xiàn)網(wǎng)絡(luò)通信和/或本地通信。上 述各模塊501~405可以是存儲器501中存儲的機(jī)器可執(zhí)行指令模塊。處理器503通過執(zhí)行存 儲器501中各模塊501~505中包含的機(jī)器可執(zhí)行指令,進(jìn)而能夠?qū)崿F(xiàn)上述各模塊501~505 的功能。
[0090] 另外,本申請的每個實(shí)例可以通過由數(shù)據(jù)處理設(shè)備如計(jì)算機(jī)執(zhí)行的數(shù)據(jù)處理程序 來實(shí)現(xiàn)。顯然,數(shù)據(jù)處理程序構(gòu)成了本發(fā)明。此外,通常存儲在一個存儲介質(zhì)中的數(shù)據(jù)處理 程序通過直接將程序讀取出存儲介質(zhì)或者通過將程序安裝或復(fù)制到數(shù)據(jù)處理設(shè)備的存儲 設(shè)備(如硬盤和/或內(nèi)存)中執(zhí)行。因此,這樣的存儲介質(zhì)也構(gòu)成了本發(fā)明。存儲介質(zhì)可以使 用任何類型的記錄方式,例如紙張存儲介質(zhì)(如紙帶等)、磁存儲介質(zhì)(如軟盤、硬盤、閃存 等)、光存儲介質(zhì)(如CD-ROM等)、磁光存儲介質(zhì)(如M0等)等。
[0091] 因此,本申請還提供了一種非易失性存儲介質(zhì),其中存儲有數(shù)據(jù)處理程序,該數(shù)據(jù) 處理程序用于執(zhí)行本申請上述方法的任何一種實(shí)例。
[0092] 以上所述僅為本發(fā)明的較佳實(shí)施例而已,并不用以限制本發(fā)明,凡在本發(fā)明的精 神和原則之內(nèi),所做的任何修改、等同替換、改進(jìn)等,均應(yīng)包含在本發(fā)明保護(hù)的范圍之內(nèi)。
【主權(quán)項(xiàng)】
1. 一種計(jì)算機(jī)程序的測試方法,其特征在于,所述方法包括: 創(chuàng)建中間函數(shù)和至少一個測試用例,其中,每一測試用例包括與至少一個被測函數(shù)對 應(yīng)的至少一個基于類的模擬函數(shù); 在所述被測計(jì)算機(jī)程序中注入與至少一個被測函數(shù)相關(guān)的跳轉(zhuǎn)指令; 所述方法還包括: 當(dāng)運(yùn)行一測試用例時,生成該測試用例中所述模擬函數(shù)所屬類的對象指針; 當(dāng)所述至少一個被測函數(shù)中的任一者被調(diào)用時,通過執(zhí)行與該被測函數(shù)相關(guān)的所述跳 轉(zhuǎn)指令而調(diào)用所述中間函數(shù); 當(dāng)所述中間函數(shù)被調(diào)用時,通過執(zhí)行所述中間函數(shù),確定該被測函數(shù)對應(yīng)的模擬函數(shù) 的地址及其所屬類的對象指針并調(diào)用所述對應(yīng)的模擬函數(shù); 當(dāng)所述模擬函數(shù)被調(diào)用時,通過執(zhí)行所述模擬函數(shù),與所述被測函數(shù)之間進(jìn)行交互,并 獲得所述被測函數(shù)的返回值;及 基于所述返回值確定測試結(jié)果。2. 根據(jù)權(quán)利要求1所述的方法,其中,所述測試用例進(jìn)一步包括至少一個參數(shù)準(zhǔn)備函 數(shù),用于獲取所述測試用例中各模擬函數(shù)所需的參數(shù); 該方法還包括: 當(dāng)運(yùn)行一測試用例時,通過執(zhí)行其中的所述參數(shù)準(zhǔn)備函數(shù)來獲取其中所述模擬函數(shù)所 需的參數(shù); 通過執(zhí)行所述中間函數(shù),進(jìn)一步讀取所述參數(shù)準(zhǔn)備函數(shù)獲取的該被測函數(shù)對應(yīng)的模擬 函數(shù)所需的參數(shù)。3. 根據(jù)權(quán)利要求2所述的方法,進(jìn)一步包括:根據(jù)模擬函數(shù)的類型創(chuàng)建相應(yīng)類型的參數(shù) 準(zhǔn)備函數(shù); 所述測試實(shí)例中包括的參數(shù)準(zhǔn)備函數(shù)與其中模擬函數(shù)的類型相應(yīng)。4. 根據(jù)權(quán)利要求3所述的方法,其中,所述模擬函數(shù)的類型為所述模擬函數(shù)的調(diào)用約定 的類型。5. 根據(jù)權(quán)利要求2所述的方法,其中,所述確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其 所屬類的對象指針,包括: 找到調(diào)用該被測函數(shù)的指令的下一條指令的地址; 通過所述下一條指令的地址找到該被測函數(shù)的地址;及 根據(jù)該被測函數(shù)的地址確定所述對應(yīng)的模擬函數(shù)的地址和所述對象指針。6. 根據(jù)權(quán)利要求2所述的方法,其中,該方法的測試環(huán)境基于X86系統(tǒng); 其中,所確定的所述對應(yīng)的模擬函數(shù)的地址、所述對象指針、所需的參數(shù)被放入堆棧; 該方法進(jìn)一步包括: 將所述對象指針傳入預(yù)設(shè)的用于傳遞對象指針的寄存器;根據(jù)所述模擬函數(shù)所需的參 數(shù)的個數(shù)做堆棧調(diào)整。7. 根據(jù)權(quán)利要求2所述的方法,其中,該方法的測試環(huán)境基于ARM系統(tǒng); 其中,所確定的所述對應(yīng)的模擬函數(shù)的地址、所述對象指針、所需的參數(shù)被放入堆棧; 該方法進(jìn)一步包括:將所述模擬函數(shù)所需的參數(shù)傳入預(yù)設(shè)的用于傳遞函數(shù)參數(shù)的寄存 器組;其中,如果所需的參數(shù)的個數(shù)多于所述寄存器組的寄存器數(shù)量,則將所需參數(shù)中未能 傳入所述寄存器組的參數(shù)放入堆棧并作堆棧調(diào)整; 將所述對象指針傳入用于傳遞對象指針的寄存器;及 將所述模擬函數(shù)的地址傳入預(yù)設(shè)的用于保存當(dāng)前要跳轉(zhuǎn)的函數(shù)地址的寄存器。8. 根據(jù)權(quán)利要求1至7任一項(xiàng)所述的方法,其中,所述模擬函數(shù)所屬的類未繼承自其它 類。9. 一種計(jì)算機(jī)程序的測試裝置,其特征在于,所述裝置包括: 配置模塊,創(chuàng)建中間函數(shù)和至少一個測試用例,其中,每一測試用例包括與至少一個被 測函數(shù)對應(yīng)的至少一個基于類的模擬函數(shù);在所述被測計(jì)算機(jī)程序中注入與至少一個被測 函數(shù)相關(guān)的跳轉(zhuǎn)指令; 所述裝置還包括: 測試用例模塊,包括所述至少一個測試用例;當(dāng)運(yùn)行一測試用例時,生成該測試用例中 所述模擬函數(shù)所屬類的對象指針; 跳轉(zhuǎn)模塊,當(dāng)所述至少一個被測函數(shù)中的任一者被調(diào)用時,通過執(zhí)行與該被測函數(shù)相 關(guān)的所述跳轉(zhuǎn)指令而調(diào)用所述中間函數(shù); 中間函數(shù)模塊,包括所述中間函數(shù);當(dāng)所述中間函數(shù)被調(diào)用時,通過執(zhí)行所述中間函 數(shù),確定該被測函數(shù)對應(yīng)的模擬函數(shù)的地址及其所屬類的對象指針并調(diào)用所述對應(yīng)的模擬 函數(shù); 所述測試用例模塊,當(dāng)所述模擬函數(shù)被調(diào)用時,通過執(zhí)行所述模擬函數(shù),與所述被測函 數(shù)之間進(jìn)行交互,并獲得所述被測函數(shù)的返回值;及 測試結(jié)果模塊,基于所述返回值確定測試結(jié)果。10. 根據(jù)權(quán)利要求9所述的裝置,其中,所述測試用例進(jìn)一步包括至少一個參數(shù)準(zhǔn)備函 數(shù),用于獲取所述測試用例中各模擬函數(shù)所需的參數(shù); 所述測試用例模塊,當(dāng)運(yùn)行一測試用例時,進(jìn)一步通過執(zhí)行其中的所述參數(shù)準(zhǔn)備函數(shù) 來獲取其中所述模擬函數(shù)所需的參數(shù); 所述中間函數(shù)模塊,進(jìn)一步通過執(zhí)行所述中間函數(shù),進(jìn)一步讀取所述參數(shù)準(zhǔn)備函數(shù)獲 取的該被測函數(shù)對應(yīng)的模擬函數(shù)所需的參數(shù)。11. 根據(jù)權(quán)利要求9或10所述的裝置,其中,所述中間函數(shù)模塊,找到調(diào)用該被測函數(shù)的 指令的下一條指令的地址;通過所述下一條指令的地址找到該被測函數(shù)的地址;及根據(jù)該 被測函數(shù)的地址確定所述對應(yīng)的模擬函數(shù)的地址和所述對象指針。
【文檔編號】G06F11/36GK106055481SQ201610389734
【公開日】2016年10月26日
【申請日】2016年6月2日
【發(fā)明人】江濤, 劉華星
【申請人】騰訊科技(深圳)有限公司