移動端執行JS指令碼除錯方案-單元測試

語言: CN / TW / HK

theme: cyanosis

前言

前段時間寫了一篇關於移動端執行JS指令碼的文章記錄一次在移動端執行JS指令碼的試驗, 裡面提到關於除錯的部分:搭建一個Vue專案用於指令碼的除錯。但經過一段時間的實踐發現,該方案弊端較多: 1. 模組之間較難做整合。 2. 除錯是通過eval注入的指令碼打包產物,雖說也可在瀏覽器控制檯除錯,但不夠直接。(其實是移動端寫多了不太習慣在瀏覽器除錯。。。) 3. Vue畢竟與檢視有關聯,每次新增指令碼都需要編寫額外的Vue部分程式碼,增加了成本

說白了就是懶。。。所以針對除錯這件事,筆者重新思考了一下。JS指令碼的驗證主要分為兩個部分:邏輯正確環境適配。環境的話,只要JS引擎的適配性強,一般不會有大問題。畢竟最終還會使用Babel進行編譯,這也是借鑑前端開發的場景得出的結論。所以大部分問題會出現在邏輯上,再結合上面提到的問題,最後筆者打算通過Jest做一個由Typescript編寫的單元測試

Jest單元測試

流程

image.png 這裡將之前的瀏覽器層替換成了Jest單元測試。由於是模擬層,所以關於指令碼中需要原生注入的物件都會在單元測試中進行模擬。

Jest搭建

這裡筆者採用的是Jest + Babel + Typescript的結構。Babel負責Typescript的編譯,以及JS版本的轉換問題。

npm install jest @types/jest babel-jest --save-dev

npx jest --init

初始化後,會生成一個jest.config.js,用於Jest的配置,這裡沒有特殊的配置所以沒有修改。編譯過程中會自動讀取babel.config.js,如果測試與實際打包的Babel配置有區別則需要特別區分。更多的資訊可以檢視Jest文件

簡單的測試程式碼

Jest環境就緒後,就需要一個.(spec|test).ts的檔案作為單元測試的case檔案。以下是以上篇文章提到的Demo程式碼為基礎編寫的單元測試。這裡主要分為兩端的測試,Android、iOS。

```typescript describe('Test', () => { beforeEach(() => { jest.resetModules() });

test('Android', () => {
    process.env.OS = 'Android'

    // 模擬原生物件注入
    const dbObj = require('./exports/db').default
    dbObj.loadDB('./test/sqlite/test.db', 'database')

    const deviceInfoObj = require('./exports/deviceInfo').default
    deviceInfoObj.loadDeviceInfo('Android')

    // 注入指令碼
    require('../src/Test')

    // 指令碼內容執行
    const inferInterface = global['test']

    inferInterface.testFetchOne()

    dbObj.closeDB('database')
})

test('iOS', () => {
    process.env.OS = 'iOS'

    // 模擬原生物件注入
    const dbObj = require('./exports/db').default
    dbObj.loadDB('./test/sqlite/test.db', 'database')

    const deviceInfoObj = require('./exports/deviceInfo').default
    deviceInfoObj.loadDeviceInfo('iOS')

    // 注入指令碼
    require('../src/Test')

    // 指令碼內容執行
    const inferInterface = global['test']

    inferInterface.testFetchOne()

    dbObj.closeDB('database')
})

afterEach(() => {
    delete process.env.OS
})

}) ```

test函式可以理解為每個測試case,這裡分為Android、iOS。具體的流程就和移動端執行時大同小異了: 1. 原生物件注入(這裡是建立一個JS物件新增到global進行模擬)。 2. 注入指令碼(依賴指令碼程式碼)。 3. 指令碼內容執行。

ps:這裡沒有用太多Jest的api,具體細節可檢視Jest官方文件

執行效果:

在控制檯執行後,可檢視每個case的執行狀況,如果是出錯也會有對應的堆疊

image.png

image.png

結合VSCode

還可以結合VSCode進行斷點除錯

```json { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Jest", "program": "${workspaceFolder}/module-script/node_modules/.bin/jest", "args": [

        ],
        "cwd": "${workspaceRoot}/module-script", 
        "outputCapture": "std",
    }
]

} `` 建立一個launch.json`執行jest命令,接下來就能愉快的斷點除錯指令碼了。

最後

以上就是關於指令碼的單元測試內容。採用這種方式可以很好的解決隨指令碼複雜度提高帶來的除錯成本,也是比較符合移動端開發習慣的

最後再貼一下Demo地址:xcyoung/mobile-js-engine-exsample (github.com)