從0開發(fā)3D引擎(四):搭建測試環(huán)境
大家好,本文介紹了3D引擎的測試方法,搭建了本地的測試環(huán)境。
上一篇博文
從0開發(fā)3D引擎(三):搭建開發(fā)環(huán)境
下一篇博文
從0開發(fā)3D引擎(五):函數(shù)式編程及其在引擎中的應用
了解自動化測試
對于引擎開發(fā)這種復雜、長期的項目,為了減少bug,提升長期的開發(fā)效率,自動化測試必不可少。在我們的Wonder.js引擎中,包括了本節(jié)介紹的3種自動化測試,測試覆蓋率達到了95%。
本系列為了節(jié)省篇幅,不進行自動化測試。因此本節(jié)只進行簡單的介紹,不給出實際的案例,讀者可以到Wonder.js->test/目錄下查看自動化測試實例。
單元測試
我們需要寫測試用例對單個函數(shù)進行單元測試。
搭建環(huán)境
使用jest作為測試框架,sinon進行stub。
如果讀者想了解stub的概念,可以參考我對Stub和Mock的理解
因為不能直接使用js庫,需要寫對應的FFI(類似于typescript的d.ts文件)才能在Reason中被調(diào)用,所以我們可以使用bs-jest和Wonder的Wonder-bs-sinon作為FFI
集成測試
相對于單元測試,集成測試的測試目標變?yōu)槟硞€特性,該特性跨越多個函數(shù)或多個模塊。
搭建環(huán)境
與單元測試的環(huán)境一樣。
目錄結(jié)構(gòu)
可以在test/unit/目錄下寫單元測試用例,而在test/integration/目錄下寫集成測試用例。
端對端測試
也稱為e2e測試,包括了“渲染測試”和“性能測試”。它們都需要安裝puppeteer,通過chrome內(nèi)核渲染3D場景來進行測試。
- 渲染測試
渲染測試是針對特定的場景(如只有一個模型的場景,或者只有一個光源的場景)進行測試,從而保證渲染的正確性。
測試步驟為:
1、預先渲染一張正確圖片
2、使用引擎渲染一張當前圖片
3、逐個像素地比較兩者,如果95%以上的像素都相同,則測試通過;否則測試失敗
- 性能測試
性能測試是針對極端場景(如5000個box)進行測試,從而保證花費的時間和占用的內(nèi)存大小符合要求。
測試步驟為:
1、預先準備基準數(shù)據(jù)
使用引擎運行場景多次,取平均值,記錄到json文件中
2、使用引擎運行場景多次(少于“準備基準數(shù)據(jù)”的運行次數(shù)),取平均值,得到當前數(shù)據(jù)
3、比較兩者的花費的時間和占用的內(nèi)存大小,如果在誤差范圍內(nèi),則測試通過;否則測試失敗
注意事項:
只有在本地測試時,保持基準數(shù)據(jù)不變。如果在云端(如在push到Github倉庫時使用CI工具-travis進行測試)或者其它環(huán)境(如換一臺電腦進行測試)進行性能測試,需要在每次測試時更新基準數(shù)據(jù)(因為不同的環(huán)境,性能不一樣,所以對應的基準數(shù)據(jù)也不一樣)。
通過打印日志來調(diào)試
有以下的原因使得可以在單元測試和集成測試中通過打印日志來進行調(diào)試:
- 因為在自動化測試中打開watch,代碼修改后能夠立即刷新,所以能夠即時看到打印的結(jié)果,測試很方便
- 因為在函數(shù)式編程中,函數(shù)為純函數(shù)(Reason也允許非純),沒有狀態(tài),所以我們可以通過打印函數(shù)的輸入和輸出,來驗證該函數(shù)是否正確
了解運行測試
本系列通過在Chrome瀏覽器中進行運行測試來驗證程序的正確性。
通過以下的方式進行運行測試:
斷點調(diào)試
因為瀏覽器運行的是Reason編譯后的js代碼,所以我們可以在瀏覽器的控制臺->Sources中通過斷點來調(diào)試js代碼
具體可以參考:
使用斷點暫停代碼
通過Spector.js測試WebGL
Spector.js調(diào)試預覽:

