大家好,本文介紹了3D引擎的測試方法,搭建了本地的測試環境。
上一篇博文
下一篇博文
了解自動化測試
對於引擎開發這種復雜、長期的項目,為了減少bug,提升長期的開發效率,自動化測試必不可少。在我們的Wonder.js引擎中,包括了本節介紹的3種自動化測試,測試覆蓋率達到了95%。
本系列為了節省篇幅,不進行自動化測試。因此本節只進行簡單的介紹,不給出實際的案例,讀者可以到Wonder.js->test/目錄下查看自動化測試實例。
單元測試
我們需要寫測試用例對單個函數進行單元測試。
搭建環境
使用jest作為測試框架,sinon進行stub。
如果讀者想了解stub的概念,可以參考我對Stub和Mock的理解
因為不能直接使用js庫,需要寫對應的FFI(類似於typescript的d.ts文件)才能在Reason中被調用,所以我們可以使用bs-jest和Wonder的Wonder-bs-sinon作為FFI
集成測試
相對於單元測試,集成測試的測試目標變為某個特性,該特性跨越多個函數或多個模塊。
搭建環境
與單元測試的環境一樣。
目錄結構
可以在test/unit/目錄下寫單元測試用例,而在test/integration/目錄下寫集成測試用例。
端對端測試
也稱為e2e測試,包括了“渲染測試”和“性能測試”。它們都需要安裝puppeteer,通過chrome內核渲染3D場景來進行測試。
- 渲染測試
渲染測試是針對特定的場景(如只有一個模型的場景,或者只有一個光源的場景)進行測試,從而保證渲染的正確性。
測試步驟為:
1、預先渲染一張正確圖片
2、使用引擎渲染一張當前圖片
3、逐個像素地比較兩者,如果95%以上的像素都相同,則測試通過;否則測試失敗
- 性能測試
性能測試是針對極端場景(如5000個box)進行測試,從而保證花費的時間和占用的內存大小符合要求。
測試步驟為:
1、預先准備基准數據
使用引擎運行場景多次,取平均值,記錄到json文件中
2、使用引擎運行場景多次(少於“准備基准數據”的運行次數),取平均值,得到當前數據
3、比較兩者的花費的時間和占用的內存大小,如果在誤差范圍內,則測試通過;否則測試失敗
注意事項:
只有在本地測試時,保持基准數據不變。如果在雲端(如在push到Github倉庫時使用CI工具-travis進行測試)或者其它環境(如換一台電腦進行測試)進行性能測試,需要在每次測試時更新基准數據(因為不同的環境,性能不一樣,所以對應的基准數據也不一樣)。
通過打印日志來調試
有以下的原因使得可以在單元測試和集成測試中通過打印日志來進行調試:
- 因為在自動化測試中打開watch,代碼修改后能夠立即刷新,所以能夠即時看到打印的結果,測試很方便
- 因為在函數式編程中,函數為純函數(Reason也允許非純),沒有狀態,所以我們可以通過打印函數的輸入和輸出,來驗證該函數是否正確
了解運行測試
本系列通過在Chrome瀏覽器中進行運行測試來驗證程序的正確性。
通過以下的方式進行運行測試:
斷點調試
因為瀏覽器運行的是Reason編譯后的js代碼,所以我們可以在瀏覽器的控制台->Sources中通過斷點來調試js代碼
具體可以參考:
使用斷點暫停代碼
通過Spector.js測試WebGL
Spector.js調試預覽:
Spector.js能查看一幀中WebGL的調用情況、shader代碼和WebGL的狀態,它支持WebGL 1.0或WebGL 2.0,也支持WebGL 1.0的VAO等擴展。
另外,Spector.js支持多個canvas,能查看指定的canvas對應的WebGL信息。這對於調試編輯器(如我們的Wonder-Editor在線編輯器)很有用。因為編輯器有多個canvas(如一個canvas進行主場景繪制,另一個canvas以材質球的方式顯示單個material資產的效果),而我們希望分別調試從每個canvas中取得上下文的WebGL。
Spector.js可以在Chrome的擴展中安裝,詳情請見官方Github
通過log調試Shader
本系列通過在fragment shader中,將變量作為輸出的顏色,來調試Shader的變量值。
更多可以參考:
調試OpenGL -> 調試着色器輸出
OpenGL ES 2.0 Shader 調試新思路(一): 改變提問方式
移動端測試
我們通過下面兩種方法進行測試:
- 模擬測試
我們可以在Chrome瀏覽器上,點擊控制台->Toggle Device Toolbar,打開用於模擬移動設備視口的界面。
本系列主要用該方法測試引擎對於移動端touch事件的支持。
詳細的介紹參考:
使用 Chrome DevTools 中的 Device Mode 模擬移動設備
- 真機測試
具體步驟如下:
1、在測試html頁面中引入vConsole庫
從而可以通過打印日志的方式,在手機上查看錯誤和日志信息
vConsole介紹參考:
前端開發 - 在手機上調試利器vConsole
2、把測試頁面push到測試環境的服務器上(如使用Github Pages搭建的服務器)
3、把測試頁面的訪問地址轉換為二維碼
如使用草料二維碼在線轉換
4、用測試手機的微信掃該二維碼,運行測試頁面,驗證渲染結果,查看錯誤和日志信息
了解性能測試
因為本系列開發的引擎重視性能,所以會通過手動的性能測試,來指導引擎優化。
性能測試的指標包括時間開銷和內存開銷,下面分別分析:
測試時間開銷
- 使用Chrome DevTools的Javascript Profiler
通過在測試頁面記錄profile,查看每個函數的時間開銷,從而定位到熱點函數進行優化。
相關資料可參考:
加速執行 JavaScript
Chrome DevTools 之 Profiles,深度性能優化必備
- 使用Chrome DevTools的Performance
通過時間線Timeline,可以查看CPU端各個線程和GPU的執行順序和熱點函數的時間開銷。
本系列主要用該方法測試在多線程中,每個線程的執行順序和性能開銷
相關資料可參考:
如何使用 Timeline 工具
Chrome DevTools 之 Timeline,快捷性能優化工具
- 使用Chrome DevTools的NetWork
查看各個資源的加載時間和順序。
本系列用該方法測試在“使用函數式反應式編程的流來異步加載 js、二進制文件等資源”時,各個資源的加載順序是否正確。
- 使用Performance.now
使用該方法打印某段邏輯的時間開銷,多用於自動化測試->端對端測試—>性能測試。
本系列在使用profile定位到熱點函數后,會使用該方法確定具體代碼的時間開銷。通過比較優化前和優化后的時間開銷,來評估優化的效果。
示例代碼為:
var n1 = performance.now();
執行某些邏輯
var n2 = performance.now();
//打印邏輯的時間開銷(ms為單位)
console.log(n2 - n1);
- 使用Console.profile
相對於Chrome DevTools的Javascript Profiler,該方法可以測試某一段邏輯的profile,而不是整個頁面的profile,粒度更小,更加可控。
(圖來自Chrome 控制台console的用法(學了之后對於調試js可是大大有用的哦))
測試內存開銷
- 使用Chrome DevTools的Memory
本系列對這個工具的應用:
使用Allocation sampling,定位內存占用的熱點函數;
使用Allocation instrumentation on timeline來比較每一幀內存開銷的增長情況,從而確定是否有內存泄漏。如果有內存泄漏,則通過Heap snapshot,記錄多個內存快照並進行比較,定位到具體是哪些地方增加了內存。
相關資料可參考:
解決內存問題
搭建本地測試環境
運行測試和性能測試不僅需要使用Chrome瀏覽器的控制台功能,還需要:
1、安裝Spector.js
Spector.js可以在Chrome的擴展中安裝
2、進行移動端測試時,需要在測試頁面中引入vConsole庫,並使用Github Pages搭建測試服務器