高效的敏捷测试第八课 静态测试工具和生成测试报告
第18講:增加自動(dòng)的靜態(tài)測(cè)試和測(cè)試報(bào)告生成功能
在之前的講解里,我曾經(jīng)提到過,靜態(tài)測(cè)試的對(duì)象包括需求、設(shè)計(jì)和代碼,也提到過代碼審查的兩種方式:一種是人工評(píng)審,另一種是基于工具的自動(dòng)靜態(tài)測(cè)試。在?CI?環(huán)境中我們可以通過?GitHub?的?Pull Request?特性來(lái)進(jìn)行代碼的人工評(píng)審。這一講,我將帶你學(xué)習(xí)自動(dòng)的靜態(tài)測(cè)試方法、工具和靜態(tài)測(cè)試報(bào)告,以及自動(dòng)化測(cè)試報(bào)告的生成。
代碼分析(靜態(tài)測(cè)試)
代碼的靜態(tài)測(cè)試,也叫靜態(tài)分析,它不需要運(yùn)行應(yīng)用程序就可以對(duì)軟件代碼進(jìn)行檢查,并找出其中的缺陷。自動(dòng)靜態(tài)測(cè)試是指利用靜態(tài)分析工具對(duì)代碼進(jìn)行自動(dòng)掃描發(fā)現(xiàn)缺陷的技術(shù),相對(duì)人工評(píng)審來(lái)說(shuō),它不需要投入太多人力就可以發(fā)現(xiàn)代碼中的缺陷,是效率比較高的代碼審查方式。
自動(dòng)靜態(tài)分析方法一般能夠發(fā)現(xiàn)代碼中的下列問題。
代碼結(jié)構(gòu)問題:重復(fù)性代碼、高度耦合的代碼等。
實(shí)現(xiàn)問題:資源泄漏、空指針引用、死循環(huán)、緩沖區(qū)溢出等。
可讀性差、不規(guī)范的問題:有些代碼沒有縮進(jìn)、變量在使用前未定義等。
這些功能對(duì)于查找一些代碼的安全漏洞缺陷特別實(shí)用,比如有些程序如果接收到超出緩沖區(qū)的數(shù)據(jù)和參數(shù),就會(huì)導(dǎo)致緩沖區(qū)溢出,攻擊者利用精心構(gòu)造的溢出數(shù)據(jù)就可以讓程序執(zhí)行其惡意代碼,從而獲得系統(tǒng)的控制權(quán),達(dá)到入侵系統(tǒng)的目的。如果在研發(fā)階段不能發(fā)現(xiàn)此類問題,上線后可能會(huì)造成重大的信息安全事故。比如?2003?年美國(guó)?Davis-Besse?核電站受到?Slammer?蠕蟲攻擊,就是因?yàn)槌绦蛑械木彌_區(qū)溢出漏洞被黑客利用而造成的。
要實(shí)現(xiàn)自動(dòng)的靜態(tài)測(cè)試,團(tuán)隊(duì)需要完成以下幾方面的工作。
?
首先需要選擇合適的靜態(tài)分析工具。對(duì)于自動(dòng)靜態(tài)測(cè)試,僅僅借助工具進(jìn)行測(cè)試還不夠,并且無(wú)論采用哪種工具,團(tuán)隊(duì)都需要一起定義掃描規(guī)則,使用統(tǒng)一的規(guī)則進(jìn)行靜態(tài)測(cè)試。比如在開發(fā)過程中對(duì)發(fā)現(xiàn)的代碼缺陷進(jìn)行總結(jié)、提煉或抽象,把這些代碼缺陷模式借助規(guī)則集、模型、解析樹、形式化方法等方式描述出來(lái),結(jié)合編程規(guī)范就形成了自定義的掃描規(guī)則。
其次,開發(fā)人員提交代碼前應(yīng)該先在本地開發(fā)環(huán)境里執(zhí)行靜態(tài)測(cè)試,結(jié)果可以做為人工評(píng)審(Code Review)的輸入項(xiàng)進(jìn)行分析,如果其中的典型或重大問題能讓團(tuán)隊(duì)成員知曉并討論如何避免,則可以有效地提高整個(gè)團(tuán)隊(duì)的代碼能力和質(zhì)量意識(shí)。
最后,將靜態(tài)測(cè)試工具集成在?CI?環(huán)境中,靜態(tài)測(cè)試將會(huì)成為持續(xù)集成活動(dòng)的一部分,并且自動(dòng)生成可視化的代碼分析報(bào)告,發(fā)送郵件通知開發(fā)人員進(jìn)行分析和修復(fù)工作。
優(yōu)秀的靜態(tài)分析工具
我們先從靜態(tài)分析工具開始講起,常用的工具有很多,這里只列出其中的一些,比如?Java 可以選擇?PMD、FindBugs?等,C/C++?語(yǔ)言可以選擇?C++ Test、CppTest、Splint?等,Python?語(yǔ)言可以選擇?Pylint、Pychecker、PyCharm?等。
FindBugs 通過檢查?JAR 文件,將字節(jié)碼與一組缺陷模式進(jìn)行對(duì)比,從而發(fā)現(xiàn)可能的代碼問題,它既提供可視化 UI 界面,同時(shí)也可以作為 Eclipse 或?IntelliJ DEA(簡(jiǎn)稱 IDEA)插件使用。FindBugs 還為用戶提供定制 Bug Pattern 的功能,用戶可以根據(jù)需求自定義 FindBugs 的代碼檢查條件。
PMD?可以檢查、分析 Java?源程序代碼,并通過內(nèi)置的編碼規(guī)則對(duì) Java 代碼進(jìn)行靜態(tài)檢查。同時(shí),它也支持開發(fā)人員對(duì)代碼檢查規(guī)范進(jìn)行自定義配置,主要檢驗(yàn)潛在的 bug、未使用的代碼、重復(fù)的代碼、循環(huán)體創(chuàng)建新對(duì)象等問題。另外,PMD 還可以和多種?IDE 進(jìn)行集成。
Checkstyle?是針對(duì) Java?代碼風(fēng)格的檢查工具,它偏重于代碼編寫格式的檢查,包括?Javadoc?注釋、命名約定、標(biāo)題、Import?語(yǔ)句、修飾符等。
靜態(tài)測(cè)試報(bào)告的自動(dòng)生成
在實(shí)際使用中,代碼分析工具一般通過各自的插件集成到?IDE(Elipse、IntelliJ DEA、Pycharm等)環(huán)境中,開發(fā)人員在提交代碼前會(huì)對(duì)代碼進(jìn)行實(shí)時(shí)的靜態(tài)測(cè)試。如圖?1?所示,在?IDEA中安裝了?3?個(gè)代碼分析插件:SonarLint、Checkstyle?和?PMD。其中,PMD?和?Checkstyle?可以添加工具自帶的代碼規(guī)則,以及團(tuán)隊(duì)自定義的代碼規(guī)則。
圖?1 IDEA?中添加代碼分析工具的插件
在?IDEA?中選擇需要分析的源文件和分析工具,就可以得到如圖?2?所示的代碼分析結(jié)果。
圖?2 代碼分析結(jié)果
SonarLint?一般作為?IDE?的插件,用于開發(fā)人員進(jìn)行本地的代碼分析,以便在編程中及時(shí)發(fā)現(xiàn)問題、及時(shí)修改,以確保代碼?push?到代碼庫(kù)前的代碼質(zhì)量,如圖?3?所示。
圖3 IDEA 中的 SonarLint 插件
SonarLint?可以和?SonarQube?集成,從而擁有更加豐富的代碼規(guī)則集,而且在代碼掃描分析完之后,其測(cè)試結(jié)果會(huì)上傳到?SonarQube?服務(wù)器上,如圖 4 所示,它以直觀的可視化界面來(lái)展現(xiàn)代碼質(zhì)量及單元測(cè)試覆蓋率。雙擊顯示頁(yè)面上的某個(gè)數(shù)字,就可以查看具體的信息等內(nèi)容。
圖?4 SonarQube 的測(cè)試報(bào)告
靜態(tài)分析工具和?CI?調(diào)度工具的集成讓靜態(tài)測(cè)試成為持續(xù)集成的一部分,如果我們要讓靜態(tài)測(cè)試和 Jenkins 集成,就需要用到?SonarQube Scanners,實(shí)現(xiàn)代碼自動(dòng)掃描并上傳報(bào)告到?SonarQube,這也是目前比較主流的應(yīng)用方式。也就是說(shuō), SonarQube Scanners?依據(jù)?SonarQube?服務(wù)器中的代碼規(guī)則庫(kù)進(jìn)行遠(yuǎn)程代碼分析,而且可以和構(gòu)建工具?Gradle、Maven、Azure DevOps 等集成。
圖?5?就描述了這種?CI?環(huán)境中代碼分析的工作流程。開發(fā)人員在本地開發(fā)代碼并利用?SonarLint?進(jìn)行實(shí)時(shí)代碼分析,然后將代碼?push?到代碼倉(cāng)庫(kù)中,觸發(fā)持續(xù)構(gòu)建,之后采用?SonarQube Scanners?進(jìn)行代碼分析,持續(xù)集成結(jié)束后將代碼分析結(jié)果發(fā)布到?SonarQube?服務(wù)器以呈現(xiàn)測(cè)試報(bào)告。SonarQube?服務(wù)器將代碼規(guī)則集和分析結(jié)果存儲(chǔ)在數(shù)據(jù)庫(kù)中,缺陷則提交給開發(fā)人員。
圖?5 SonarQube 在 CI 環(huán)境中的集成
下面是?Jenkins?流水線腳本示例,構(gòu)建過程包括編譯、部署、單元測(cè)試、代碼覆蓋率分析等,這些過程完成之后,Jenkins 會(huì)自動(dòng)調(diào)用?sonarQube Scanners?執(zhí)行代碼靜態(tài)測(cè)試,測(cè)試報(bào)告會(huì)自動(dòng)上傳到?sonaQube?的界面上。
自動(dòng)化測(cè)試報(bào)告的自動(dòng)生成
除了單元測(cè)試和代碼靜態(tài)測(cè)試,BVT、回歸測(cè)試、性能測(cè)試等自動(dòng)化測(cè)試也可以在?CI?環(huán)境中自動(dòng)觸發(fā)測(cè)試活動(dòng)并生成測(cè)試報(bào)告。
下面的?Jenkins?流水線腳本給出了調(diào)用?Robot Framework?進(jìn)行自動(dòng)化測(cè)試的示例。當(dāng)然,你需要在?Jenkins?里安裝相應(yīng)的?Robot Framework?插件。
Jenkins?可以生成?HTML?格式的報(bào)告,就像上面腳本里定義的。但是要得到更加美觀的報(bào)告則需要集成第三方的測(cè)試報(bào)告生成工具。報(bào)告的生成有兩種方式:
在?Jenkins?中集成測(cè)試報(bào)告生成工具然后自動(dòng)生成報(bào)告;
在自動(dòng)化測(cè)試框架中實(shí)現(xiàn)自定義的測(cè)試報(bào)告生成功能模塊,然后通過?Jenkins?和測(cè)試框架的集成生成測(cè)試報(bào)告。
先說(shuō)第?1?種方式,首先我們介紹兩個(gè)測(cè)試報(bào)告生成的工具,即 Grafana?和?Allure2。
Grafana?是一款用?Go?語(yǔ)言編寫的開源框架,它通過對(duì)采集數(shù)據(jù)的查詢,以可視化的方式展現(xiàn)大規(guī)模的指標(biāo)數(shù)據(jù),是目前網(wǎng)絡(luò)架構(gòu)和應(yīng)用分析中流行的時(shí)序數(shù)據(jù)(指帶有時(shí)間戳的數(shù)據(jù))展示工具。
Grafana?可以關(guān)聯(lián)多種數(shù)據(jù)源,比如?MySQL、InfluxDB(開源分布式時(shí)序數(shù)據(jù)庫(kù))等。在 Jenkins?中安裝?InfluxDB?插件后,將每次構(gòu)建的信息存入數(shù)據(jù)庫(kù),就可以發(fā)送到?Grafana,按照時(shí)間順序展示測(cè)試結(jié)果,包括由單元代碼覆蓋率統(tǒng)計(jì)工具和代碼分析工具生成的結(jié)果。同時(shí),利用?Grafana?可以建立測(cè)試結(jié)果和測(cè)試指標(biāo)的實(shí)時(shí)監(jiān)控面板,圖?6?展示了?Jenkins?中多個(gè)流水線部署管道每次構(gòu)建后的代碼覆蓋率。
圖?6 Grafana?展示的代碼覆蓋率
順便提一下,Grafana 的功能還不止如此,把它集成在部署流水線中,可以幫助我們實(shí)時(shí)呈現(xiàn)、監(jiān)控?Kubernetes?容器集群的負(fù)載情況,包括集群?Pod、CPU、內(nèi)存和外部存儲(chǔ)等使用狀態(tài),如圖?7?所示。
圖7 ?Grafana?監(jiān)控?Kubernetes?集群負(fù)載
另一款比較優(yōu)秀的測(cè)試報(bào)告框架是?Allure2,它可以提供如圖?8?所示的比較美觀的測(cè)試結(jié)果概覽,而且可以查看每個(gè)測(cè)試用例的測(cè)試結(jié)果、測(cè)試用例的描述等。
圖?8 Allure 生成的測(cè)試報(bào)告 Overview
下面的?Jenkins?流水線腳本給出了自動(dòng)化回歸測(cè)試之后?Allure?自動(dòng)生成的測(cè)試報(bào)告示例。腳本定義只有在測(cè)試失敗時(shí)才會(huì)用郵件通知相關(guān)人員,但每次都會(huì)生成?Allure?測(cè)試報(bào)告,Allure?報(bào)告的鏈接會(huì)顯示在?Jenkins?管理界面上。具體的配置方法你可以自己學(xué)習(xí)。
用戶自定義的測(cè)試報(bào)告
只要把?Allure?這樣的測(cè)試報(bào)告框架和?CI?環(huán)境進(jìn)行集成,就可以自動(dòng)生成比較美觀的測(cè)試報(bào)告。如果團(tuán)隊(duì)需要自定義的測(cè)試報(bào)告以滿足進(jìn)一步的需求,Allure?還可以提供與自動(dòng)化測(cè)試框架的集成,通過在測(cè)試腳本中添加?Allure?注解比如?@Story、@Issue、@Attachment,來(lái)實(shí)現(xiàn)測(cè)試報(bào)告的定制,這些功能包括關(guān)聯(lián)用戶故事、關(guān)聯(lián)測(cè)試用例、定義測(cè)試用例級(jí)別、關(guān)聯(lián)缺陷、為失敗用例添加 UI 界面的截圖等。
另外還有?ExtentReports,它也是一款可以和多個(gè)自動(dòng)化測(cè)試框架集成,從而實(shí)現(xiàn)定制化測(cè)試報(bào)告的框架。圖?9?展示了?ExtendReport?和測(cè)試框架集成后生成的自定義?HTML?報(bào)告,來(lái)自我公眾號(hào)里的一篇文章,介紹了基于?Spock?的測(cè)試自動(dòng)化框架,有興趣的可以去看看。
圖?9 ?ExtentReports 生成的自定義測(cè)試報(bào)告
這部分內(nèi)容就介紹到這里了,下面我簡(jiǎn)單總結(jié)一下這一講的內(nèi)容:
代碼的靜態(tài)測(cè)試可以有效提高代碼質(zhì)量,合適的靜態(tài)測(cè)試工具有?PMD、Splint、Pylint?或 SonarLint;
靜態(tài)測(cè)試工具與?CI?環(huán)境集成后可以自動(dòng)生成代碼分析報(bào)告并讓結(jié)果和缺陷信息可視化;
介紹了?3?種測(cè)試報(bào)告框架,即 Allure、ExtendReport?和?Grafana,前兩個(gè)和自動(dòng)化測(cè)試框架集成可以實(shí)現(xiàn)用戶自定義的測(cè)試報(bào)告。
最后給你留兩道思考題:你還知道有哪些用于生成測(cè)試報(bào)告的開源框架嗎?平時(shí)希望生成怎樣的測(cè)試報(bào)告?歡迎留言參與討論。
第19講:搭建敏捷自動(dòng)化測(cè)試框架及其案例分析
在前幾講已經(jīng)介紹了虛擬化技術(shù)、CI/CD 環(huán)境、DevOps 下的基礎(chǔ)設(shè)施及自動(dòng)部署、BVT 等,而上一講介紹了靜態(tài)測(cè)試技術(shù)和工具,這一講將側(cè)重介紹動(dòng)態(tài)測(cè)試工具,從而形成一個(gè)完整的測(cè)試基礎(chǔ)設(shè)施的體系。
如果只是討論工具,感覺不夠恰當(dāng),所以會(huì)提升到自動(dòng)化測(cè)試框架這個(gè)層次上。因?yàn)楣ぞ吆芏?#xff0c;變化也很快,而且換工具是比較容易的,今天喜歡這個(gè)工具,就用這個(gè),明天有更好的工具,就可能想換了。經(jīng)常望著這山比那山高、頻繁換工具,也是不合適的,因?yàn)閳F(tuán)隊(duì)已經(jīng)熟練使用工具并積累了良好的經(jīng)驗(yàn),與工具聯(lián)系在一起的腳本值得繼承,這些無(wú)形資產(chǎn)都值得保護(hù)。
自動(dòng)化測(cè)試框架是測(cè)試基礎(chǔ)設(shè)施的核心部分,不僅提供了各種測(cè)試服務(wù),比如測(cè)試腳本的開發(fā)、執(zhí)行、調(diào)試和管理,測(cè)試過程的管理、測(cè)試資源的管理,以及支持不同類型的測(cè)試(比如性能測(cè)試、安全性測(cè)試、易用性測(cè)試等)執(zhí)行與分析,而且也希望基于這個(gè)框架,讓測(cè)試與開發(fā)平臺(tái)、CI/CD 環(huán)境更加融合,構(gòu)建更高效的研發(fā)平臺(tái)。
自動(dòng)化測(cè)試框架的構(gòu)成
可以設(shè)想一下自動(dòng)化測(cè)試開發(fā)與執(zhí)行的場(chǎng)景:首先,研發(fā)人員根據(jù)測(cè)試任務(wù)的要求,開發(fā)和調(diào)試自動(dòng)化測(cè)試腳本,并能基于腳本和測(cè)試環(huán)境組合成測(cè)試任務(wù),在下班前預(yù)先安排好測(cè)試任務(wù),比如在某個(gè) Web 頁(yè)面上提交測(cè)試任務(wù),而這些任務(wù)能夠在當(dāng)晚自動(dòng)執(zhí)行,第二天我們一上班就可以查看測(cè)試結(jié)果或?yàn)g覽測(cè)試報(bào)告。如果晚上執(zhí)行不順利,系統(tǒng)則會(huì)發(fā)消息或郵件給相關(guān)人員,讓我們檢查并處理存在的問題,使得測(cè)試能夠繼續(xù)跑下去。當(dāng)然,如果測(cè)試都在半夜執(zhí)行,不適合人工干預(yù),那就增加一些異常處理機(jī)制、重試機(jī)制來(lái)自動(dòng)處理這類問題。
這種測(cè)試任務(wù)能夠按某種機(jī)制(比如定時(shí)機(jī)制、版本構(gòu)建成功后消息觸發(fā)機(jī)制等)自動(dòng)啟動(dòng)執(zhí)行,而且需要自動(dòng)發(fā)現(xiàn)可用的測(cè)試資源來(lái)執(zhí)行測(cè)試任務(wù),這依賴于資源監(jiān)控和調(diào)度工具 或 平臺(tái)來(lái)完成,并借助代理獲得機(jī)器狀態(tài)、運(yùn)行測(cè)試工具和將測(cè)試日志發(fā)送到特定服務(wù)器上以供分析。
為此,我們需要構(gòu)建一個(gè)自己的自動(dòng)化測(cè)試框架,能夠集成測(cè)試腳本開發(fā)環(huán)境、測(cè)試執(zhí)行引擎、測(cè)試資源管理、測(cè)試報(bào)告生產(chǎn)器、函數(shù)庫(kù)、測(cè)試數(shù)據(jù)源和其他可復(fù)用模塊等為一體,而且還可以靈活地集成其他各種測(cè)試工具,包括單元測(cè)試工具、API 測(cè)試工具和 UI 測(cè)試工具等。不同于工具,框架只是實(shí)現(xiàn)一個(gè)架構(gòu),用戶可以根據(jù)自己的需求進(jìn)行填充,比如進(jìn)行二次開發(fā)增加具體、特定的功能,還可以集成其他不同的測(cè)試工具。圖1就展示了自動(dòng)化測(cè)試框架的邏輯結(jié)構(gòu),由多個(gè)組件構(gòu)成。
? ?
圖1 ?自動(dòng)化測(cè)試框架的基本構(gòu)成
Harness/IDE:TA 框架的核心,相當(dāng)于“夾具”,框架的其它組成部分都能與之集成,而且具有腳本的創(chuàng)建、編輯、調(diào)試和管理等功能。
TA 腳本的管理,包括公共腳本庫(kù)、項(xiàng)目歸類的腳本庫(kù),這部分可以與 GitHub 這類(代碼庫(kù))配置管理工具集成。
測(cè)試資源管理:增加、刪除和配置相應(yīng)的測(cè)試設(shè)備(軟硬件資源),并根據(jù)它們的使用狀態(tài)來(lái)分配測(cè)試資源,這部分可以和容器管理工具集成。
測(cè)試數(shù)據(jù)管理:測(cè)試數(shù)據(jù)的自動(dòng)生成、存儲(chǔ)、備份和恢復(fù)等,也可以演化成一個(gè)數(shù)據(jù)平臺(tái),甚至是數(shù)據(jù)中臺(tái)。
開放的接口:提供給其他 CI 環(huán)境或其他測(cè)試環(huán)境的集成接口,這種接口以 API 形式提供,類似之前提到的“基礎(chǔ)設(shè)施即代碼”的概念。
代理(Agents):負(fù)責(zé) Harness 與工具的通信,控制測(cè)試工具的運(yùn)行。
任務(wù)安排(Scheduler):安排和提交定時(shí)任務(wù)、事件觸發(fā)任務(wù)等,以便實(shí)現(xiàn)無(wú)人值守的自動(dòng)化測(cè)試執(zhí)行。
數(shù)據(jù)統(tǒng)計(jì)分析:針對(duì)測(cè)試結(jié)果(含測(cè)試工具運(yùn)行產(chǎn)生的日志),生成可讀性良好的測(cè)試報(bào)告(如 HTML 格式的測(cè)試結(jié)果),如上一講提到的 SonarQube、Allure2 等。
自動(dòng)化測(cè)試框架能夠與 CI 環(huán)境、配置管理系統(tǒng)和缺陷管理系統(tǒng)等集成起來(lái),持續(xù)構(gòu)建后直接觸發(fā) BVT、后續(xù)的深度自動(dòng)化測(cè)試。這種集成,不僅發(fā)生在單元測(cè)試、接口層次上,而且還可以在系統(tǒng)層面、業(yè)務(wù)層面的測(cè)試。下面我們就介紹不同層次的自動(dòng)化測(cè)試框架。
自動(dòng)化測(cè)試框架的分類
結(jié)合前面分層自動(dòng)化測(cè)試策略——金字塔模型來(lái)劃分自動(dòng)化測(cè)試框架更合適一些,從單元測(cè)試、接口測(cè)試再到 UI 層、ATDD/BDD 的自動(dòng)化測(cè)試框架。
單元測(cè)試框架,由 JUnit 演化成單元測(cè)試框架家族 xUnit 最具代表性,形成了單元測(cè)試的基本規(guī)則,包含了面向各種編程語(yǔ)言的框架,比如 JUnit、CppUnit、NUnit、PyUnit、JsUnit、QUnit、DBUnit、HttpUnit 等。JavaScript 語(yǔ)言,也有一些其他的測(cè)試框架,比如 Jasmine、Mocha、Buster.js、DaleJS、PhantomJS、TestSwarm、JsTestDriver 等。
接口測(cè)試框架,比如 HttpRunner、Karate、APIfortress、Swagger 等。從框架的角度看,JMeter、SoapUI、Postman、PyTest、APIAutoTest 等算接口測(cè)試工具,還不能算框架,而 REST Assured 通常也算 API 框架,它更是為了簡(jiǎn)化基于 REST 服務(wù)的測(cè)試而建立的 Java 領(lǐng)域特定語(yǔ)言(DSL),但將它和 JUnit 集成起來(lái),如同 APIAutoTest +TestNG + HttpClient、Unittest + Request + HTMLRunner 等集成,也可形成接口測(cè)試框架。Robot Framework 和 Requests 庫(kù)集成起來(lái),也能執(zhí)行 API 的測(cè)試。
UI 自動(dòng)化測(cè)試框架,比如面向 Web 的 Selenium + WebDriver、TestCafe 和 Cypress,面向移動(dòng) App 的 Appium,面向 Windows 客戶端軟件的 AutoIT 等。移動(dòng) App 還有更多的自動(dòng)化測(cè)試框架,比如基于 Android 的 TA 框架 Robotium、Selendroid、ATAF 等,基于 iOS 的 TA 框架 KIF、Kiwi 等,以及跨平臺(tái)的 Ranorex Studio、Calabash 等。
ATDD/BDD 自動(dòng)化測(cè)試框架:Robot Framework、Ginkgo、Cucumber、JBehave/ NBehave / CBehave、SpecFlow、RSpec、JDave、Chakram(REST API)、Concordion、Fitnesse、Guage 等。
在敏捷測(cè)試中,更推薦單元測(cè)試和基于接口的自動(dòng)化測(cè)試,如果再進(jìn)一步,ATDD 和 BDD 也是敏捷測(cè)試中所推薦的,是更為徹底的自動(dòng)化,即讓需求可執(zhí)行,將需求變成真正的活文檔。而基于 UI 的自動(dòng)化測(cè)試框架更適合傳統(tǒng)的開發(fā),或者說(shuō)不是為敏捷測(cè)試而生,所以我們重點(diǎn)會(huì)關(guān)注單元測(cè)試和基于接口的測(cè)試、支持 ATDD/BDD 的驗(yàn)收測(cè)試等三類自動(dòng)化測(cè)試框架。下面將從這三類框架中各拿出一個(gè)工具,做進(jìn)一步的案例分析。
單元測(cè)試框架 JUnit 5
先說(shuō)單元測(cè)試框架。談起單元測(cè)試框架,不得不介紹 JUnit,它是最為經(jīng)典的自動(dòng)化測(cè)試框架,也成為了事實(shí)上的單元測(cè)試框架的業(yè)界標(biāo)準(zhǔn)。JUnit 最新版本是 JUnit 5,它不再是一個(gè)單一的 jar 包,而是由 JUnit platform(平臺(tái))、Jupiter(木星)、Vintage 等三部分組成,如圖 2 所示,其顯著的新特性有擴(kuò)展模型、嵌套測(cè)試、條件測(cè)試、參數(shù)化測(cè)試等。
? ?
圖2 ?JUnit 5 架構(gòu)示意圖
JUnit platform,其主要作用是在 JVM 上啟動(dòng)測(cè)試框架,包含一個(gè)內(nèi)部的 JUnit 公共庫(kù)以及用于測(cè)試引擎、配置和啟動(dòng)測(cè)試計(jì)劃、配置測(cè)試套件的注釋等公共 API,同時(shí)還支持通過控制臺(tái)(Console Launcher)命令、IDE 或構(gòu)建工具 Gradle、Maven(即借助 surefire-provider、gradle-plugin)等來(lái)啟動(dòng)測(cè)試。
JUnit Jupiter,包含了 JUnit5 最新的編程模型(注釋、類、方法)和擴(kuò)展機(jī)制的組合(Jupiter API)和一個(gè)測(cè)試引擎(Test Engine),用于編寫和執(zhí)行 JUnit 5 的新測(cè)試,其中 junit-jupiter-params 為參數(shù)化測(cè)試提供支持。
JUnit Vintage,一個(gè)測(cè)試引擎,允許在平臺(tái)上運(yùn)行老的 JUnit 3 和 JUnit 4 測(cè)試用例,從而確保必要的向后兼容性。
通過上面這張注釋列表,能感受到 JUnit 5 更強(qiáng)大的功能。例如,擴(kuò)展機(jī)制通過 @ExtendWith 定義,簡(jiǎn)單明了。
可以通過 @ParameterizedTest 來(lái)定義參數(shù)化測(cè)試方法,而且還可以和其他注釋組合使用,指定多個(gè)來(lái)源,包括 @ValueSource、@MethodSource、@CsvSource、@ArgumentSource 等。
? ? ??
API 層的 TA 測(cè)試框架 Karate
API 層的自動(dòng)化測(cè)試框架,如上所列,也有很多,要選擇適合自己的框架,也不是容易的事情,可以選擇自己熟悉的工具,比如 HttpRunner、JMeter、Postman 等。這里介紹一個(gè)由 Intuit 公司開發(fā)并開源的 API 測(cè)試框架 Karate,它不僅提供了源代碼,而且還提供了比較完整的文檔和演示實(shí)例,值得關(guān)注。這個(gè)框架,官方列出了 30 多個(gè)優(yōu)點(diǎn)(特性),這里從中選出十大優(yōu)點(diǎn),供參考。
(1)純文本腳本,可以調(diào)用其他腳本,能調(diào)用 JDK 類、Java 庫(kù),并具有嵌入式 JavaScript 引擎,可構(gòu)建適合特定環(huán)境的、可重復(fù)使用的功能庫(kù),具有良好的可擴(kuò)展性。
(2)標(biāo)準(zhǔn)的 Java / Maven 項(xiàng)目結(jié)構(gòu),以及與 CI / CD 管道的無(wú)縫集成,并支持 JUnit 5。
(3)優(yōu)雅的 DSL 語(yǔ)法原生地支持 JSON 和 XML,包括 JsonPath 和 XPath 表達(dá)式,覆蓋數(shù)據(jù)的輸入和結(jié)果的輸出。
(4)基于流行的 Cucumber / Gherkin 標(biāo)準(zhǔn),支持 BDD(Cucumber 場(chǎng)景 Scenario Outline 表),并內(nèi)置與 Cucumber 兼容的測(cè)試報(bào)告。
(5)內(nèi)置對(duì)數(shù)據(jù)驅(qū)動(dòng)測(cè)試的支持,原生支持讀取 YAML 甚至 CSV 文件,并能夠標(biāo)記或分組測(cè)試,其場(chǎng)景數(shù)據(jù)支持友好的 JSON、XML 或其獨(dú)有的 payload 生成器方法。
(6)全面的斷言功能,容易定位故障,清楚地報(bào)告哪個(gè)數(shù)據(jù)元素(和路徑)與預(yù)期不符。
(7)多線程并行執(zhí)行,內(nèi)置分布式測(cè)試功能,可用于 API 測(cè)試而無(wú)需任何復(fù)雜的“網(wǎng)格”基礎(chǔ)架構(gòu),從而顯著節(jié)省測(cè)試時(shí)間,簡(jiǎn)化測(cè)試環(huán)境準(zhǔn)備工作。
(8)API mocks?or test-doubles 甚至可以在多個(gè)調(diào)用之間維持 CRUD 的“狀態(tài)”,從而支持微服務(wù)和消費(fèi)者驅(qū)動(dòng)的契約測(cè)試。
(9)模擬 HTTP Servlet,可以測(cè)試任何控制器 Servlet,例如,Spring Boot / MVC 或 Jersey / JAX-RS- 無(wú)需啟動(dòng)應(yīng)用程序服務(wù)器,可以使用未更改的 HTTP 集成測(cè)試。
(10)全面支持不同類型的 HTTP 調(diào)用:
SOAP / XML 請(qǐng)求
HTTPS / SSL,不需要證書、密鑰庫(kù)等
HTTP 代理服務(wù)器
URL 編碼的 HTML 表單數(shù)據(jù)
Multi-part?文件上傳、Cookie 處理的支持
HTTP ?head、路徑和查詢參數(shù)的完全控制
WebSocket 支持
這里展示了一個(gè)簡(jiǎn)單的 WebSocket 測(cè)試示例,用到了 Given-When-Then 這種 BDD 的場(chǎng)景描述方式。
??
驗(yàn)收測(cè)試框架 Ginkgo
最后來(lái)分析一個(gè)驗(yàn)收測(cè)試的自動(dòng)化測(cè)試框架,比較著名的有前面提到的 Cucumber 和 Robot Framework,今天介紹一個(gè)用 Go 語(yǔ)言開發(fā)的框架 Ginkgo(銀杏),它對(duì) BDD?有很好地支持,擁有自己的 DSL,包括嵌套的 Describe、Context 和 When 容器模塊,BeforeEach / AfterEach、BeforeSuite / AfterSuite、It / Specify 等也一應(yīng)俱全,這樣就能幫助我們組織和編排測(cè)試用例了。
先上一個(gè)例子,讓你感受一下,測(cè)試用例的業(yè)務(wù)場(chǎng)景是多么清晰、腳本的可讀性多么良好,這會(huì)大大降低腳本后期的維護(hù)成本。?
Go 語(yǔ)言擅長(zhǎng)并行處理,Ginkgo 并行執(zhí)行能力也就是原生的能力,實(shí)現(xiàn)了進(jìn)程級(jí)并行執(zhí)行測(cè)試的能力,既節(jié)省時(shí)間,穩(wěn)定性也大大提高,也特別適合現(xiàn)在流行的容器環(huán)境,一個(gè)容器跑一個(gè)進(jìn)程,可以直接在每個(gè)容器上運(yùn)行命令 ginkgo -p 來(lái)執(zhí)行測(cè)試。而且,ginkgo CLI 工具在并行執(zhí)行測(cè)試時(shí),會(huì)起一個(gè)監(jiān)聽隨機(jī)端口的服務(wù)來(lái)實(shí)現(xiàn)不同進(jìn)程之間的消息同步、日志和報(bào)告的聚合工作,從而輸出整齊漂亮的日志和測(cè)試報(bào)告。
下面給出 ginkgo 幾個(gè)命令,可以看出:非常方便地實(shí)現(xiàn)并行執(zhí)行、代碼覆蓋率度量和 XUnit 測(cè)試包的轉(zhuǎn)換。
ginkgo -nodes = N 在N個(gè)并行進(jìn)程中運(yùn)行測(cè)試,并實(shí)時(shí)打印出一致的輸出
ginkgo -cover 使用Go的代碼覆蓋率工具運(yùn)行測(cè)試
ginkgo -coverprofile=FILENAME 指定覆蓋率文件名稱
ginkgo -outputdir=DIRECTORY 指定覆蓋率文件存放目錄
ginkgo convert將XUnit樣式的測(cè)試包轉(zhuǎn)換為Ginkgo樣式的包
通過 ginkgo build、ginkgo -notify 等命令,還能進(jìn)行測(cè)試服務(wù)分發(fā)、執(zhí)行工作流時(shí)實(shí)現(xiàn)消息通知,這樣很容易和 CI/CD(如 Jinkins)集成起來(lái),實(shí)現(xiàn)全流程的自動(dòng)化測(cè)試。通過 ginkgo bootstrap、ginkgo generate 可以創(chuàng)建測(cè)試集、測(cè)試用例模板,從而更好地實(shí)現(xiàn)測(cè)試復(fù)用。
ginkgo build PACKAGE_PATH編譯測(cè)試集成.test文件,可部署到其他地方執(zhí)行
ginkgo -notify 執(zhí)行完成后觸發(fā)通知,需要按照對(duì)應(yīng)插件
ginkgo -r ?遞歸執(zhí)行文件夾內(nèi)的所有測(cè)試用例
ginkgo bootstrap 創(chuàng)建測(cè)試集模板文件,會(huì)生成xxx_suite_test.go文件
ginkgo generate xxx 創(chuàng)建測(cè)試用例模板文件
Ginkgo 也支持第三方測(cè)試庫(kù):Gomock 和 Testify,還能和 Google Go 的 Agouti(基于瀏覽器的驗(yàn)收測(cè)試測(cè)試庫(kù))集成。
Ginkgo 借助 Gomega(匹配器 / 斷言庫(kù),是 Ginkgo BDD 測(cè)試框架的最佳搭檔)的 Eventually 和 Consistently 兩大功能提供了原生的異步支持,能大大降低死鎖或者未設(shè)置超時(shí)而異常卡住等問題的風(fēng)險(xiǎn),提升執(zhí)行的穩(wěn)定性,而且能夠減少?zèng)]必要的等待時(shí)間。
Eventually(func() []int {
? ?return thing.SliceImMonitoring
}, TIMEOUT, POLLING_INTERVAL).Should(HaveLen(2))
Consistently(func() []int {
? ?return thing.MemoryUsage()
}, DURATION, POLLING_INTERVAL).Should(BeNumerically("<", 10))
針對(duì)分布式系統(tǒng)進(jìn)行集成測(cè)試時(shí),這個(gè)功能也很有用。
externalProcess.DoSomethingAmazing()
Eventually(func() bool {
? ?return somethingAmazingHappened()
}).Should(BeTrue())
至此,完成了本講要討論的內(nèi)容,主要討論了自動(dòng)化測(cè)試框架的構(gòu)成與分類,并從中選了三個(gè)具有代表性的框架進(jìn)行了分析與展示,它們分別是單元測(cè)試框架 JUnit 5、API 層的 TA 測(cè)試框架Karate 和驗(yàn)收測(cè)試框架 Ginkgo。
最后留一個(gè)思考題,如果讓你在 Ginkgo 和 Robot Framework 中選擇一個(gè)框架,你會(huì)選擇哪一個(gè)?為什么?歡迎留言參與討論。
總結(jié)
以上是生活随笔為你收集整理的高效的敏捷测试第八课 静态测试工具和生成测试报告的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SAP 月末结账步骤
- 下一篇: Unity开发 Photon Pun 多