Spector.js能查看一幀中WebGL的調(diào)用情況、shader代碼和WebGL的狀態(tài),它支持WebGL 1.0或WebGL 2.0,也支持WebGL 1.0的VAO等擴展。
另外,Spector.js支持多個canvas,能查看指定的canvas對應的WebGL信息。這對于調(diào)試編輯器(如我們的Wonder-Editor在線編輯器)很有用。因為編輯器有多個canvas(如一個canvas進行主場景繪制,另一個canvas以材質(zhì)球的方式顯示單個material資產(chǎn)的效果),而我們希望分別調(diào)試從每個canvas中取得上下文的WebGL。
Spector.js可以在Chrome的擴展中安裝,詳情請見官方Github
通過log調(diào)試Shader
本系列通過在fragment shader中,將變量作為輸出的顏色,來調(diào)試Shader的變量值。
更多可以參考:
調(diào)試OpenGL -> 調(diào)試著色器輸出
OpenGL ES 2.0 Shader 調(diào)試新思路(一): 改變提問方式
移動端測試
我們通過下面兩種方法進行測試:
- 模擬測試
我們可以在Chrome瀏覽器上,點擊控制臺->Toggle Device Toolbar,打開用于模擬移動設備視口的界面。
本系列主要用該方法測試引擎對于移動端touch事件的支持。
詳細的介紹參考:
使用 Chrome DevTools 中的 Device Mode 模擬移動設備
- 真機測試
具體步驟如下:
1、在測試html頁面中引入vConsole庫
從而可以通過打印日志的方式,在手機上查看錯誤和日志信息
vConsole介紹參考:
前端開發(fā) - 在手機上調(diào)試利器vConsole
2、把測試頁面push到測試環(huán)境的服務器上(如使用Github Pages搭建的服務器)
3、把測試頁面的訪問地址轉(zhuǎn)換為二維碼
如使用草料二維碼在線轉(zhuǎn)換
4、用測試手機的微信掃該二維碼,運行測試頁面,驗證渲染結(jié)果,查看錯誤和日志信息
了解性能測試
因為本系列開發(fā)的引擎重視性能,所以會通過手動的性能測試,來指導引擎優(yōu)化。
性能測試的指標包括時間開銷和內(nèi)存開銷,下面分別分析:
測試時間開銷
- 使用Chrome DevTools的Javascript Profiler
通過在測試頁面記錄profile,查看每個函數(shù)的時間開銷,從而定位到熱點函數(shù)進行優(yōu)化。
相關(guān)資料可參考:
加速執(zhí)行 JavaScript
Chrome DevTools 之 Profiles,深度性能優(yōu)化必備
- 使用Chrome DevTools的Performance
通過時間線Timeline,可以查看CPU端各個線程和GPU的執(zhí)行順序和熱點函數(shù)的時間開銷。
本系列主要用該方法測試在多線程中,每個線程的執(zhí)行順序和性能開銷
相關(guān)資料可參考:
如何使用 Timeline 工具
Chrome DevTools 之 Timeline,快捷性能優(yōu)化工具
- 使用Chrome DevTools的NetWork
查看各個資源的加載時間和順序。
本系列用該方法測試在“使用函數(shù)式反應式編程的流來異步加載 js、二進制文件等資源”時,各個資源的加載順序是否正確。
- 使用Performance.now
使用該方法打印某段邏輯的時間開銷,多用于自動化測試->端對端測試—>性能測試。
本系列在使用profile定位到熱點函數(shù)后,會使用該方法確定具體代碼的時間開銷。通過比較優(yōu)化前和優(yōu)化后的時間開銷,來評估優(yōu)化的效果。
示例代碼為:
var n1 = performance.now();
執(zhí)行某些邏輯
var n2 = performance.now();
//打印邏輯的時間開銷(ms為單位)
console.log(n2 - n1);
- 使用Console.profile
相對于Chrome DevTools的Javascript Profiler,該方法可以測試某一段邏輯的profile,而不是整個頁面的profile,粒度更小,更加可控。

(圖來自Chrome 控制臺console的用法(學了之后對于調(diào)試js可是大大有用的哦))
測試內(nèi)存開銷
- 使用Chrome DevTools的Memory
本系列對這個工具的應用:
使用Allocation sampling,定位內(nèi)存占用的熱點函數(shù);
使用Allocation instrumentation on timeline來比較每一幀內(nèi)存開銷的增長情況,從而確定是否有內(nèi)存泄漏。如果有內(nèi)存泄漏,則通過Heap snapshot,記錄多個內(nèi)存快照并進行比較,定位到具體是哪些地方增加了內(nèi)存。
相關(guān)資料可參考:
解決內(nèi)存問題
搭建本地測試環(huán)境
運行測試和性能測試不僅需要使用Chrome瀏覽器的控制臺功能,還需要:
1、安裝Spector.js
Spector.js可以在Chrome的擴展中安裝
2、進行移動端測試時,需要在測試頁面中引入vConsole庫,并使用Github Pages搭建測試服務器
浙公網(wǎng)安備 33010602011771號