LoginSignup
3
1

GitHub Actionsでthree.jsの単体テスト

Last updated at Posted at 2021-09-22

はじめに

この記事は、GitHub Actions上でthree.jsの単体テスト方法を記録、共有するためのものです。

node.jsでWebGLを利用したコードを単体テストし、GitHub Actions上で処理します。ヘッドレスブラウザやelectronは使用しません。

想定する読者

この記事は、以下の読者を想定して書かれています。

  • JavaScriptの開発経験がある
  • Jestを使ったことがある
  • three.jsを使ったことがある
  • リポジトリをGitHubで管理している / 管理したい

JavaScriptの解説やJestのインストールガイドはこの記事には含まれません。

想定する環境

この記事は、以下の環境を想定して書かれています。記事を読む前に、お手元の環境をご確認ください。

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x, 20.x]

また、テスティングフレームワークはJestを利用します。

"devDependencies": {
  "jest": "^29.3.1",
}

先に結論だけ

GitHub Actionsでthree.jsを単体テストする最小限のリポジトリを作りました。

WebGLを利用した単体テスト

Jestはnode.jsで稼働するJavaScriptテスティングフレームワークです。Jestはjsdomという、JavaScriptで記述されたDOM実装と連携します。このjsdomを使ってCanvasを作成し、WebGLを利用するコードをテストします。

Jestでjsdomを利用する

Jestでjsdomを利用するには、まずJestとjest-environment-jsdomをインストールします。

npm i -D jest jest-environment-jsdom

次に設定ファイルを作成し環境にjsdomを指定します。

▼jest.config.js

module.exports = {
  testEnvironment: "jest-environment-jsdom",
};

もしくは、jestコマンドに--env=jest-environment-jsdomオプションを追加します。

▼package.json

"scripts": {
  "test": "jest --env=jest-environment-jsdom"
}

課題

jsdomは軽量化のため、標準設定ではCanvas要素をdiv要素で代用します。そのため、CanvasRenderingContext2DやWebGLRenderingContextはテストで使えません。

  • Canvas要素のサポート
  • WebGLRenderingContextのサポート

jsdomでWebGLをテストするためには、この2つの課題を解決しなければなりません。

Canvas要素のサポート

jsdomでCanvas要素をサポートするために、node-canvasを利用します。

npm install canvas --save-dev

jsdomはnode-canvasのインストールを自動で検知します。ユーザーがなにか設定をする必要はありません。

const canvas = document.createElement("canvas");

テストコード上でdocument.createElementを呼び出すと、node-canvasからCanvas要素が返されます。

WebGLRenderingContextのサポート

jsdomでWebGLRenderingContextをサポートするために、headless-glを利用します。headless-glはnode.js上でWebGLRenderingContextを作成するモジュールです。

npm install gl --save-dev

テストコードでは、以下のようにWebGLRenderingContextを生成します。

const gl = require('gl')(width, height)

width, heightには好きなサイズを指定できますが、THREE.WebGLRendererのsetSize関数で変更されてしまうため、最小限のサイズを指定します。

const gl = require('gl')(1, 1)

テストコードの作成 

node-canvasheadless-glを使ってテストを作成します。

▼./__test__/Test.spec.js

const THREE = require("three");

jest.spyOn(console, "error").mockImplementation()

describe("Test", () => {
    const canvas = document.createElement("canvas");

    test("2d context should be exist", () => {
        const context = canvas.getContext("2d");
        expect(context).toBeTruthy();
    })

    test("generate webgl context", ()=>{
        const gl = require("gl")(1,1);
        expect(gl).toBeTruthy();
    })

    test("generate webgl renderer", ()=>{
        const gl = require("gl")(1,1);
        const renderer = new THREE.WebGLRenderer({context:gl, canvas:canvas});
        renderer.setSize(640, 480);

        expect(renderer.getContext()).toBeTruthy();
        expect(renderer.getContext()).toBe(gl);
        expect(renderer.domElement.width).toBe(640);
    })
})

このテストで、以下の課題2点が確認できました。

  • Canvas要素のサポート
  • WebGLコンテキストのサポート

また、CanvasとWebGLコンテキストを利用してWebGLRendererが生成できました。

GitHub Actionsで実行する

ここまでで作成したテストは、そのままGitHub Actionsで動作しません。GitHub Actionsの仮想環境ubuntu-latestには、headless-glが依存するいくつかのパッケージが含まれていないためです。

headless-glはビルド済みのバイナリを配布していますが、2024/01/05の時点では、node.js v20向けのバイナリは配布されていません。node.js v20環境でテストを行う場合は、依存パッケージをaptからインストールし、ビルドしなければなりません。

    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: "npm"
      - run: sudo apt-get update
      - name: Install dependencies for headless-gl
        run: sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config
      # npm ciの途中で、headless-glのビルドが始まる
      - run: npm ci
      # npm testの実行直前に xvfb-run --auto-servernum で仮想フレームバッファーXvfbを起動
      - run: xvfb-run --auto-servernum npm test

各OSで必要とされるパッケージは、headless-glのREADMEを参照してください。

参考記事

以上、ありがとうございました。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1