黃仁歡
摘要:Qt是一個開源的、跨平臺的C++圖形用戶界面應(yīng)用程序開發(fā)框架,使用其開發(fā)的應(yīng)用軟件可以按照代碼走查、靜態(tài)檢查、覆蓋率統(tǒng)計(jì)、單元測試、軟件集成測試的測試步驟進(jìn)行測試,有利于排查潛在的代碼缺陷和故障,提高代碼質(zhì)量和健壯性。該文將闡述這一測試過程所使用的方法,總結(jié)實(shí)測經(jīng)驗(yàn),為軟件測試人員提供借鑒。
關(guān)鍵詞:代碼走查;覆蓋率統(tǒng)計(jì);單元測試;軟件測試實(shí)踐;Qt應(yīng)用程序測試
中圖分類號:TP311? ? ? 文獻(xiàn)標(biāo)識碼:A
文章編號:1009-3044(2021)16-0070-03
開放科學(xué)(資源服務(wù))標(biāo)識碼(OSID):
1 概述
Qt作為現(xiàn)階段流行的跨平臺C++圖形用戶界面應(yīng)用程序開發(fā)框架,它的軟件開發(fā)遵循著一般軟件開發(fā)的正常流程,其開發(fā)生命周期按照可行性研究報(bào)告、需求分析、風(fēng)險(xiǎn)分析、架構(gòu)設(shè)計(jì)、組件設(shè)計(jì)、實(shí)現(xiàn)與測試、驗(yàn)證與確認(rèn)、部署與維護(hù)8個階段進(jìn)行。缺少任一環(huán)節(jié),那么這個軟件都是不完整的,不能投入市場進(jìn)行部署運(yùn)營。而軟件測試,是保障軟件質(zhì)量最重要、最有效的方法[2]。作為一個優(yōu)秀的、跨平臺的應(yīng)用程序開發(fā)框架,由它進(jìn)行編碼的軟件,也需要經(jīng)過嚴(yán)格的、全面的、多方位的測試過程,從而發(fā)現(xiàn)和消除軟件內(nèi)部隱藏的故障,只有這樣,軟件才會通過完整性、充分性測試。
本文涉及的項(xiàng)目需要通過SIL2等級的功能安全認(rèn)證,由于項(xiàng)目本身只是一個應(yīng)用層軟件,在進(jìn)行SIL2認(rèn)證工作時(shí)不考慮硬件相關(guān)的因素,根據(jù)既有的軟件開發(fā)的流程及參照《EN50128-2011》標(biāo)準(zhǔn)中對通用軟件開發(fā)的要求,對軟件開發(fā)的生命周期進(jìn)行了微調(diào),并且注重軟件的測試方法、過程和細(xì)節(jié)。
2 測試過程
軟件編碼人員根據(jù)詳細(xì)設(shè)計(jì)文檔進(jìn)行代碼編寫,遵照模塊劃分圖、UML類圖、接口定義將軟件功能逐步實(shí)現(xiàn),開發(fā)者會進(jìn)行基本的功能驗(yàn)證工作,保證程序運(yùn)行正常和功能完整,然后將代碼提交SVN歸檔,完成開發(fā)工作。此后,便進(jìn)入代碼的測試階段。
針對Qt應(yīng)用程序軟件測試的不同階段,可以將測試過程劃分為代碼走查,靜態(tài)檢查,單元測試,覆蓋率統(tǒng)計(jì),集成測試五大階段,這些階段具有先后順序,上一個階段完成后才可以開展下一個階段的工作。
2.1 代碼走查
代碼走查是以組為單位對代碼進(jìn)行審查,是一系列規(guī)程和錯誤檢查技術(shù)的集合。在實(shí)際工作過程中,代碼走查是最容易被開發(fā)者或測試者省略的一個階段[3]。開展代碼走查工作具有一定難度的,原因有以下兩種:首先,代碼走查人員如何安排;其次,問題排查難及驗(yàn)收標(biāo)準(zhǔn)模糊。代碼走查的意識和重要性往往被項(xiàng)目負(fù)責(zé)人忽視,這往往是不可取的。
在我們的項(xiàng)目中采取交叉走查的方式,即開發(fā)者A對開發(fā)者B的代碼進(jìn)行走查,開發(fā)者B對開發(fā)者C的代碼進(jìn)行走查,開發(fā)者C對開發(fā)者A的代碼進(jìn)行走查。走查的內(nèi)容分為三大塊:
1)對注釋進(jìn)行走查;文件的注釋走查,需簡述文件要實(shí)現(xiàn)的功能、作者、修改日期等;函數(shù)的注釋走查,需描述函數(shù)的功能,參數(shù)含義,返回值信息等;變量的注釋走查,簡述變量的內(nèi)容;注釋風(fēng)格的走查,嚴(yán)格使用Doxygen風(fēng)格注釋,保證后期可通過Doxygen插件自動生成項(xiàng)目源代碼幫助文檔;
2)對代碼的邏輯結(jié)構(gòu)進(jìn)行走查;每個走查者參照詳細(xì)設(shè)計(jì)文檔,找到每一個功能點(diǎn)對應(yīng)的實(shí)現(xiàn)代碼,逐行解釋程序的數(shù)據(jù)結(jié)構(gòu)、邏輯和調(diào)用關(guān)系,使某一個功能的實(shí)現(xiàn)方法與其他成員想法達(dá)成一致;
3)對異常處理的走查;包括運(yùn)算錯誤異常走查、接口異常走查、輸入/輸出異常走查及重點(diǎn)數(shù)據(jù)的異常走查。
走查結(jié)果以表格的形式輸出,包含走查問題類型、問題個數(shù)及問題占比;并且記錄走查的工時(shí),包含走查時(shí)間、問題修改時(shí)間、驗(yàn)證時(shí)間。
2.2 靜態(tài)檢查
靜態(tài)檢查是指不需要編譯運(yùn)行源代碼本身,僅通過分析或檢查源代碼的語法、結(jié)構(gòu)、過程、接口等來檢查程序的正確性。開展靜態(tài)檢查的依據(jù)是基于業(yè)界認(rèn)可或者標(biāo)準(zhǔn)化的規(guī)范,對于基于C++的Qt開發(fā)框架來說,目前我們采用的是汽車工業(yè)軟件可靠性協(xié)會于2008年發(fā)布的《MISRA C++:2008》編碼規(guī)范。
C++Test是Parasoft公司開發(fā)的一個針對C/C++源代碼進(jìn)行自動化測試的一個工具,它可以對源代碼進(jìn)行三種測試:白盒測試、黑盒測試以及回歸測試。此外,它還支持對源代碼進(jìn)行靜態(tài)檢查。
在Qt編譯的Debug目錄下,打開Makefile.Debug文件,添加如下代碼:
CC? = cpptestscan gcc
CXX = cpptestscan g++
重新編譯后,會生成一個bdf文件。由C++Test工具創(chuàng)建測試工程并導(dǎo)入該bdf文件,選擇與Qt相同版本的編譯器,設(shè)置靜態(tài)檢查規(guī)則,我們選擇《MISRAC++2008》規(guī)則239條加上《Qt最佳實(shí)踐》規(guī)則8條,值得一提的是,除了上述的247規(guī)則外,作為代碼復(fù)雜度的衡量標(biāo)準(zhǔn)-圈復(fù)雜度并不在其中,因此,通過過濾器搜索將圈復(fù)雜度限制在20之內(nèi)的規(guī)則勾選,總共依據(jù)248條規(guī)則對項(xiàng)目軟件進(jìn)行靜態(tài)檢查測試,然后執(zhí)行靜態(tài)測試。在結(jié)果輸出窗體欄的質(zhì)量任務(wù)可查看測試結(jié)果及對應(yīng)的違規(guī)說明、案例示范,方便開發(fā)人員修正。最后,該工具會生成一個靜態(tài)檢查的報(bào)告文檔。
2.3 單元測試
軟件單元測試是通過編寫測試用例對一個模塊、一個函數(shù)或者一個類來進(jìn)行正確性驗(yàn)證的測試工作。對C++來說,通常是面向?qū)ο蟮木幊谭绞?,所以我們以單個類為一個測試單元,然后再對類內(nèi)的函數(shù)逐一測試。QTest是Qt提供的一種簡單易用的單元測試框架,它不僅提供了單元測試框架的基本功能,還針對GUI(圖形用戶界面)的測試進(jìn)行了擴(kuò)展,如對鍵盤輸入事件、鼠標(biāo)點(diǎn)擊事件等進(jìn)行了模擬;并且QTest可以與Qt的工具鏈、基礎(chǔ)類庫、應(yīng)用框架、集成開發(fā)環(huán)境(IDE)等良好地結(jié)合。
在QtCreator新建工程時(shí)選擇QTest單元測試工程,以子工程pri的形式導(dǎo)入源代碼工程;其次,針對每一個源代碼文件xxx.cpp,都創(chuàng)建與之對應(yīng)的單元測試文件,命名為tst_xxx.cpp,使得每一個測試文件都可以通過修改測試入口函數(shù)(QTEST_MAIN(類名))進(jìn)行獨(dú)立測試;然后基于每個函數(shù)的代碼內(nèi)容編寫測試用例。
正常值測試:測試用例設(shè)置的值在數(shù)據(jù)類型的范圍內(nèi),例如,字符串類型的數(shù)據(jù),可以設(shè)置為“abc”,整型類型的數(shù)據(jù),可以設(shè)置為123,對于確定數(shù)值范圍的情況,還可以取數(shù)值的中間值進(jìn)行測試;
邊界值測試:這類型的測試用例需要清楚的知道數(shù)據(jù)的上限和下限,取臨界點(diǎn)數(shù)據(jù)的左值和右值作為用例的數(shù)據(jù),例如涉及旋轉(zhuǎn)的角度問題,上限為360°,下限為0°,在設(shè)計(jì)邊界值用例時(shí),這個案例有4個邊界值數(shù)據(jù),即361°、359°、1°和-1°,要測試超出合理數(shù)據(jù)范圍內(nèi)的數(shù)值程序如何處理,是否有異常機(jī)制;
路徑測試:也叫分支測試,是指程序代碼中使用if…else、do…while、switch…case等關(guān)鍵字時(shí)需要編寫的用例測試,通過改變控制語句的值,從而執(zhí)行不同的代碼。
異常測試:異常測試包含的范圍比較廣泛,所有不應(yīng)該出現(xiàn)的情況都屬于異常的范疇,在這里我們重點(diǎn)關(guān)注數(shù)據(jù)的異常,一個是開發(fā)者對數(shù)值運(yùn)算產(chǎn)生的異常值,一個是用戶輸入的數(shù)據(jù)異常,在設(shè)計(jì)測試用例時(shí)需要輸入異常數(shù)據(jù)來檢驗(yàn)程序是否對異常數(shù)據(jù)進(jìn)行處理。
QTest框架通過QCOMPARE宏來比較單元用例中期望值與實(shí)際值是否相等,從而判定該條用例是否測試通過,當(dāng)兩個值相等時(shí),表明測試通過,否則,測試不通過。
2.4 覆蓋率統(tǒng)計(jì)
在單元測試用例工程之后,我們可以進(jìn)行覆蓋率統(tǒng)計(jì)。通過代碼覆蓋率審查,可以發(fā)現(xiàn)程序的未測試部分代碼,并且知道程序中哪一段代碼最耗時(shí),能有效地幫助開發(fā)人員重構(gòu)代碼,以提高代碼質(zhì)量[5]。
代碼覆蓋率統(tǒng)計(jì)主要流程:
1)對單元測試工程增加編譯參數(shù);
LIBS += -lgcov
QMAKE_CXXFLAGS += --coverage
2)重新編譯單元測試工程文件,生成gcno文件;
gcno文件包含重建基本塊圖和相應(yīng)的塊的源碼的行號信息。
3)運(yùn)行單元測試程序,生成gcda文件;
gcda文件包含弧跳變的次數(shù)和其他的概要信息。
4)使用gcov工具,生成gcov文件;
gcov文件包含代碼覆蓋率信息,但是可讀性較差。
為了對代碼覆蓋率的快速分析,有必要對覆蓋率信息進(jìn)行可視化輸出。基于以上的流程,增加以下步驟:
5)使用lcov工具,生成info文件;
info文件包含一個或多個源代碼文件所對應(yīng)的覆蓋率信息,但是可讀性較差
6)使用ghtml命令,生成html文件
html文件是我們想要的可視化輸出文件,如圖3所示。
從圖中我們可以清晰明了地看到源代碼的覆蓋率,包括行覆蓋、函數(shù)覆蓋及分支覆蓋信息。對于每一個文件,還可以精確的看的哪一行代碼、哪一個分支沒有覆蓋。這助于引導(dǎo)測試人員設(shè)計(jì)更合理的用例,實(shí)現(xiàn)代碼覆蓋,這對提高代碼質(zhì)量有著重大的作用。
由于lcov工具與Windows平臺不兼容,考慮到Qt框具有的跨平臺特性,將Windows下的Qt應(yīng)用程序的源代碼、編譯生成的gcno、gcda文件放到Linux平臺下,使用lcov工具生成info文件,該info文件會包含Windows平臺下的路徑,因此,需要對info文件進(jìn)行如下修改:
1)刪除包含第三方庫的信息;
2)刪除包含Qt源碼的信息;
3)將源代碼路徑修改成Linux風(fēng)格的路徑。
最后,再使用ghtml工具生成html文件,也能實(shí)現(xiàn)圖3的可視化輸出效果。
如果發(fā)現(xiàn)源代碼有未被測試用例覆蓋的行,需要進(jìn)行編寫單元測試用例,使其覆蓋。在我們的項(xiàng)目中,只需要滿足行覆蓋和函數(shù)覆蓋即可,分支覆蓋要求則更高,在這里不進(jìn)行展開描述。
2.5 軟件集成測試
軟件集成測試是軟件測試中處于組件測試和系統(tǒng)測試之間一個非常重要的環(huán)節(jié),這是因?yàn)樗薪M件都經(jīng)過單元測試并能正常運(yùn)行并不意味著這些組件放到一起經(jīng)過集成后還能正常運(yùn)行[7]。
軟件集成測試的依據(jù)是系統(tǒng)的概要設(shè)計(jì)文檔,概要設(shè)計(jì)文檔定義了的所有公共接口,需要將各個接口模塊串聯(lián)起來形成一個個獨(dú)立的功能點(diǎn),也是我們要設(shè)計(jì)的測試用例,用來覆蓋系統(tǒng)需求規(guī)范里的功能。軟件集成測試過程如圖4所示。
與單元測試的測試用例不同的是,軟件集成測試需要多個模塊間相互配合,模塊間有數(shù)據(jù)交互,形成數(shù)據(jù)流,由數(shù)據(jù)驅(qū)動達(dá)到某個功能點(diǎn)的測試目的。集成測試的實(shí)施方案有多種,如自底向上集成測試法、自頂向下集成測試法、三明治集成測試法等。對于Qt應(yīng)用程序的軟件集成測試,同樣可以使用QTest框架進(jìn)行測試,工程創(chuàng)建、用例編寫、測試執(zhí)行、結(jié)果審查等都與單元測試過程一樣,此處不再贅述。
2.6 回歸測試
在軟件生命周期的任何一個階段,只要軟件代碼發(fā)生了改動,我們就必須重新測試現(xiàn)有的功能,以便確定修改是否達(dá)到了目的[8],這就是回歸測試。進(jìn)行回歸測試時(shí),需要重新對用例庫進(jìn)行審查,比如:1)修正不適用的測試用例;2)刪除冗余的測試用例;3)增加與新需求相適應(yīng)的測試用例??捎糜诨貧w的測試用例準(zhǔn)備完成后,應(yīng)對回歸測試的范圍進(jìn)行評估,使用恰當(dāng)?shù)姆椒ㄟM(jìn)行測試,常用的回歸測試方法有:1)全用例再測試;2)基于風(fēng)險(xiǎn)進(jìn)行測試;3)基于操作進(jìn)行測試;4)僅測試修改部分。
回歸測試是一個不斷按照“計(jì)劃->執(zhí)行->檢查->改進(jìn)”過程進(jìn)行的工作,每一輪的測試結(jié)果恰好可以作為下一輪回歸的依據(jù),以使得回歸測試更精準(zhǔn)和高效。
3 結(jié)束語
本文闡述了一個完整的軟件測試過程,通過該過程可以有效的發(fā)現(xiàn)和挖掘可能存在的錯誤和異常,能提高軟件的質(zhì)量和保證軟件的安全,這一軟件測試過程被成功應(yīng)用于功能安全認(rèn)證SIL2等級的認(rèn)證中。
一個軟件產(chǎn)品的上線,除了以上闡述的軟件測試階段的所必需方法,還需要通過嚴(yán)格的系統(tǒng)集成測試階段、驗(yàn)收測試階段,這樣才能保證軟件能夠滿足用戶的需求。本文的立腳點(diǎn)是傳統(tǒng)軟件行業(yè)的測試,對于互聯(lián)網(wǎng)、手持終端的軟件測試,上述列舉的測試過程不一定適用,這是本文的欠缺之處。
參考文獻(xiàn):
[1] 朱健.基于Qt Test的自動化單元測試[J].價(jià)值工程,2017,36(14):216-219.
[2] 鞠秀娟,趙明.軟件自動化測試概述及應(yīng)用工具分析[J].計(jì)算機(jī)應(yīng)用,2007(S1):317-318,321.
[3] 周玫.有效開展代碼走查工作的實(shí)踐過程分析[J].現(xiàn)代信息科技,2019,3(1):190-191.
[4] 毛子晏.對計(jì)算機(jī)軟件測試技術(shù)的幾點(diǎn)探討[J].電腦知識與技術(shù),2020,16(18):77-79.
[5] 朱少民.全程軟件測試[M].3版.北京:人民郵電出版社,2019.
[6] Jorgensen P C.基于模型的測試:一個軟件工藝師的方法[M]. 王軼辰,王軼昆,曹志欽,譯.北京:機(jī)械工業(yè)出版社,2019.
[7] 侯艷芳,楚書來.探析軟件測試之集成測試[J].計(jì)算機(jī)光盤軟件與應(yīng)用,2012(3):78-79.
[8] 李龍,黎連業(yè).軟件測試實(shí)用技術(shù)與常用模板[M].北京:機(jī)械工業(yè)出版社,2018.
【通聯(lián)編輯:謝媛媛】